Only this pageAll pages
Powered by GitBook
1 of 61

UMA Protocol

Loading...

Loading...

Loading...

Developers

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Protocol Overview

Loading...

Loading...

Loading...

Loading...

Community

Loading...

Loading...

Loading...

Using UMA

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Verification Guide

Loading...

Loading...

Loading...

Loading...

Resources

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Welcome to UMA

A decentralized truth machine

An optimistic oracle (OO) that can record any verifiable truth or data onto a blockchain 🔮

UMA is an optimistic oracle and dispute arbitration system that securely allows for arbitrary types of data to be brought onchain. UMA’s oracle system provides verified onchain data for projects including:

  1. Crosschain bridge

  2. Prediction markets

  3. Insurance protocols

  4. Custom derivatives

UMA's optimistic oracle (OO) is designed to be modular and extensible with focus on building real-world use cases. Two main versions of the optimistic oracle (OO) are currently live: OOv2 and OOv3. Choosing the right one depends on your use case.


Core Concepts

Learn the fundamentals of UMA's optimistic oracle.

Correct Oracle for Your Use Case

UMA offers OOv2 and OOv3. Based on your idea and product, let's learn which one fits your use case best:

OOv2
OOv3

We understand that your product needs can be complex and would require a larger discussion on which optimistic oracle version to use. Feel free to reach out to us and get help.


Developer Quickstart

Having decided the correct optimistic oracle for your use case, let's now dive deeper into how you can ship apps powered by verifiable onchain truth using UMA's optimistic oracle.

OOv2 prioritizes protocols that need third-parties to propose answers to data requests.

Here are some app guides to help you build on UMA OOv2:

OOv3 prioritizes protocols that simply needs asserted data to be verified.

Here are some app guides to help you build on UMA OOv3:


Community

The UMA token secures UMA’s optimistic oracle through decentralized governance and economic guarantees against corruption. Token holders vote on upgrades, price requests, and disputes, earning rewards for honest participation.

UMA Improvement Proposals (UMIPs) are design documents used to propose changes to the UMA ecosystem. They are an important part of UMA's governance processes.

The UMA DAO accepts proposals for onchain actions that require tokenholders approval. An example would be a request for funding from the UMA treasury.


Resources and Support

We request all community members and developers to and gain instant help on any issues they face while voting or submitting proposals to UMA.

You can .

The security of our protocol is extremely crucial. If you notice any bugs in the protocol, . You can also find details of our .

Optimistic Oracle v2

This section showcases different design patterns for building contracts that integrate with the UMA Optimistic Oracle (OO). These include:

  • A simple deposit box to showcase the basic OO request lifecycle.

  • An event based prediction market. In this example, settlement requests are submitted at the time of contract deployment, and the OO proposer network is used as a decentralized keeper service that identifies when settlement events happen and propose the outcomes.

  • An , where an integrating contract handles proposals and state management, and only uses the OO when proposal verification is needed or a dispute is filed.

What's New!

Keep up with the latest updates to UMA’s Optimistic Oracle. This changelog covers new features, improvements, and important changes for developers and integrators.

May 8, 2025

1

Showing Polymarket Clarifications in the Voter dApp

We’ve updated the voter dApp to show Polymarket clarifications right within the dApp to ensure that all UMA voters have access to the same critical information before voting on disputes.

"internal Optimistic Oracle"

Integrations must submit data requests that can then be answered by third-party proposers.

Integrations submit assertions, where they propose data to their own request along with its parameters.

The specific parameters for proposers and disputers to follow must be included in the request.

The challenge period and dispute process remains the same.

Primary use cases: Prediction markets, sports betting applications, and insurance protocols.

Primary use cases: Crosschain infrastructure, content moderation, transaction verification.

here
join our discord server
find more support resources here
please report them here
audits here
Cover

Optimistic Oracle V2

Build prediction markets and insurance protocols

Cover

Optimistic Oracle V3

Build data asserters and escalation managers

Cover

Voting Walkthrough

Learn how to stake tokens, vote, and claim rewards

Cover

Prediction Market

Use OOv2 to identify and settle real-world events in prediction markets.

Cover

Insurance

Use OOv2 to verify and resolve claims in insurance applications.

Cover

Data Asserter

Use OOv3 to asserts arbitrary offchain data onchain through flexible assertions

Cover

Escalation Managers

Use OOv3 to enable modular functionality via custom escalation managers

Cover

Governance

Learn about UMA token, UMIPs and voting on UMA's DVM

Cover

UMIP Process

Learn how UMIPs propose changes to the UMA Ecosystem

Cover

DAO Proposals

Learn how you can submit onchain proposals to the UMA Ecosystem

2

Increased the Settlement Price Approval Threshold (SPAT)

The Settlement Price Approval Threshold (SPAT) is basically the level of agreement needed among voters to resolve a dispute. Before now, the OO used to accept a simple majority (50%+), which meant disputes could be resolved, even on rare occasions when opinions were pretty divided.

We’ve now raised SPAT to 65% to strengthen the required consensus for vote outcomes. If we don't hit that threshold, the vote "rolls" to another round, giving everyone time to reconsider and discuss until there’s a stronger community agreement.

3

Enhanced Voter Information and Warnings

We've added clear warnings and guidance for voters within the dApp to help voters understand that they have a responsibility to verify claims independently.

4

Improved Discussion Environment

We've updated how discussions are sorted in the voter dApp; instead of the initial chronological order where the earliest comments are seen first in the discussion pane, users can now sort from the most recent

5

Fixed PM Market Linking

We've resolved technical issues with links to Polymarket markets, ensuring voters can easily access the associated market information directly from the voter dApp. This provides crucial context about market odds and trading activity.

Using Blacklisting Tokens as Currency

Using a token that allows backlisting (e.g. USDC) as your currency opens up a griefing vector that integrators should be aware of.

The and functions allow the caller to set any address as the proposer and disputer that will receive payouts if their proposal/dispute is correct upon settlement. If a bad actor calls both and and specifies a blacklisted address for repayment, the function will revert and cause the request to be frozen unless the address is unblacklisted. This costs the malicious user 2 bonds and does not result in any gain, but freezing the request could cause issues for the integrator.

To avoid this, integrations that use tokens with blacklisting functionality should ensure that their admins can call a function that ignores the frozen request and creates a new OOV2 request. In this way they can prevent a frozen request from having any negative consequences to their protocol.

requestPrice
proposePriceFor
disputePriceFor
proposePriceFor
disputePriceFor
settle

Voting Gas Rebates

Risk Labs currently provides gas rebates for voters who have staked 1000 or more UMA to encourage more community members to participate in securing the Optimistic Oracle.

  • Rebates cover the gas cost for commit and reveal transactions and are denominated in ETH.

  • Voters must have at least 1000 UMA staked at the start of the commit period for that voting period's commit and reveal transactions to be rebated.

  • Commited votes must be revealed to be rebated.

  • If a voter commits more than once on a dispute, only the first commit will be rebated.

  • If a delegate address is used to vote, the rebate will be sent to the delegate address.

  • Rebates are calculated for one calendar month and are sent out within the first half of the following month. Announcements are made in the UMA Discord at the time each rebate is sent out.

Discord Summaries

LLM generated Discord discussion summaries warnings and information

The Voterdapp contains a "Discussion Summary" tab with an LLM summary of Discord comments on the vote. The summary removes duplicate arguments across all comments to give voters an overview of all arguments which is useful for long or spammed comment threads. The summary does not fact check comments, add additional arguments, or give voting recommendations.

Voters should always verify all arguments included in the summaries with their own research. The raw comments are also provided in the "Discord Comments" tab so voters can review them against the summary in case of LLM error.

Using Blacklisting Tokens as Currency

Using a token that allows backlisting (e.g. USDC) as your assertTruth currency opens up a griefing vector that integrators should be aware of.

The assertTruth and disputeAssertion functions allow the caller to set any address as the asserter and disputer that will receive payouts if their assertion/dispute is correct upon settlement. If a bad actor calls these functions and specifies a blacklisted address for repayment, the settle function will revert and cause the request to be frozen unless the address is unblacklisted. This costs malicious users their bonds and does not result in any gain, but freezing the assertion could cause issues for the integrator.

Integrations that use tokens with blacklisting functionality should ensure that they have a way to manage frozen assertions (e.g. an admin function that can ignore a frozen assertion) without negatively affecting their integration.

oSnap

Support for oSnap will be deprecated on December 15th, 2025. After this date, oSnap will not be able to execute transactions from your DAO’s Safe treasury.

oSnap integrations should take the following steps to prepare:

  • Ensure their Safe signers are prepared to sign and execute any necessary DAO transactions

  • Disable oSnap on all DAO treasuries by following these steps: https://docs.uma.xyz/developers/osnap/disabling-osnap

ManagedOptimisticOracleV2

The ManagedOptimisticOracleV2 contract is modified version of the OptimisticOracleV2 intended to be deployed for a single integration. It allows the integration to designate a request manager address that can set a default proposer whitelist and easily manage an existing request's bond size, liveness and proposer whitelist before the request has been proposed.

How does UMA's Oracle work?

UMA's Optimistic Oracle allows contracts to quickly request and receive data information. The Optimistic Oracle acts as a generalized escalation game between contracts that initiate a price request and UMA's dispute resolution system known as the Data Verification Mechanism (DVM). Prices proposed by the Optimistic Oracle will not be sent to the DVM unless it is disputed.

If a dispute is raised, a request is sent to the DVM. All contracts built on UMA use the DVM as a backstop to resolve disputes. Disputes sent to the DVM will be resolved within a few days - after UMA tokenholders vote on what the correct outcome should have been.

Optimistic Oracle

The first part of UMA's oracle system is the Optimistic Oracle. This is a layer that is designed to optimistically verify pieces of data quickly. It is secured by the UMA DVM, because disputes can be escalated from the Optimistic Oracle layer to the DVM for dispute arbitration. The main lifecycle of the OO looks like this, and is detailed in the Asserter and Disputer rows within the diagram above.

Default Proposer Whitelist

Risk Labs manages the default proposer whitelist for Polymarket's ManagedOptimisticOracleV2 contract. The current whitelist can be viewed and is subject to updates and changes in guidelines. Polymarket, as the request manager for the contract, may also change an unproposed request’s proposer whitelist at any time.

Current Proposer Whitelist Criteria

Proposer addresses must meet the two below criteria over the last 6 months:

  • 5 or more Polymarket proposals on OptimisticOracleV2 or ManagedOptimisticOracleV2

oSnap Proposal Verification

oSnap Proposal Verification with UMA's Optimistic Oracle

Verifying Proposals

After transactions have been requested for execution, the challenge period begins. The challenge period length is set by the oSnap Safe module advanced settings. Invalid requests must be disputed within the challenge period. oSnap requests can be reviewed in the 's Verify tab.

After selecting a request, a sidebar will show additional request details including the bond amount, when the challenge period ends, a dispute button (when a wallet is connected), a link to the corresponding Snapshot proposal, the oSnap rules that the request should be reviewed against (including minimum quorum and voting period for the Snapshot proposal), and links to relevant block explorer pages.

Disabling oSnap

Steps to remove oSnap from your DAO Snapshot space and Safe treasury

Requirements:

  • The below steps propose a Safe transaction to disable oSnap. Transactions can only be proposed to a Safe by that Safe's Signers or Proposers. You can view these roles on your Safe's settings page.

  • Executing the proposed Safe transaction requires your minimum number of Signers to sign the transaction and one Signer to execute the transaction.

Steps:

Additional Resources

Additional tutorials and resources about UMA that are not featured on this docs site

Internal Learning Sessions

Disputing Oracle Data

  1. Go to the , if you are disputing proposals on a live network like Ethereum, Optimism, or Polygon, or go to the if you are disputing test data on Görli. Disputes will be resolved by the if you are on a live network, or by a mock oracle if you are on Görli (see Resolving Disputes).

  2. Locate proposals under the Proposals tab for outstanding proposals that are within the challenge window and can be disputed.

  3. Click on the proposal you want to dispute.

Verification System

Human research and logic to secure valid Oracle requests

Prerequisites

Before getting into the specifics of how to verify proposals from the Optimistic Oracle, please make sure to go through the following resources to understand how UMA works:

ASSERT_TRUTH Deprecation

As of December 8th, 2025. is the intended default identifier to be used with OOV3. The original identifier will be deprecated as of December 15, 2025. These identifiers have teh same specifications and the change is only to break support for deprecated projects.

Please note: after these changes do not use the following OOV3 functions:

  • the assertTruthWithDefaults function will always revert as it hardcodes in the ASSERT_TRUTH identifier

  • the defaultIdentifier public constant variable will return the deprecated ASSERT_TRUTH identifier

Proposing via the Oracle Dapp

Viewing, proposing and disputing ManagedOptimisticOracleV2 requests on the Oracle Dapp is the same as other OptimisticOracleV2 requests except for the following differences:

  • If your connected address is not on the request's proposer whitelist, the propose button on the request's sidebar will be disabled.

  • The request's proposer whitelist is displayed under the "More Information" heading at the bottom of the request sidebar.

Links

Links

You can keep up to date with what is happening with UMA across our various social media platforms and community resources:

Unsupported Contracts

Risk Labs/UMA protocol no longer actively supports or improves:

  • The

  • The

These contracts are open-source code, and anyone is free to use, improve, or fork the code. However note that for these contracts to be safe, it requires a robust system of well capitalized off-chain watchers (liquidator & disputer bots) to continually check that positions are appropriately collateralized, or that positions are not being liquidated unfairly. Anyone using this code in production must ensure that there are well-capitalized liquidators and disputers running at all times; failure to do so could result in a loss of all locked funds. Risk Labs does not and will not run liquidators for these contracts, nor does it give any security assurances about any EMP or Perp contracts. As always, UMA protocol and Risk Labs will continue to support proposed addition or request of price identifiers for general use including within EMP/Perp contracts.

Voter Guide

Voting best practices and warnings

  • Read through the vote Description under the Details tab. Carefully review how the vote should resolve and if provided, the timing of when the request can resolve and any listed sources.

  • Review the Timestamp under the Details tab. This is the point in time at which the vote should be evaluated.

  • The vote Discussion tabs lists comments from the UMA Discord with arguments, resources, and suggested votes that may be helpful. However, some commenters may try to influence the vote for their own profit. Always ​independently verify​ any claims before relying on them.

Optimistic Oracle v3

This section showcases different design patterns for building contracts that integrate with the UMA Optimistic Oracle v3. These include:

  • A showcasing the simplest possible OOv3 integration contract.

  • Building example contracts:

Proposing Programmatically

Proposing and disputing ManagedOptimisticOracleV2 requests is largely the same as OptimisticOracleV2 requests with the following differences:

Adding the ManagedOptimisticOracleV2 Addresses

Programmatic proposers and disputers will be used to listening for OptimisticOracleV2 events and sending proposing and disputing transactions to these addresses. To add support to new ManagedOptimisticOracleV2 deployments, programmatic proposers and disputers will have to add these new deployment addresses to their bot configs.

Note: the first ManagedOptimisticOracleV2 deployment is managed by Polymarket and can be found .

For prediction market votes, it is helpful to review the market odds over time to sanity check your vote. The market odds after an event has expired are a reflection of how bettors with skin in the game think a market should resolve. You should not vote based on the market odds, but if you are planning on voting against strong market odds you may want to do extra research to ensure your vote is correct.

  • Proposal accuracy greater than 95% in the last 6 months.

  • How do I get on the whitelist?

    Propose OOV2 Polymarket requests that are not whitelisted to meet the criteria for the next update.

    When will the whitelist be updated?

    Updates are based on data pulled on the 2nd of each month for the preceding 6 months (e.g. June 2nd to December 2nd). The whitelist is updated within the following week.

    Are address removed from the whitelist?

    Yes, if a whitelisted address no longer meets the criteria of the most recent update it will be removed from the whitelist.

    here

    L2 Bridge Architecture

  • How to use Storybook

  • LM 2.0

  • Protected Tokens

  • KPI Options 2.0

  • Optimistic Governance

  • Introduction to using UMA's Optimistic Oracle

  • Introduction to Merkle Roots

  • UMA Call Options

  • Introduction to the LSP

  • Range Tokens

  • Validating an Across v2 Dispute
    Across v2 Architecture
    Optimistic Distributor

    Click the 'Connect wallet' button in the top right corner and go through the steps to connect your wallet. Confirm you are on the same network as the proposal.

  • Before disputing, confirm the details of the request and ancillary data to ensure the proposal is actually incorrect. You may also want to check the instructions in the UMIP for the identifier.

  • Click the 'Dispute Proposal' button.

  • Confirm the transaction details through your wallet provider. After confirming, the proposal will be disputed.

  • If you are on a live network, the dispute will escalate to the DVM on Ethereum for resolution. If you are on Görli, you will need to manually resolve the dispute through the Mock Oracle.

  • Optimistic Oracle dApp
    Testnet dApp
    DVM

    Understanding oSnap

    Why Verification Matters:

    When a project integrates with UMA, they do so with the understanding that someone is always watching for the opportunity to dispute bad proposals. The Verification Team is one form of defence against these bad proposals, and an important one at that. This team is responsible for bringing the human element to proposal resolution. Sometimes the truth can only be discovered through intensive research and lengthy discussion. Our job is to highlight those moments and provide the best source of truth available for UMA voters to consider. By joining our team, you become a key contributor to our shared goal of maintaining the integrity of our oracle.

    Join the Verification Team here --> https://discord.gg/muN6tBaG4d

    Understanding UMA
    ASSERT_TRUTH2
    ASSERT_TRUTH
    Twitter
  • Discourse

  • Medium

  • YouTube

  • UMAverse

  • UMA Protocol Calendar

  • UMA Press Kit

  • Employment at UMA

    If you are interested in working at UMA, please see our vacancies below. If you know someone that might be a good fit, check out our “talent referral options” program that offers up to 1000 $UMA to anyone who refers suitably qualified candidates for any of our open positions.

    • Risk Labs Job Postings

    • "Talent Referral Options" Program

    Discord
    Expiring Multi-Party (EMP)
    Perpetual Multi-Party
    Viewing a Request's Proposer Whitelist

    ManagedOptimisticOracleV2 requests have defined proposer whitelists. The whitelist for a given request can be found by calling the getProposerWhitelistWithEnforcementStatus function with the request's requester , identifier , and ancillaryData. The function will return an isEnforced boolean that defines whether a whitelist is enforced and an address array of allowedProposers . If isEnforced is true, then only allowedProposers may propose the request. If isEnforced is false, any address will be able to propose.

    When a new request is created on ManagedOptimisticOracleV2 it will default to the defaultProposerWhitelist unless overridden by the requestManager . This default whitelist can be viewed with the following steps:

    1. Call the defaultProposerWhitelist view function on a deployed ManagedOptimisticOracleV2 contract to get the address of the default whitelist.

    2. Call getWhitelist on the default whitelist address to view all address on the whitelist. Alternatively, call isOnWhitelist to check if a given address is on the whitelist.

    Proposing on ManagedOptimisticOracleV2

    Proposing on ManagedOptimisticOracleV2 can be done by calling the same proposePrice or proposePriceFor functions with the same arguments as proposing on OptimisticOracleV2. Proposal transactions from addresses that are not whitelisted will revert with the following error messages, "Sender not whitelisted" or, "Proposer not whitelisted".

    Listening for ManagedOptimisticOracleV2 Events

    The emitted events that are relevant to oracle participants (RequestPrice, ProposePrice and DisputePrice, SettlePrice) are unchanged from the OptimisticOracleV2 contract. These events can be queried via RPCs or by using our subgraph that indexes ManagedOptimisticOracleV2 events.

    here
    1. An Asserter will post a bonded assertion about the state of the world. This assertion will :

      • identifier: price identifier being requested.

      • timestamp: timestamp of the fact being asserted.

      • claim: ancillary data containing additional information about the assertion

      • currency: ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.

      • bond: a bond size that represents the stake the asserter is putting on their statement being correct.

    2. Disputers can refute a piece of data submitted by an Asserter within the assertion liveness period by referencing their own off-chain price feeds and determination methodologies. The liveness period is a pre-defined amount of time a that an assertion can be disputed.

    3. If Disputers do not refute the price submitted by the Asserter within the proposal liveness period, the assertion is optimistically treated as being correct.

    4. If an assertion is disputed, the assertion will be submitted to UMA’s DVM for dispute arbitration.

    UMA's Data Verification Mechanism

    The Data Verification Mechanism (DVM) provides a backstop to the UMA OO by resolving disputes that happen when a proposed/asserted piece of data is disputed.

    1. In the event of a dispute, a price request is submitted to the DVM which proposes a vote to UMA tokenholders to report the price of the asset at a specific timestamp.

    2. The vote will conclude after a 48-96 hour voting period.

    3. UMA tokenholders will reference the price identifier's UMIP to determine how to arrive at a vote result via off-chain price feeds and methodologies.

    4. The DVM will aggregate votes from UMA tokenholders to determine the final price of the asset for a given timestamp.

    The DVM is powerful because it encompasses an element of human judgment to ensure contracts are securely and correctly managed when issues arise from volatile (and sometimes manipulatable) markets.

    UMA's oracle system is constructed with economic guarantees around the cost of corrupting the DVM to ensure it will cost more to corrupt the oracle (i.e., obtain 51% or more UMA tokens) than the amount someone could profit from corrupting the oracle (i.e. stealing funds within contracts on UMA).

    Oracle system diagram

    The UMIP Process

    UMA Improvement Proposals (UMIPs) are design documents used to propose changes to the UMA ecosystem. UMIPs are intended to be the primary mechanism for proposing new features, collecting community input on an issue, and for documenting the design decisions that have gone into the UMA protocol.

    UMIPs are a convenient way to track the progress of an implementation. Examples of common UMIPS include adding a new price identifier or collateral currency to be supported by the DVM. UMIPs are presented to UMA tokenholders for voting through the voting dapp to determine whether they will be accepted or rejected.

    UMIPs need to provide a concise technical specification of the feature and a rationale for the feature. They are modeled after EIPs and ZEIPs. See here for an EIP template and ZEIP template.

    Resolving Disputes

    If the dispute is on a live network, it will be resolved by the DVM on Ethereum, and the results returned within 48-72 hours (depending on when the dispute was raised during the DVM voting cycle).

    If you are testing the dispute flow on Görli, you will need to manually resolve the dispute through the Mock Oracle. This contract stands in for the DVM on Görli and allows you to manually return your own values for testing purposes.

    1. Go to the Mock Oracle contract on Görli Etherscan.

    2. Click 'Write Contract.'

    3. Click 'Connect to Web3' to connect your wallet.

    4. Click 'OK' on the pop-up that warns you that writing to contracts on Etherscan is a beta test feature.

    5. Connect through your wallet interface, and switch networks to Görli if necessary.

    6. Click pushPrice to see the parameters you will need to enter.

    7. Enter the original request's identifier, time, and ancillaryData, and enter the value you want to return for price.

    8. Click 'Write' and submit the transaction.

    9. Depending on how the contract you are testing was written, you may need to call settleAndGetPrice from your contract to the Optimistic Oracle contract to get the value returned from the mock oracle, or you may be able to call settle on the Optimistic Oracle and have your contract automatically receive and handle the return value with a priceSettled callback function.

  • Insurance contract

  • A generic data assertion framework

  • A description of Escalation Managers and how they can be used.

  • Deploying sandboxed oracle environment for testing the dispute flow.

  • quick start tutorial
    Prediction market
    The explanation includes an IPFS hash that is a unique identifier for the Snapshot proposal and can be used to retrieve details of the proposal. For example, https://ipfs.io/ipfs/bafkreie2hujdeenwz7dcbqcvwq37vjgu6g3alvkk5ysxbm4yqpeahm37xa.

    oSnap Proposal Pass Criteria

    An oSnap proposal's voting results must meet both criteria below to be considered passed:

    1. Quorum: FOR + AGAINST + ABSTAIN ≥ Required Quorum

    2. 'FOR' majority: FOR > 50% * (FOR + AGAINST + ABSTAIN)

    Disputing Proposals

    If the oSnap request does not meet the Rules, it should be disputed. Disputed requests can not be executed no matter how UMA resolves the dispute. This section outlines the steps to dispute an invalid oSnap request, or any other invalid assertions to UMA's Optimistic Oracle.

    Optimistic Oracle dApp
    Connect a Snapshot space admin wallet and navigate to your Snapshot space Settings page. If you do not have an admin wallet connected, you can also access this page by pasting in this URL with your DAO's ENS inserted: https://snapshot.box/#/<YOUR DAO ENS>.eth/settings/execution
  • Click "Execution" on the left side menu and the pencil icon inside the "oSnap by UMA" box to show oSnap enabled Treasuries.

  • If your space has oSnap configured, Treasuries will display below the "oSnap by UMA" box with their status displayed as "Active".

    1. To disable oSnap on a active oSnap treasury, hover over "Active", to show the "Disable" button and click it to open the oSnap Safe app.

    1. Opening up the oSnap Safe app may bring up the following Safe warnings depending on your browser's stored cookies:

    1. In the oSnap Safe app, click "Deactive oSnap"

    1. This will propose a "disableModule" transaction in the Safe(Wallet) dapp. This transaction can be proposed, reviewed, signed, and executed as per the typical Safe(Wallet) transaction flow.

    1. After this transaction is executed, oSnap is disabled from your Safe treasury. Treasuries without oSnap enabled will display with an "Enable" button in Snapshot's Execution settings page (note, it may take some time after the executed transaction for the Snapshot UI to update).

    ManagedOptimisticOracleV2 requests are tagged "Managed Optimistic Oracle V2" on the Oracle Dapp.

    Setting Custom Bond and Liveness Parameters

    Overview of Setting Customer Bond and Liveness Parameter in UMA's Optimistic Oracle

    Every request to UMA's Optimistic Oracle includes bond and liveness settings that specify the size of the bond that proposers (and disputers) are required to post, the token used for bonding, and the liveness window, which is the challenge period during which a proposal can be challenged.

    The minimum bond is the same as final fee for Optimistic Oracle V2 (OOV2) or can be queried by calling getMinimumBond(token) for Optimistic Oracle V3 (OOV3). The default liveness window is two hours. For many cases, you may want to customize these values. The primary reason to increase the bond size or challenge window is to increase your security for complex requests or requests that could move large amounts of money.

    How to think about proposer and disputer bonds

    In most cases, you will want to set a bond higher than the minimum. The reason for this is that the bond provides a financial incentive for disputers to dispute invalid proposals. Disputers receive half of the proposer bond in the case of a successful dispute in the OOV3. For the OOV2, it's half of the excess above the final fee.

    The part of the bond that doesn't go to the disputer in a successful dispute goes to the UMA Store contract. The reason the disputer does not get the full amount is to prevent a malicious proposer from making a bad proposal and then front-running an honest disputer to dispute themselves if they get caught.

    Example bond payouts (OOV3)

    As an example, imagine an application that requires a 10,000 USDC bond to assert a claim via OOV3.

    To make an assertion, a proposer must post a 10,000 USDC bond, which they will get back after the liveness window if the assertion is not disputed. To make a dispute, a disputer must also post a 10,000 USDC bond.

    If the disputer wins, they receive 15,000 USDC (10,000 USDC disputer bond + 5,000 USDC from the excess proposer bond) and the Store receives 5,000 USDC.

    If the proposer wins, they receive 15,000 USDC (10,000 USDC proposer bond + 5,000 USDC from the disputer bond) and the Store receives 5,000 USDC (half of the disputer bond).

    Higher or lower bonds?

    If data received from the oracle could potentially move large amounts of value, you may want to set a higher bond to make it more costly for an attacker to attempt to steal funds through a false proposal. (Remember that the proposer will lose their entire bond if they are disputed and found to be incorrect.)

    The tradeoff to setting a higher bond is that it may be more difficult to run a project that requires frequent proposals, since good proposers will have funds locked up for at least the length of the challenge window. Another tradeoff is that a very high bond may make it difficult for disputers to post bonds to challenge bad proposals. Remember also that disputers will lose their bond if they are incorrect, so the disputer has a capital cost and a risk of loss.

    Before launching your contract, you should think about who you expect to be proposers and disputers, whether they have adequate access to capital, how much value the oracle is securing, how many requests you expect to make in a given day, and whether you should add a proposer reward (to incentivize independent proposers to take on the capital cost and risk of proposing answers to your requests).

    There are no exact answers to how high or low your bond should be, although it is almost always a good idea to set a bond that is larger than the final fee so that disputers have an incentive to dispute bad proposals.

    How to think about liveness

    The liveness period is the challenge window where disputers can dispute a proposal, and is another knob you can turn to increase security (while accepting UX trade-offs).

    A typical challenge period is two hours, which is usually plenty of time for disputers to recognize and dispute bad proposals. In some cases, you may want to increase the length of the challenge period. A classic example is an insurance contract, since insurance contracts usually have these qualities:

    1. Large amounts of value are at stake.

    2. Payouts are rare.

    3. Proposals and disputes require a greater amount of thought and consideration.

    4. Payouts are not very time sensitive, and a long delay (even a day or more) to allow proposers and disputers to think through the situation will not seriously inconvenience users.

    You may want to consider a two-hour challenge window in these situations:

    1. Requests happen frequently and proposers and disputers will need to reuse their capital regularly for bonding.

    2. The dollar value secured by a request is lower.

    3. The request is easy to reason about (and proposals and disputes could potentially be automated).

    4. Users are sensitive to the settlement time.

    At this time, it is generally not recommended to set a challenge window shorter than two hours.

    If your users are very sensitive to settlement time, you may want to consider a smart contract architecture that allows a particular type of user to fully insure a piece of data that is acted on instantly, and then waiting to be reimbursed after the challenge window. Think of this user as a "designated waiter," who is probably compensated in some way.

    A good example is the in the Across protocol. Users of the Across bridge receive their funds almost instantly, because a relayer sends them funds on the receiving chain and then submits for reimbursement from the protocol, and has to wait for several hours for their relay to be bundled with other relays, proposed, and then settled after the challenge window.

    In this case, the UX for most users is excellent (nearly instant transfers) but the protocol is still secured by a long challenge window that is absorbed by a less time sensitive user type (the relayer) who is paid fees for their trouble.

    Governance

    The UMA token is primarily a governance token used to contribute to UMA protocol decisions, such as voting on UMA Improvement Proposals (UMIPs), price requests, and disputes made to UMA's Data Verification Mechanism (DVM).

    Governing the UMA ecosystem

    The UMA token is an integral part of the UMA ecosystem as it guarantees the economic security of UMA smart contracts and its oracle system. The objective of the UMA token is to enable the optimistic oracle to remain secure utilizing a fully decentralized and permissionless method.

    UMA's DVM is designed with an economic guarantee around the cost it would take to corrupt the oracle and the profit someone would receive. The DVM ensures the price to obtain 51% of UMA tokens is greater than the profit from corrupting the DVM, as measured by the collateral stored in UMA's financial contracts. This is achieved through an inflationary reward (currently 0.05% of total network token supply), distributed pro-rata by stake to voters who participate and vote correctly. As long as there is an honest majority, voters will vote correctly.

    As the total value of collateral locked in UMA grows, the UMA token is required to increase in value to ensure the security of the DVM. To ensure this inequality holds, the DVM may charge fees to financial contracts which the DVM would use to buy UMA tokens.

    Voting

    The UMA voting process requires tokenholders to commit and reveal their votes in two separate stages. Each stage is open for 24 hours, so each voting period is 48 hours.

    • UMA Tokenholders can discuss their votes in the #voting channel of the before voting

    • UMA tokenholders can use the to vote on protocol decisions

    Examples of governance proposals include:

    • Approving new and

    • Price requests and disputes

    • Upgrading the core DVM protocol and / or modify DVM parameters

    • Registering and de-registering contract templates

    Proposing Oracle Data

    This tutorial describes how to propose answers to data requests. The data could be anything from token prices, to who won a basketball game, to whether an optimistic governance action is valid.

    Step 1: Go to the Optimistic Oracle dApp, if you are answering requests on a live network like Ethereum, Optimism, or Polygon, or go to the Testnet dApp if you are answering requests (probably your own) on Goerli.

    Step 2: Locate requests under the Requests tab for outstanding requests.

    Step 3: Click on the request you are interested in proposing data for.

    Step 4: Click the 'Connect wallet' button in the top right corner and go through the steps to connect your wallet. Confirm you are on the same network as the data request.

    Step 5: Before proposing, confirm the details of the request and ancillary data to ensure you are proposing accurate data. You may also want to check the instructions in the for the identifier.

    Step 6: Once you are sure of the proposed value and connected to your wallet, input the value and click the 'Submit Proposal' button.

    Step 7: Confirm the transaction details through your wallet provider. After confirming, the proposal will be sent!

    Glossary

    Optimistic Oracle

    The "Optimistic Oracle" (OO) allows contracts to quickly request and receive price information. Unlike mechanically restrictive price feed oracles, an optimistic oracle can serve any arbitrary data on-chain.

    DVM

    The “Data Verification Mechanism” (DVM) is the name of the oracle service provided by UMA. The DVM does not provide an on-chain price feed. Instead, it is only used to resolve disputes of liquidations and to settle synthetic token contracts upon expiration.

    Parameters of a Long Short Pair (LSP) smart contract:

    Financial Product Library (FPL)

    The financial product libraries are used to transform the value returned by the price identifier into a final settlement value. Financial product libraries can be applied to create different types of financial contracts and payout functions.

    Refer to for a list of deployed financial product libraries for each network. If your desired financial product library is not already deployed, refer for instructions on deploying and verifying your own financial product library contract.

    collateralPerPair

    The collateralPerPair parameter determines the amount of collateral required to mint each pair of long and short tokens.

    • Example: If a contract uses WETH as collateral and the collateralPerPair parameter is set to 0.25 on deployment, each long and short token that is minted would require 0.25 WETH as collateral.

    expiryPercentLong

    ExpiryPercentLong is used to determine the redemption rate between long and short tokens. ExpiryPercentLong is a number between 0 and 1, where 0 assigns all collateral to the short tokens and 1 assigns all collateral to the long tokens.

    UMA Product Types:

    Range Tokens

    Range tokens enable a DAO to use its native token as collateral to borrow funds. At maturity, if the debt is not paid, the range token holder is instead compensated with an amount of the collateral (the native token) using the settlement price of the native token to determine the number of tokens. This is similar to a tokenized convertible debt structure.

    Success Tokens

    Success tokens offer an alternative way for DAOs to diversify their treasury and sell tokens to investors in an incentive-aligned way. Success tokens are two financial products wrapped into one token: a set amount of a project token which is combined with a covered call option on that token backed by a set amount of the same token.

    KPI Options

    Key Performance Indicator (KPI) Options are synthetic tokens that will pay out more rewards if a project’s KPI reaches predetermined targets before a given expiry date. Every KPI Option holder has an incentive to improve that KPI because their option will be worth more. This is intended to align individual token holder interests with the collective interests of the protocol.

    DAO Proposals

    The UMA DAO accepts proposals for on-chain actions that require tokenholders approval. An example would be a request for funding from the UMA treasury. The steps to complete a proposal:

    Step 1: Post to Discourse

    The first step is making a post in the UMA discourse under non-technical UMIPs. The post should outline the key components of a proposal and give the community a chance to submit feedback and recommend changes.

    An example submission is Polymarket's Liquidity Mining Program.

    Step 2: Snapshot Vote

    When the proposal appears ready, a Snapshot vote can be created by the proposer with a 5 day close. Should it receive majority support at the end of 5 days, it will then pass to snapshot for an indicative vote prior to being put to an on-chain vote.

    Proposals that require movement of treasury funds require a 4,000 UMA bond to be posted which is returned if the proposal is successful in an on-chain vote of tokenholders.

    RiskLabs, the foundation which established UMA, has indicated its willingness to handle the on-chain proposal and cover the bond payment for proposals which attract majority support on a snapshot poll of tokenholders.

    Here is the snapshot for .

    Step 3: On-chain Vote

    After a Snapshot vote has successfully passed, an on-chain vote is held to transfer the funds. If the vote is successful, the funds are transferred to the recipient wallet address.

    Example Projects

    Integrations use the Optimistic Oracle for various use cases.

    For a complete list of all current integrations see:

    Integrations
    Description

    Approved Price Identifiers

    This table includes identifiers that could be useful for new contracts and are likely to be encountered by proposers, disputers, and voters. It does not include identifiers that have been deprecated, identifiers that have fallen out of use, or specific token pairs.

    If you need an identifier that is not included in this list, you can for approval. If a price request is made with an identifier that is not on this table, please refer to the canonical on GitHub. The absence of an identifier from this table does not necessarily mean the identifier is not approved, it just means it is not recommended for new contracts.

    If you want to use an approved identifier that is not on this list, let us know and we can add the identifier back to this table for easier voter/disputer reference.

    Subgraphs

    This section explains the UMA subgraph and how to interact with it. The UMA subgraph indexes data from UMA contracts over time. It organizes data about tokenholders, contracts, DVM requests, voting, and more. The subgraph updates for each UMA contract interaction. The subgraph runs on protocol’s hosted service and can be openly queried.

    UMA has a GraphQL API Endpoint hosted by called a subgraph for indexing and organizing data from the smart contracts. The schema of GraphQL elements available is defined in .

    Ethereum Mainnet

    Voting Walkthrough

    How to stake tokens, vote, and claim rewards

    This tutorial describes how to vote using the . For context, each voting period is 48hrs. Voting takes 3 steps:

    • Commit Vote: the first 24hrs of a voting period allows you to encrypt and commit your vote

    • Reveal vote: the second 24hrs of a voting period allows you to decrypt and reveal your vote. Votes are tallied by a DVM smart contract at the end of the reveal period.

    relayer

    Shutting down contract instantiations (in rare circumstances)

    UMA Discord
    Voter dApp
    price identifiers
    collateral currencies
    github
    here
    Polymarket's Liquidity Mining Program

    Explorer Page

  • Graphql Endpoint: https://gateway.thegraph.com/api/[api-key]/subgraphs/id//41LCrgtCNBQyDiVVyZEuPxbvkBH9BxxLU3nEZst77V8o

  • Code Repo

  • Helpful Links

    Querying from an Application

    Managing your API Key & Setting your indexer preferences

    Resources

    LSP Subgraphs

    • Mainnet Subgraph

    • Polygon Subgraph

    • Kovan Subgraph

    EMP Subgraphs (includes query for whitelisted collateral)

    • Mainnet Subgraph

    • Kovan Subgraph

    Voting Subgraphs

    • Mainnet Subgraph

    • Kovan Subgraph

    Here is the source code for deployed subgraphs.

    Making Queries

    To learn more about querying a subgraph refer to The Graph’s documentation.

    The Graph
    The Graph
    the subgraphs repo
    Creating an API Key Video Tutorial
    UMIP

    Sherlock is a protocol on the Ethereum blockchain that protects users from smart contract exploits with proprietary security analysis and protocol-level coverage. UMA acts as an unbiased, decentralized arbiter for Sherlock where disputes are escalated to UMA's DVM and voted on to be resolved.

    Domination Finance is a decentralized exchange (DEX) deployed on Ethereum and Polygon. Domination Finance uses UMA's Optimistic Oracle to enable users to speculate on popular market dominance metrics, such as Bitcoin Dominance (BTCDOM).

    Yam Synths is a powerful platform from the Yam DAO community providing easily accessible and innovative synthetic assets. UMA's Optimistic Oracle helps Yam to allow anyone in the world to access and trade cutting-edge synthetic products.

    Hats.finance is a proactive bounty protocol for white hat hackers and auditors, where projects, community members, and stakeholders incentivize protocol security and responsible disclosure. Hats.finance and UMA have collaborated on a product called protected tokens which enable users to recover funds in the event of a hack, bug, or other cause of lost funds.

    Across

    Across protocol is a novel bridging method that combines UMA's Optimistic Oracle with bonded relayers and single-sided liquidity pools to provide decentralized instant transactions from rollup chains to Ethereum mainnet.

    Polymarket

    Polymarket is an information markets platform that lets you trade on the world’s most highly-debated topics. Polymarket supports UMA and its Optimistic Oracle as a resolution source for its markets.

    Jarvis Network

    Jarvis Network is a set of protocols on Ethereum allowing anyone to gain exposure to the price of any traditional or digital assets with stablecoins, against liquidity pools. Jarvis leverages UMA's Optimistic Oracle and DVM as its liquidation and dispute mechanism to ensure that jFIATs are properly collateralized.

    projects.uma.xyz

    ASSERT_TRUTH2 (as of Dec 8, 2025)

    New intended default price identifier for Optimistic Oracle V3

    MULTIPLE_CHOICE_QUERY

    Allows requests with a predefined set of valid responses.

    NUMERICAL

    Returns a number value based on a question asked in the ancillary data.

    ROPU_ETHx

    Reflects violations of the MEV-policy committed by validators of the ETHx staking protocol

    YES_OR_NO_QUERY

    Returns an answer to a "yes or no" question.

    ACROSS-V2

    Verification of whether a bundle of Across bridge transactions submitted to mainnet is valid.

    UMIP-179

    ASSERT_TRUTH (DEPRECATED as of Dec 15, 2025)

    submit a new UMIP
    UMIP directory

    Former default price identifier for Optimistic Oracle V3

    Claim rewards: staking rewards are constantly accrued. You can claim + restake or just claim them to your wallet whenever you like.

    The purpose behind using the Commit/Reveal scheme is that it allows votes to remain private.

    Instructions:

    1. Go to http://vote.uma.xyz.

    2. Connect your wallet.

    3. In order to vote, you must stake your tokens. Click "Stake/Unstake" then follow the instructions in the module. Staking your tokens does three things:

      • Your tokens will immediately start to earn a prorated portion of the $UMA token emissions, which is reflected as an APY on the dapp.

      • You will be able to vote with those tokens

      • You will have a 7-day cooldown period in order to unstake those tokens. During that period, your tokens will not be earning any rewards or be eligible for voting.

    Indicate that you understand the cooldown period, approve, then stake your $UMA
    1. You can only vote when there is a live vote(s), and during the Commit period.

    2. Choose your vote(s) from the dropdown menu, then click "Commit vote" and send the transaction.

    3. Each voting round consists of a 24-hour commit period, followed by a 24-hour reveal period. In order for your vote(s) to count, you need to return and reveal your vote(s) during the reveal period.

    4. During the reveal period, return to the Dapp and choose "Reveal" to reveal your vote(s).

    Once the dapp shows your vote as "Revealed," you are done with the voting process. The vote(s) will be finalized when the reveal period ends, at which point you will be able to see if you voted correctly. If you did, you will receive a bonus. If you voted inaccurately or failed to vote, you will have a penalty applied to your stake. This penalty amount is redistributed to accurate voters.

    Protocol Parameters (adjustable by governance)

    Emissions: .18 $UMA/second

    Missed vote penalty: 0.1% of staked balance

    Withdraw cooldown period: 7 days

    Claim rewards

    Emission rewards begin to accrue automatically when you stake $UMA. You may claim these rewards to your wallet, or claim-and-stake to your staked balance.

    Rewards associated with voting successfully are automatically added to your staked balance after the voting period ends.

    UMA voter dApp

    Polymarket

    How to verify Polymarket Proposals

    What is the YES_OR_NO_QUERY?

    The YES_OR_NO_QUERY (UMIP can be read here) is a price identifier intended for plaintext binary questions. Requesters encode their questions in ancillary data. For a full overview of how ancillary data is formatted, refer here.

    The YES_OR_NO_QUERY is most typically used by Polymarket today to resolve the outcome of information markets. This can come in the form of asking for the outcome of sports games, a crypto or nft price at a specific point in time or world events among many other things.

    Note that this price identifier is often in the form of YES or NO, but could also be in the form of THIS or THAT - ie “did the Lakers or Clippers win the game last night” can work even though it is not really a YES or NO question. The example used in the rest of this document will illustrate how this can be done.

    Components of Ancillary Data

    From the UMIP:

    When converted from bytes to UTF-8, the ancillary data should be a dictionary object containing q (question), p1, p2, p3 and p4 keys and values. p4 is optional and will only apply in certain situations.

    Example:

    q: title: French Open Final: Djokovic vs. Ruud, description: This market will resolve to "Djokovic" if Novak Djokovic wins the final, or to "Ruud" if Casper Ruud wins the final. res_data: p1: 0, p2: 1, p3: 0.5. Where p1 corresponds to Ruud, p2 to Djokovic, p3 to unknown/50-50,initializer:91430cad2d3975766499717fa0d66a78d814e5c5

    The UMIP goes on to note default values for p1, p2, p3 and p4.

    • p1 is usually used for “NO” values and defaults to `0` if not explicitly assigned

    • p2 is used for “YES” values and defaults to `1` if not explicitly assigned

    • p3 is for “UNKNOWN” or “CANNOT BE DETERMINED” and defaults to `0.5` if not explicitly assigned.

    • p4 is for situations where the question is expected to eventually be able to be evaluated, but cannot be at this time. An example would be if the outcome to a sports game was asked for, but the game has not yet happened or finished. This will be referred to as the “magic number” and defaults to the minimum int256 value or before e18 scaling: -57896044618658097711785492504343953926634992332820282019728.792003956564819968

    Important Note: Polymarket currently uses OptimisticOracleV2. Therefore, the early request should only be used if a proposed value is proposed earlier than the expected event resolution time noted in ancillary data.

    For additional context on when the magic number or p3 are expected to be returned, from the UMIP:

    p4 is intended to be used for situations where it is not a given that the price request (or contract settlement) should even occur yet. An example of this would be the UMA event-based expiry LSP. A request to settle an event-based expiry LSP can be submitted at any time but if the question can not be resolved yet it should be ignored.

    The default p4 value is the minimum int256 value and is used as a "magic number" to indicate that an event-based expiry request is invalid and the contract should continue as normal. For example, if the question is related to a basketball game on January 6th and a settlement request comes in on January 5th, the question can not be resolved yet, and voters should return the p4 value with the magic number to reject the settlement request. This value also moves the decimal place 18 spaces to the left, due to the default behavior of the UMA voting interface to scale input values to 18 decimals. After scaling by the interface, the value will be -57896044618658097711785492504343953926634992332820282019728792003956564819968

    Notice that a p3 value would never be returned earlier than the final price request time noted in the ancillary data or the requesting contract's expiration timestamp and a p4 value would never be returned after that point. Consider an unresolvable question like, "Was the weather nice on January 6th, 2022?" If the question was asked on January 7th, 2022, you would return the p3 value. If the same question was asked on January 5th, 2022, you would return the p4 value.

    Scaling values

    Also noted in the UMIP is the fact that return values are not scaled when referred to in the UMIP or present in ancillary data.

    This simply means that if the ancillary data contains “p2:1”, this should really be returned on-chain as 1e18 (not 1 wei). So 1000000000000000000 instead of 1.

    All price identifier values are treated this way in the UMA system. The UMA voter dapp and Optimistic Oracle proposer interface both perform this scaling automatically for UMA voters or proposers.

    Understanding Question Data

    When verifying a proposal, it is important to assess the question data and arrive at their own conclusion for what the return value should be. Here is the example above in the oracle UI:

    Key data in the proposal is the identifier, timestamp, and the ancillaryData.

    The YES_OR_NO_QUERY identifier tells us which “pricing methodology” we should be referring to. This is best understood by reading the corresponding UMIP. For all price identifiers, the UMIP can be looked up by price identifier name.

    The proposed time tells us the timestamp a value was proposed and therefore should be evaluated.

    The Additional Text Data above represents the ancillary data and contains the plaintext version of the binary question that a proposer should be evaluating. It is important to read the full text data as it could also contain pricing specifications or data sources that should be used.

    In the example, I can see that the question is asking if Novak Djokovic or Casper Ruud wins the French Open Final. It does not specify a data source so I can use a wide array of publicly available information to determine what I think the correct answer should be. Referring to ESPN scores:

    I see that Djokovic won and I should continue to read the ancillary data to determine which return value should be used in this scenario.

    Ancillary data question:

    This market will resolve to "Djokovic" if Novak Djokovic wins the final, or to "Ruud" if Casper Ruud wins the final.

    Resolution key:

    res_data: p1: 0, p2: 1, p3: 0.5. Where p1 corresponds to Ruud, p2 to Djokovic, p3 to unknown/50-50

    Since Djokovic won and p2 corresponds to 1, the proposed value should be p2:1.

    Voters/proposers should typically evaluate all price requests independent of the party that has requested the data. But as a validation tool, the requestor can sometimes provide information that will help us verify the values that we are about to propose. As an example, this question was from .

    This is one simple example of evaluating a YES_OR_NO_QUERY, but almost all questions follow the same format.

    Approved Collateral Types

    Collateral Currency
    Final Fee
    UMIP
    Chains

    ABT

    0.055

    USDB

    250

    Voting with a 2-Key Contract

    The UMA DVM two-key contract enables you to actively engage in voting using hot keys (private keys stored on machine and used often), but protect your funds with the stronger, and preferable, use of cold keys (private keys stored offline and used rarely). Another way this contract can be used is to delegate voting rights to an EOA, while still maintaining token ownership with a multisig or other ownership structure.

    Each two-key contract is a unique smart contract that you deploy. It keeps track of:

    • The number of UMA tokens you have deposited into the two-key contract

    • The address of your hot wallet; the hot wallet is permissioned to sign transactions and vote in DVM governance

    • The address of your cold wallet; only the cold wallet (and importantly, not the voting wallet or any other address) is permissioned to withdraw UMA tokens from the two-key contract

    DANGER

    If you do not know exactly why you are setting up a 2-Key contract, then you likely do not need one. Deploying the contract is expensive and unnecessary unless you need to vote with separate hot and cold keys.

    Voting with a hardware wallet is not a reason that necessitates needing to set up a 2-Key contract. You can likely vote by connecting your hardware wallet to MetaMask or another wallet provider.

    If you have any doubt about your need for a 2-Key contract, please ask in the UMA Discord before proceeding.

    Prerequisites

    • You need ETH in your hot wallet for the initial deployment of the 2-key contract and for submitting all subsequent votes.

    • You need ETH in your cold wallet to make the initial UMA token deposit, and also if you ever want to withdraw tokens from the 2-key contract.

    Instructions to deploy your own 2-key contract

    Connect

    Navigate to the UMA voter dApp (vote.umaproject.org) and connect your MetaMask hot wallet. This will be your voting wallet going forward.

    Deploy

    Click on the gear icon on the far right.

    In the modal, click Add Cold Wallet Address

    Input your cold wallet address and click Save.

    Verify your deployment was correct

    The following steps help you verify that your two-key contract was deployed correctly and check that the permissions are held by the correct address.

    • Copy the 2-key smart contract address (i.e., DesignatedVoting Escrow Account) from the voter dApp and view it on Etherscan

    • Under Read Contract input roleID 0 in function 1. getMember, and click query. Check that the address output matches your cold wallet address.

    • Input roleID 1

    Voting

    To vote with the 2-key contract, you will need to send UMA tokens to it. After sending UMA tokens to the two-key contract address, you can immediately start voting with your hot keys at the voter dApp. This will exclude you from voting with any additional UMA tokens that are in your hot wallet through the voter dApp.

    Withdraw tokens

    The following steps let you withdraw UMA tokens from the two-key contract using your cold keys. You will have to withdraw and deploy a new two-key contract if you want to designate a new hot key for voting.

    • Navigate to your DesignatedVotingContract on Etherscan

    • Connect your cold wallet by clicking the “Connect to web3” button

    • Use function 11. withdrawErc20

    Changing the voter address

    To change the voter address for a DesignatedVotingContract, you just need to call resetMember(newAddress) with your cold keys (owner address) and pass in the new address that you wish to use as the voter.

    DVM 2.0 FAQ

    Frequently asked questions about the new UMA DVM 2.0

    What kind of APY can I expect to receive for staking?

    To learn more about how exact APY is calculated, you can refer here.

    At a high level though, all UMA voters on average will receive an APY determined by the annual UMA emissions amount divided by the average total UMA staked over the year.

    Before the DVM 2.0 upgrade, approximately 18-20mm UMA was voting on average for each vote. If this holds relatively constant, it means that average UMA voter APYs will be approximately 28-32%. This can of course fluctuate on an individual voter basis dependent on voter performance.

    How do I maximize my APY?

    Maximizing your APY should be simple. To maximize APY you should:

    • Remain staked within the system.

    • Claim and restake your rewards at times when it makes sense based off balancing your increased stake’s additional future rewards received against gas costs of claiming and restaking.

    • Vote consistently and carefully. Incorrect or absent voter stakes are slashed and distributed to correct / participating voters after each voting round.

    What is the current UMA voter rewards emission rate?

    The UMA emission rate is currently 0.155 UMA/second. This will be distributed pro-rata to all stakers within the UMA system on a per second basis. The UMA emissions rate is controlled by UMA governance and can be updated at any time by a DVM vote.

    What is the unstake timer? Why does this exist?

    The unstake timer is a set amount of time that a staker must wait before they can execute a request to unstake from the UMA system. With the initial DVM 2.0 upgrade, this unstake timer was set to 7 days.

    The unstake timer exists to make the UMA voting system more hardened against attempted manipulation attacks. UMA has always had an assumption that if a malicious attacker could manage to either vote with or bribe a majority of voters to vote incorrectly on a dispute, the UMA token would go to zero in value. This is known as the UMA cost of corruption.

    In practice, this is probably not entirely true as markets are not entirely efficient. Attackers could likely dump voted with tokens for some amount of value after a successful attack. Having a required 7 hold period more strongly enforces that UMA’s cost of corruption is enforced by the market if a manipulation attempt is successful.

    What kind of things does the DVM vote on?

    The Optimistic Oracle & DVM can provide all kinds of different data, from crypto prices, to sports, to verifying if a bridging transaction was valid, with new use cases being added all the time, so its hard to anticipate precisely what you might be asked to vote on, however all questions will be asking something about the state of the world at a particular time, indicated by the timestamp.

    How should I determine what I should vote?

    There are two primary data sources to assist a voter in determining what value they should vote with.

    First, the UMIP that the DVM request references. This will tell you general information about how that question should be answered. The second place to check is the ancillary data of the question. This will provide more context for the question and is likely to include a source, which a link that will take you to a place where that data is likely to be published.

    Disputes are also discussed at length in the #voting-chat and #evidence-rationale channels.

    Why do I have to commit and reveal votes?

    The commit/reveal cycle prevents people from seeing how others have voted by encrypting all initial votes and only decrypting them once all votes are cast. The oracle is built on Schelling Point theory, which indicates that the most likely consensus of non-colluding participants is the truth. By obscuring how other people have voted, this ensures that each tokenholder votes independently.

    Can I vote with tokens that haven’t been staked?

    No. Only tokens that have been staked can be voted with. If you have already initiated the unstaking process for any or all of your coins, they also will not receive rewards or be able to be voted with. However if you have unstaked coins when a vote starts, you can stake your coins any time up to the end of the commit period, and they will be eligible to vote with.

    Can I vote while I am unstaking?

    Unstaked tokens cannot vote. This includes tokens that are in the “cooldown period” after an unstake request has been submitted.

    Can I cancel an unstake request while it is pending?

    You cannot. Unstake requests cannot be canceled once submitted. If you once again wish for those tokens to be staked, you can wait for the unstake period to finish, claim your tokens and restake them.

    Can I get someone else to vote on my behalf?

    It is possible to delegate your staked UMA in one wallet to a different wallet, allowing voters to keep their UMA on a cold wallet and vote with hot wallet, however there is a 1-1 relationship between voting wallets and staking wallets, therefore it is not possible for one person to vote on behalf of multiple other people.

    Do I still get gas rebates?

    Yes! Risk Labs will still be continuing with the existing voting gas rebate program.

    I still don't know how this works - where can I get help?

    Jump into our and ask questions about anything that you are unsure of.

    Quick Start

    0 to 1 Optimistic Oracle integration by example.

    The primary integration point into the UMA ecosystem is the Optimistic Oracle (OO). The OO is an oracle for arbitrary off-chain data which leverages an interactive escalation game between requesters, proposers and disputers and is secured by economic incentives.

    This getting started tutorial will show you how to go from 0 to 1 with the Optimistic Oracle by executing the simplest possible request flow. Later in the docs you can find more information on and dig deeper into its mechanism and .

    If you prefer, you can also watch the following video tutorial in which we follow the step-by-step instructions described below. Please note, the Optimistic Oracle now supports Sepolia testnet.

    Quick start

    0 to 1 integration with the Optimistic Oracle V3.

    The primary integration point into the UMA ecosystem is the Optimistic Oracle V3 (OOV3). The OOV3 is an oracle for arbitrary off-chain data which leverages an interactive escalation game between asserters and disputers and is secured by economic incentives. It differs from the Optimistic Oracle V2 (getting started can be found ) by being easier to reason about and simpler in integration points.

    This getting started tutorial will show you how to go from 0 to 1 with the OOV3 by executing the simplest possible assertion flow. Later in the docs you can find more information on how the OOV3 works and dig deeper into its mechanism and more sophisticated code examples.

    in function
    1. getMember
    , and click query. Check that the address output matches your hot wallet address.
    Input erc20Address:
    0x04fa0d235c4abf4bcf4787af4cf447de572ef828
  • Input the number of tokens that you want to withdraw * 10^18 (for example, if you want to withdraw 1.1 tokens, you should input 1100000000000000000)

  • Click “Write”

  • Confirm the transaction with your cold keys and wait for the transaction to finish mining

  • UMA Discord
    discord
    Sherlock
    Domination Finance
    Yam Synths
    Hats.finance
    UMIP-170
    UMIP-191
    UMIP-181
    UMIP-165
    UMIP-177
    UMIP-107

    USDC

    250

    UMIP-18

    Arbitrum, Arbitrum (USDC.e), Base, Core, Ethereum, Optimism, Optimism (USDC.e), Polygon, Polygon (USDC.e)

    WETH

    0.055

    UMIP-10

    Arbitrum, Base, Blast, Core, Ethereum, Optimism, Polygon,

    WIP

    50

    Story

    UMIP-178
    Ethereum
    UMIP-182
    Blast

    A minimum viable Optimistic Oracle integration

    You will be working through a simple smart contract that asks the oracle the question: Q:Did the temperature on the 25th of July 2022 in Manhattan NY exceed 35c? A:1 for yes. 0 for no. After submitting the request, you will propose a solution using the UMA Optimistic Oracle UI.

    Once through liveness, you will fetch the price from the smart contract. This shows the full lifecycle of an Optimistic Oracle data request on the Sepolia testnet, interacting with an actual Optimistic Oracle contract deployment, without needing to write any code or clone any repos. It should give you the basic intuition as to how the Optimistic Oracle works without too much overhead and is a great starting point before digging deeper. Let's get started!

    Prerequisites

    To complete this tutorial you will need:

    1. Metamask installed in a Chromium based browser (such as Google Chrome) If you don't have it already, you can get Metamask here.

    2. A wallet set up in Metamask.

    3. Sepolia test ETH to send test transactions. You can get Sepolia ETH from one of these faucets: Infura, Alchemy, PoW Faucet, or LearnWeb3,

    Requesting data

    First, we will work through the basic flow for asking the oracle for a piece of data. In this example, we are asking the Oracle for information on the weather but the request could be much more complex to could power any kind of smart contract system requiring data. See approved price identifies and the sample projects for more inspiration on what is possible with the OO.

    The contract used in this tutorial is meant to be a simple data request flow. The contract exposes a simple requestData function which asks the OO a simple question about the weather.

    1. Go to this example contract on Remix. This gives you the minimum data request and retrieval flow possible. We'll work through the code in the sections that follow.

    2. Click on "gist-fba..." to see the files in the gist, and click OO_GettingStarted.sol to open to Solidity file.

    3. In the far left hand menu, click the link to deploy and run transactions (which looks like the Ethereum logo and a right arrow).

    4. In the "Environment" dropdown, choose "Injected Provider," and connect to your wallet. Make sure you are connected to Sepolia within your Metamask wallet! You don't want to deploy to a real network and spend real gas, and the Sepolia Optimistic Oracle address hardcoded into the contract will not work on other networks.

    5. Under the "Contract" dropdown, select OO_GettingStarted.

    6. Click "Deploy" and confirm the transaction with your wallet.

    7. You should now see the OO_GettingStarted contract under "Deployed Contracts". Clicking the dropdown carrot will reveal buttons for each of the functions in the contract.

    8. Click requestData to request the data specified in the contract's ancillary data, asking about the temperature in Manhattan on July 25th, 2022. Confirm the transaction in your wallet. This will submit a data request to the Optimistic Oracle.

    What we've done in the above steps is: a) deploy a smart contract and b) submit a "price request" to the Optimistic oracle through the call to the Optimistic Oracle's requestPrice function.

    Proposing data

    Now that we've asked the OO a question, it's time to propose a solution! The Optimistic Oracle works via an interactive escalation game wherein a) requesters ask questions b) proposers provide solutions and c) disputers monitor the proposals and dispute if they are invalid. If no dispute is done then the proposal is taken as valid. In this example, we'll be acting as the proposer who will be answering the question we asked in the previous section

    1. Go to the Sepolia Optimistic Oracle UI to see your request, which should be a YES_OR_NO_QUERY at the top of the index page. Click on the request to go to the details page.

    2. Click "Connect Wallet" and make sure you are connected to the Sepolia testnet so that you can make a proposal. You should see all the information posed in the data request: the requester, identifier, timestamp, ancillary data and a link to the UMIP.

    3. Submit your proposal (either 1 or 0). The actual value you submit is not super important in this case since this is just for testing purposes, but the is 0. In doing this we are acting as the "proposer" providing a solution.

    Once you've provided an answer to the question the proposal enters into a liveness period of 30 seconds. During this time it's up to Disputers to verify the correctness of what the proposer provided. Note that in a main net price request you'll normally set the liveness to much longer than 30 seconds (say two hours), the proposer will be bonded (if they propose wrong they lose money) and the proposer will be rewarded for providing a valid answer to the question.

    Settling the final answer

    Finally, we can fetch the data proposed in the previous step from the smart contract. For this example, we assume that there the proposed data was correct (was not disputed). Head back to your Remix tab and:

    1. After the transaction finalizes, wait 30 seconds (the challenge window) and then click settleRequest on the OO_GettingStarted contract on Remix. Confirm the transaction in your wallet. Because the proposal was not disputed within the challenge window, it can now be settled.

    2. Click getSettledPrice to get the settled value. It should look like int256: 0 under getSettledPrice if you proposed an answer of 0. You can also see details in the console logs.

    Congratulations! you've successfully integrated with the Optimistic Oracle, requested data, proposed data and fetched it within your smart contract! Note that the incentives in this toy example mean that there is no reason that anyone would provide the correct price (there was no reward for the proposers or disputes and there was no bond). A real world version of this should leverage custom bonds and more realistic liveness parameters.

    Next Steps

    Hopefully you got a basic understanding of the OO request flow from this getting started guide. Check out some of the example tutorials where we walk through more details on the functions discussed in this guide.

    how the Optimistic Oracle works
    more sophisticated code examples
    A minimum viable OOV3 integration

    The OOV3 works by making a truth claim about the world, stating that something has happened or is true. Once asserted, the assertion enters a challenge period wherein someone can disagree with the assertion, by disputing it. If no one disputes it during the challenge window the statement is taken as true. If disputed, the outcome is arbitrated using the UMA DVM (more info on how this works here).

    In this tutorial you will be working through a simple smart contract that asserts the following truth: Statement: Argentina won the 2022 Fifa world cup in Qatar.

    Once through the challenge window, you will use the assertion in your resolution contract. This shows the full non-dispute lifecycle of an OOV3 data assertion. It will give you the basic intuition as to how the Optimistic Asserter works without much overhead and is a great starting point before digging deeper. Let's get started!

    Prerequisites

    To complete this tutorial you will need:

    1. Metamask installed in a Chromium based browser (such as Google Chrome) If you don't have it already, you can get Metamask here.

    2. A wallet set up in Metamask.

    3. Görli test ETH to send test transactions. You can get GETH from Alchemy's faucet.

    Asserting a truth

    First, we will work through the basic flow for asserting a truth to the oracle. In this example, we are making a statement about the outcome of a sports event, but the statement could be much more complex; it could power any kind of smart contract system requiring data.

    The contract used in this tutorial is meant to be a simple data assertion flow. The contract exposes a simple assertTruth function which asserts the truth to the OA about the outcome of the world cup.

    1. Go to this example contract on Remix. This gives you the minimum assertion flow. Read the contract and the comments listed within.

    2. In the far left hand menu, click the link to deploy and run transactions (which looks like the Ethereum logo and a right arrow).

    3. In the "Environment" dropdown, choose "Injected Provider," and connect to your wallet. Make sure you are connected to Görli within your metamask wallet, that has Görli test ETH! You don't want to deploy to a real network and spend real gas, and the Görli Optimistic Oracle address hardcoded into the contract will not work on other networks.

    4. Under the "Contract" dropdown, select OOV3_GettingStarted.

    5. Click "Deploy" and confirm the transaction with your wallet.

    6. You should now see the OOV3_GettingStarted contract under "Deployed Contracts". Clicking the dropdown carrot will reveal buttons for each of the functions in the contract.

    7. Click assertTruth to request the data specified in the contract's ancillary data, asserting the truth about the outcome of the Fifa world cup. This will submit a data assertion to the Optimistic Asserter and the assertion will enter the challenge period.

    What we've done in the above steps is: a) deploy a smart contract and b) submit a "data assertion" to the Optimistic Oracle V3 through the call to the Optimistic Oracle V3's assertTruthWithDefaults function. Now, the assertion has entered the challenge window and can be disputed by someone who disagrees with the assertion. If you click the getAssertion you can see some of the fields that are associated with the assertion. For more details on what these fields mean you can look at the OOV3 interface here.

    The default liveness for an assertion is 120 seconds (2 minutes). Wait this time before going to the next step.

    Settling the assertion

    Once the assertion has settled, and assuming no one has disputed it, we can settle it! Do the following:

    1. Click settleAndGetAssertionResult in remix. This will send a transaction to settle the assertion and return the settlement value.

    2. Wait for the transaction to mine.

    3. Once mined you can expand the transaction output block inline with the green tick arrow. If you scroll down here you can find some information about the assertion, such as the settlement value (which should be true as it was not disputed).

    1. Now, you can call getAssertion and getAssertionResult from remix and see the outputs. getAssertion has changed such the settled value is true and getAssertionResult now returns true as the assertion was deemed valid as it was not disputed.

    Next Steps

    Hopefully you got a basic understanding of the Optimistic Oracle V3 request flow from this getting started guide. Note that this kind of example would not really work on mainnet as: a) there were no bonds for the asserter (and therefore no rewards for disputers) b) the challenge window was too short. The Optimistic Oracle V3 works due to economic incentives between the asserter and disputers, which was absent in this example to keep things simple. For some incentive compatible examples check out some of the example tutorials where we walk through more details on the functions discussed in this guide. Those can be found here.

    here
    here
    https://polymarket.com/

    Across

    How to verify Across Bundles

    Step 1: Install Required Dependencies:

    git:

    • Documentation: https://github.com/git-guides/install-git

    yarn:

    • Documentation: https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable

    node.js

    • Documentation:

    • Run the following command to check what version of node you are running: node -v Make sure it is greater than 16.18.0.

    redis:

    • Documentation:

    • Note: Follow the instructions

    ts-node

    • You can use the following to install globally: npm install -g ts-node

    Nvm (optional)

    • Documentation:

    • Note: Optional, but nvm allows you to easily install and switch between node versions

    VS Code (optional)

    • Highly recommend using a code editor like VS code.

    Step 2: Clone the relayer-v2 repo:

    • If using VS code, open the terminal and run the following command:

    Step 3: Run Redis

    Open a terminal window and run:

    Step 4: Environment Variables

    • Change the .env.example file to .env

    • In line 8 and 9, uncomment either the MNEMONIC or PRIVATE_KEY and input a private key that has no money on it.

      • I used to create a private key to use for the demo but again, do not use one that has any money on it as it is an unnecessary risk.

    Step 5: Run the script

    The below is an example, however the two changes that need to be made based on the request are:

    • REQUEST_TIME=CHANGE_THIS_TO_THE_TIMESTAMP

    • I used privateKey for the below, however, if you used mnemonic in your env variables, it should be changed to –wallet mnemonic

    Note: The first time you run this, it is going to take a long time.

    REQUEST_TIME=1692110627 ts-node ./src/scripts/validateRootBundle.ts --wallet privateKey

    When the script finishes running, check the Validation results as shown below. The below shows an example of an invalid bundle as it shows “valid”: false:

    Appendix

    For additional documentation on Across root bundles, visit:

    DVM 2.0

    The next iteration of the UMA DVM

    The UMA DVM is the arbitrator for the Optimistic Oracle and other UMA ecosystem contracts. It facilitates dispute resolution wherein UMA token holders vote in a commit reveal schelling point mechanism. For an overview of how the DVM see here. The DVM has been rebuilt with the new iteration being released in Q1 of 2023.

    At a high level, the upgrade adds a new staking and slashing mechanism wherein voters earn a pro-rata share of emissions for staking and are slashed for voting wrong (or not voting). This upgrade also reworks a number of other DVM contracts such as the governor, proposer contract and a new designated voting contract. Finally, this upgrade adds a new emergency recovery mechanism to the DVM that enables admin proposals to bypass the DVM's schelling point oracle system in the event of an emergency. More detail on the individual changes are broken down in the sections that follow.

    This doc page outlines some of the changes between DVM 1.0 and DVM 2.0 and some other relevant implementation details.

    Mechanism changes & UMA tokenomics update

    The DVM2.0 introduces three key changes to how the UMA token interacts with DVM system:

    1. Voters now must stake UMA in the DVM to participate in the schelling point and to receive rewards.

    2. Voters now earn a pro-rata share of a fixed emission rate simply for staking their tokens. Staking rewards are emitted at a constant rate per block. This means you can work out the overall UMA inflation over time and stakers can easily work out their APY for staking in the system. In comparison to the previous inflation system, the total inflation rate is no longer a factor of the number of votes held by the DVM. The pro-rata share of tokens received by stakers is independent of their voting performance. The emissions rate is set through UMA governance.

    3. Voters' staked balances are also now susceptible to slashing. The slashing mechanism redistributes tokens from inactive and wrong voters to the stakers who voted correctly. This hardens the schelling point by adding a more punitive cost function to being wrong. Governance votes are treated as a special price request category where the slashing mechanism is not applied.

    Vote Delegation

    First class vote delegation support enabling a 1 to 1 relationship between the delegator and delegate wallets. This lets a voter delegate from a secure cold storage wallet to a hot wallet. The hot wallet can commit, reveal and claim and re-stake their rewards but cannot access the underlying stake. If desired, more complex delegation systems (pooled UMA staking with delegate voting etc) can be built on top of this externally to the core UMA contracts.

    Emergency recovery system

    The DVM 2.0 now has an emergency recovery mechanism where bonded emergency proposals can be executed to short-circuiting and bypass the normal voting mechanism. This enables the DVM to recover from any kind of internal failure mode that could occur (breakage in the commit reveal system, contract issues or other) through a permissionless upgrade flow.

    Other system wide changes

    There are a number of other changes made, including:

    1. Governance proposals now include ancillary data enabling better identifying information to be passed along to voters.

    2. Price requests now contain a unique identifier, enabling easier tracking and support in front ends.

    3. A number of gas optimizations were made throughout the protocol.

    Implementation details

    The sections below contain some details on nuanced implementation details of the DVM2.0 system.

    Staking APY

    Staking rewards (and the associated APY) consists of two discrete components: a) rewards from being staked and b) balance changes from slashing. The net staking APY you receive considers both of these values. Let's consider them separately.

    Staking rewards are a pro-rata share of a fixed emission rate, calculated on a per block basis. The rewards you are entitled to, from the last time you claimed, are calculated as follows:

    Slashing rewards & penalties at the time of DVM 2.0 launch are designed to be as simple as possible, with the ability to update them at a later point through the use of a Slashing Library. At launch, slashing penalties will be approximately equal to the rewards one would have earned for an estimated stake duration. This has been targeted based off historical DVM 1.0 vote frequency, and means that someone who stakes but does not participate in any votes (or gets all votes wrong) should have their slashed stake and accumulated rewards cancel out for a 0% APY. This amounts to losing 0.1% of your staked amount per vote that is incorrect or missed. Note that each voting round (48 hour commit-reveal cycle) can have multiple votes in it (for example multiple price requests or governance actions). The amount you earn for voting correctly is the voters pro-rata share of the slashing of the incorrect voters. This can be calculated per voter per round as follows:

    Then, the total amount slashed per round is the sum of all voters slash for that round:

    A voter, who was correct, will then earn a pro-rater share of the totalSlashPerRound as:

    A staker's net APY is therefore the sum of their stakingRewards and positiveSlashForCorrectVotePerRound annualized over a 1 year period.

    Rolled votes

    Under some situations votes can "roll". We define a rolled vote as a vote that was not resolved in one vote round and was moved into the subsequent voting round due to not successfully reaching the two types of needed quorums. These quorums are known as GAT (God Awful Threshold) and SPAT (Schelling Point Activation Threshold).

    The GAT within the DVM 2.0 is a constant amount of UMA that must vote on any given vote for it to not roll. In the DVM 1.0, this was set as a percentage of circulating UMA. At the time of DVM 2.0 initial deployment, the required GAT per vote is a constant 5 million UMA.

    The SPAT is a new concept from the DVM 2.0. It is a percentage of staked tokens that must vote and agree in order for a vote to not roll. The required SPAT is 65% currently of staked tokens.

    If a vote does not satisfy both of these constraints, it will roll.

    Vote Deletion

    There are certain situations in the DVM 2.0 where voters may want to delete votes. A good example of this would be in the case of spam deletion, where needless price requests are submitted in order by an attacker to try to create some sort of desired slashing conditions.

    In the DVM 2.0, votes are deleted once they have rolled a certain number of times. So if voters choose to not vote on the resolution of price requests, and either the GAT or SPAT are not met for a set number of voting rounds, those price requests will become deletable. At the time of DVM 2.0 initial deployment, the number of times a vote is rolled before being deleted is 4.

    Queries

    Below are some sample queries you can use to gather information from UMA contracts.

    You can build your own queries using a and enter your endpoint to limit the data to exactly what you need.

    Financial Contracts

    stakingRewards=stakedDuration∗stake∗emissionsPerBlockcumulativeStakestakingRewards = \frac{stakedDuration*stake*emissionsPerBlock}{cumulativeStake}stakingRewards=cumulativeStakestakedDuration∗stake∗emissionsPerBlock​
    slashPerVoterPerRound=∑stake∗numberOfIncorrectVotes∗0.001slashPerVoterPerRound = \sum stake * numberOfIncorrectVotes * 0.001slashPerVoterPerRound=∑stake∗numberOfIncorrectVotes∗0.001
    totalSlashPerRound=∑slashPerVoterPerRoundtotalSlashPerRound = \sum slashPerVoterPerRoundtotalSlashPerRound=∑slashPerVoterPerRound
    positiveSlashForCorrectVotePerRound=totalSlashPerRound∗stakecumlativeCorrectVoteStakepositiveSlashForCorrectVotePerRound=\frac{totalSlashPerRound*stake}{cumlativeCorrectVoteStake}positiveSlashForCorrectVotePerRound=cumlativeCorrectVoteStaketotalSlashPerRound∗stake​
    Sign up for an Infura account https://www.infura.io/ and click ‘Create New API Key’. After you create the key, you should see a list of endpoints for each network.
  • In the .env file, update the following env variables to the URL for your infura account. The underscore number at the end of the variable represents the chain ID. So RPC_PROVIDER_ALCHEMY_1 is mainnet.

    • You can use https://chainlist.org/ to find the ID by network.

    • Include the NODE_URL_324 for zksync below even though it hasn’t been added to the .env.example file yet:

  • https://nodejs.org/en/download
    https://redis.io/docs/getting-started/installation/
    relayer-v2 README
    https://github.com/nvm-sh/nvm#installing-and-updating
    https://vanity-eth.tk/
    https://docs.across.to/v/developer-docs/how-across-works/overview/disputing-root-bundles
    https://docs.across.to/v/developer-docs/how-across-works/overview/validating-root-bundles
    Liquidations

    Price Requests

    {
      financialContracts {
        id
        creator {
          id
          isRemoved
          manager
        }
        deployer {
          id
        }
        address
        collateralToken {
          id
          name
        }
        collateralRequirement
        expirationTimestamp
        totalSyntheticTokensBurned
        totalSyntheticTokensCreated
        totalTokensOutstanding
        cumulativeFeeMultiplier
        globalCollateralizationRatio
        rawTotalPositionCollateral
        totalCollateralDeposited
        totalCollateralWithdrawn
        totalPositionCollateral
        rawLiquidationCollateral
        positions {
          id
          rawCollateral
          collateral
          tokensOutstanding
          isEnded
        }
        liquidations {
          id
          status
          amountWithdrawn
        }
      }
    }
    GraphQL Explorer
    git clone https://github.com/across-protocol/relayer-v2
    redis-server
    From the README, run the three commands:
    cd relayer-v2
    yarn install
    yarn build
    RPC_PROVIDER_ALCHEMY_1=https://eth-mainnet.g.alchemy.com/v2/{API_KEY}
    RPC_PROVIDER_ALCHEMY_10=https://opt-mainnet.g.alchemy.com/v2/{API_KEY}
    RPC_PROVIDER_ALCHEMY_137=https://polygon-mainnet.g.alchemy.com/v2/{API_KEY}
    RPC_PROVIDER_ALCHEMY_42161=https://arb-mainnet.g.alchemy.com/v2/{API_KEY}
    NODE_URL_324=https://mainnet.era.zksync.io
    {
      "at": "RootBundleValidator",
      "message": "Validation results",
      "rootBundle": {
        "poolRebalanceRoot": "0x7005c47a8e476a2551d5325a6c53cd5b71f308b2ac670742ad7cceb8078a193f",
        "relayerRefundRoot": "0x9edefc2fc000e71fa1ea1c6ce666a0f8cb2d6da422c45a372585da5e3b738713",
        "slowRelayRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "proposer": "0xf7bAc63fc7CEaCf0589F25454Ecf5C2ce904997c",
        "unclaimedPoolRebalanceLeafCount": 5,
        "challengePeriodEndTimestamp": 1692117191,
        "bundleEvaluationBlockNumbers": [
          17920824,
          108255396,
          46338509,
          977154,
          121659934,
          11305323
        ],
        "proposalBlockNumber": 17920860
      },
      "valid": false,
      "invalidReason": "Disputed pending root bundle:\n.....
    // removed the rest of the invalidReason for the example
    {
      liquidations {
        id
        status
        sponsor {
          id
        }
        liquidator {
          id
        }
        disputer {
          id
        }
        liquidationId
        tokensLiquidated
        lockedCollateral
        liquidatedCollateral
        disputeBondAmount
        disputeSucceeded
        amountWithdrawn
        events {
          __typename
        }
      }
    }
    {
      priceRequests {
        id
        isResolved
        price
        latestRound {
          roundId
          snapshotId
          totalVotesRevealed
          totalRewardsClaimed
          totalSupplyAtSnapshot
          votersAmount
          votersClaimedAmount
          tokenVoteParticipationRatio
          tokenVoteParticipationPercentage
          votersEligibleForRewardsRatio
          votersEligibleForRewardsPercentage
          votersClaimedRatio
          votersClaimedPercentage
          tokensClaimedRatio
          tokensClaimedPercentage
          winnerGroup {
            votersAmount
            totalVoteAmount
          }
          groups {
            price
            totalVoteAmount
            won
            votersAmount
          }
        }
        time
        identifier {
          id
          isSupported
        }
        committedVotes(first: 2) {
          time
        }
        revealedVotes(first: 2) {
          price
          time
        }
      }
    }
    correct response

    Deposit Box

    Simple deposit box example that showcases the basic request propose lifecycle of the UMA Optimistic Oracle

    UMA Contract Lifecycle

    UMA's Optimistic Oracle allows contracts to quickly request and receive price information. A request is made when a contract submits the following parameters with a request to the Optimistic Oracle contract:

    • identifier: price identifier being requested.

    • timestamp: timestamp of the price being requested.

    • ancillaryData: additional arguments passed with the price request.

    • currency: ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.

    • reward: reward offered to a successful proposer. Will be paid by the caller. Note: this can be 0.

    Proposers respond to price requests by referencing off-chain price feeds to submit the price of an asset. In return for their work they will receive a pre-defined proposal reward set by the Requestor. To propose prices, the Proposer is required to stake a proposal bond. In the event that the price information they proposed is disputed and deemed incorrect, the Proposer will lose their bond.

    Disputers can refute a price submitted by a Proposer within the proposal liveness period by referencing their own off-chain price feeds. The proposal liveness period is a pre-defined amount of time a proposal can be disputed before the Requestor receives the price of the asset.

    If Disputers do not refute the price submitted by the Proposer within the proposal liveness period, the price is sent to the Requestor. If a proposal is disputed, the price will be submitted to UMA’s DVM and resolved after a 48-96 hour voting period.

    Integrating with the Optimistic Oracle

    We continue to use the contract as an example. The OptimisticDepositBox is a minimal financial contract that allows a user to deposit collateral into a contract and later withdraw their collateral corresponding to a desired USD amount. When the user wants to make a withdrawal, a price request is made to the Optimistic Oracle.

    Let's first take a look at the OptimisticDepositBox constructor. Optimistic Oracle price requests require the use of a whitelisted identifier and collateral. The OptimisticDepositBox uses the protocol Finder to discover UMA protocol contracts and call the isOnWhitelist method on the AddressWhitelist and the isIdentifierSupported method on the IdentifierWhitelist contract to confirm both are whitelisted before deployment.

    Example arguments used to deploy the contract can be found and tested in the . A whitelisted USDC contract is used for collateral, the Finder and Timer addresses use existing UMA ecosystem contracts that are deployed, and a price identifier that has been contract.

    Requesting a Price

    A price request is made when the requestWithdrawal is called. A depositor submits the denominatedCollateralAmount to withdrawal and a requestPrice call is constructed with the following arguments and in the :

    After price request functionality has been implemented into your contracts, you can test your changes by creating a test in the developer quickstart repo similar to the OptimisticDepositBox test below:

    Price Proposals

    The code snippets above represent the core functionality for deploying a minimal contract and requesting a price. The next step in the contract lifecycle after a request has been made is a price can be proposed.

    is the proposePriceFor function from the Optimistic Oracle contract that is used to propose a price for requests. The price proposal will revert if the parameters do not match an existing price request. For reference, the demonstrates how to call the proposePriceFor method.

    Liveness

    An important aspect to consider when using the Optimistic Oracle is the liveness period which is the number of seconds a proposal must wait before a price can be resolved and contracts can be settled. A defaultLiveness value is set (currently 7,200) or developers can set a customLiveness value.

    To set a customLiveness value with our OptimisticDepositBox example above, we could add line 5 to change the liveness period from 7,200 seconds to 3,600:

    Proposal Bond

    A proposal bond is a preloaded reward to incentivize price proposals. Similar to the liveness period, a custom bond amount can be set for a price request.

    Two important aspects to remember when setting a proposal bond is:

    • When making a price request, the caller must approve the contract to transfer the value of the proposer reward for the collateral being used.

    • The value corresponds to the collateral decimal value. So setting the reward to 1 for USDC that uses 6 decimals would be 1000000 while an 18 decimal token would be 1.

    The below shows an example of setting the proposer bond to 50 USDC (6 decimals):

    Settlement

    The OptimisticDepositBox contract uses the executeWithdrawal method to settle contracts. It first checks if a price has been resolved by calling the hasPrice method on the Optimistic Oracle which reverts if the request is not settled or settleable. If a price has been resolved, settleAndGetPrice is called.

    Audit & Bug Bounty Programs

    Security of the platform is our highest priority. All contract code and balances are publicly verifiable, and security researchers are eligible for a bug bounty for reporting undiscovered vulnerabilities.

    Audits

    OpenZeppelin has performed the following audits on UMA contracts:

    • Common and oracle directory contracts: April 28, 2020

    Additionally, OpenZeppelin audits incremental upgrades to UMA's contracts on a continuous basis. The continuous audit report can be found .

    Bug Bounty Rewards

    UMA encourages the community to audit our contracts and security; we also encourage the responsible disclosure of any issues. The bug bounty program is intended to recognize the value of working with the community of independent security researchers and sets out our definition of good faith in the context of finding and reporting vulnerabilities, as well as what you can expect from us in return.

    UMA offers substantial rewards for discoveries that can prevent the loss of assets, the freezing of assets, or harm to users.

    All rewards will be paid in $UMA, and the amount of compensation will vary depending on bug severity. Reward amounts typically correspond to severity in the following manner.

    Severity
    Reward amount in USD

    Severity is calculated according to the risk rating model based on Impact and Likelihood.

    Scope

    The scope of our bug bounty program includes any and all of UMA's production smart contracts. It does not include known issues with the intended behavior.

    In scope

    • All UMA, Oval, or Across smart contracts that are deployed to mainnet or are otherwise noted as being applicable.

    • Bot or other offchain code to support deployed smart contracts.

    Examples of what’s in scope:

    • Being able to steal funds

    • Being able to freeze funds or render them inaccessible by their owners

    Out of scope:

    • Issues that have already been submitted by another user or are already known to the UMA team

      • Note: this includes bugs known to the UMA team, but have not been disclosed due to active mitigation efforts.

    • Vulnerabilities in contracts built on top of the protocol by third-party developers (such as smart contract wallets)

    Submissions

    Please email your submissions to .

    The submission must include clear and concise steps to reproduce the discovered vulnerability.

    Terms & Conditions

    If you comply with the policies below when reporting a security issue to us, we will not initiate a lawsuit or law enforcement investigation against you in response to your report.

    We ask that you:

    • Report any vulnerability you’ve discovered promptly.

    • Avoid violating the privacy of others, disrupting our systems, destroying data, or harming user experience.

    • Use only to discuss vulnerabilities with us.

    • Keep the details of any discovered vulnerabilities confidential until they are publicly announced by Risk Labs.

    Public disclosure of the bug or the indication of an intention to exploit it on Mainnet will make the report ineligible for a bounty. If in doubt about other aspects of the bounty, most of the will apply.

    Any questions? Reach us via email (). For more information on the UMA platform, check out our and .

    All reward determinations, including eligibility and payment amount, are made at UMA’s sole discretion. UMA reserves the right to reject submissions and alter the terms and conditions of this program without notice.

    Vulnerabilities that require ownership of an admin key
  • Any files, modules or libraries other than the ones mentioned above

  • More efficient gas solutions (although these suggestions are appreciated)

  • Any points listed as an already known weaknesses

  • Any points listed in an audit report

  • Perform testing only on in-scope systems, and respect systems and activities which are out-of-scope.

  • Not engage in blackmail, extortion, or any other unlawful conduct.

  • Not be a current or former UMA Foundation employee, vendor, contractor, or the employee of an UMA vendor or contractor.

  • Low

    $250

    Medium

    $3,000

    High

    $10,000

    Critical

    up to $1,000,000

    Financial-templates directory contracts: May 12, 2020
    Updates to the Expiring Multiparty contracts and flash loan mitigations for the voting contracts: September 9, 2020
    Perpetual Multiparty template contracts: February 2, 2021
    Insured Bridge contracts: December 1, 2021
    Governance, cross-chain oracle, and optimistic rewarder contracts: January 7, 2022
    UMA Optimistic Governor Audit: July 21, 2022
    Across Token and Token Distributor Audit: July 21, 2022
    here
    OWASP
    [email protected]
    [email protected]
    Ethereum Foundation bug bounty program rules
    [email protected]
    website
    Github
    OptimisticDepositBox
    OptimisticDepositBox fixture
    whitelisted with the IdentifierWhitelist
    method
    shown above
    requestPrice interface
    Here
    developer quickstart repo
    constructor(
        address _collateralAddress,
        address _finderAddress,
        bytes32 _priceIdentifier,
        address _timerAddress
    ) nonReentrant() Testable(_timerAddress) {
        finder = FinderInterface(_finderAddress);
        require(_getIdentifierWhitelist().isIdentifierSupported(_priceIdentifier), "Unsupported price identifier");
        require(_getAddressWhitelist().isOnWhitelist(_collateralAddress), "Unsupported collateral type");
        collateralCurrency = IERC20(_collateralAddress);
        priceIdentifier = _priceIdentifier;
    }
    
    ...
    
    function _getIdentifierWhitelist() internal view returns (IdentifierWhitelistInterface) {
        return IdentifierWhitelistInterface(finder.getImplementationAddress(OracleInterfaces.IdentifierWhitelist));
    }
    
    function _getAddressWhitelist() internal view returns (AddressWhitelist) {
        return AddressWhitelist(finder.getImplementationAddress(OracleInterfaces.CollateralWhitelist));
    }
    // Deploy the OptimisticDepositBox contract.
      const optimisticDepositBox = await (
        await getContractFactory("OptimisticDepositBox", deployer)
      ).deploy(usdc.address, parentFixture.finder.address, identifier, parentFixture.timer.address);
    function requestWithdrawal(uint256 denominatedCollateralAmount)
        public
        noPendingWithdrawal(msg.sender)
        nonReentrant
    {
        OptimisticDepositBoxData storage depositBoxData = depositBoxes[msg.sender];
        require(denominatedCollateralAmount > 0, "Invalid collateral amount");
    
        // Update the position data for the user.
        depositBoxData.withdrawalRequestAmount = denominatedCollateralAmount;
        depositBoxData.withdrawalRequestTimestamp = getCurrentTime();
    
        emit RequestWithdrawal(msg.sender, denominatedCollateralAmount, depositBoxData.withdrawalRequestTimestamp);
    
        // A price request is sent for the current timestamp.
        _requestOraclePrice(depositBoxData.withdrawalRequestTimestamp);
    }
    
    .....
    
    // Requests a price for `priceIdentifier` at `requestedTime` from the Optimistic Oracle.
    function _requestOraclePrice(uint256 requestedTime) internal {
        OptimisticOracleInterface oracle = _getOptimisticOracle();
        // For other use cases, you may need ancillary data or a reward. Here, they are both zero.
        oracle.requestPrice(priceIdentifier, requestedTime, "", IERC20(collateralCurrency), 0);
    }
    await expect(optimisticeDepositBox.connect(depositor).requestWithdrawal(amountToWithdraw))
      .to.emit(optimisticDepositBox, "RequestWithdrawal")
      .withArgs(depositor.address, amountToWithdraw, requestTimestamp);
    request.expirationTime = getCurrentTime().add(
        request.customLiveness != 0 ? request.customLiveness : defaultLiveness
    );
    function _requestOraclePrice(uint256 requestedTime) internal {
        OptimisticOracleInterface oracle = _getOptimisticOracle();
        // For other use cases, you may need ancillary data or a reward. Here, they are both zero.
        oracle.requestPrice(priceIdentifier, requestedTime, "", IERC20(collateralCurrency), 0);
        oracle.setCustomLiveness(priceIdentifier, requestedTime, "", 3600);
    }
    function _requestOraclePrice(uint256 requestedTime) internal {
        OptimisticOracleInterface oracle = _getOptimisticOracle();
        // For other use cases, you may need ancillary data. Here, the ancillary data is set to zero.
        oracle.requestPrice(priceIdentifier, requestedTime, "", IERC20(collateralCurrency), 0);
        oracle.setBond(priceIdentifier, requestedTime, "", 50000000);
    }
    function _getOraclePrice(uint256 withdrawalRequestTimestamp) internal returns (uint256) {
        OptimisticOracleInterface oracle = _getOptimisticOracle();
        require(
            oracle.hasPrice(address(this), priceIdentifier, withdrawalRequestTimestamp, ""),
            "Unresolved oracle price"
        );
        int256 oraclePrice = oracle.settleAndGetPrice(priceIdentifier, withdrawalRequestTimestamp, "");
    
        // For simplicity we don't want to deal with negative prices.
        if (oraclePrice < 0) {
            oraclePrice = 0;
        }
        return uint256(oraclePrice);
    }

    FAQs

    General questions about UMA OO

    General Questions

    What is UMA?

    UMA is a decentralized protocol designed to verify real-world information onchain in a trustless and secure manner. It consists of an optimistic oracle (OO) and a data verification mechanism (DVM) to help apps trustlessly verify real-world data using economic guarantees and community resolution.

    Why does UMA matter?

    Decentralized applications need trustworthy data to function. However, blockchains and smart contracts are inherently disconnected from real-world data. UMA bridges this gap by providing a scalable, secure, and cost-effective way to verify offchain (and onchain) information without relying on a centralized oracle.

    How does UMA compare to Chainlink?

    Chainlink streams data onchain at regular intervals. UMA is a request-based, dispute-driven system that verifies data only when needed, offering cost savings and support for broader data types.

    What makes UMA different from other oracles?

    Most oracles can only process purely objective data (e.g. price feeds). UMA is uniquely built to process and verify objective and intersubjective data (e.g. sports scores, election outcomes, cultural events, etc.).

    UMA’s OO enables smart contracts to verify intersubjective claims such as “Did the Eagles win the Super Bowl?”, “Did Donald Trump say ‘Tesla’ in the debate last night?” or “Did xyz proposal pass?" All these claims are verified using a decentralized dispute resolution system backed by economic guarantees.

    Additionally, rather than pushing data onchain by default, UMA uses an optimistic system where proposed data is assumed correct unless challenged. This design allows for fast verification through the OO, while still enabling secure dispute resolution through the DVM. If a dispute is raised, a decentralized network of UMA token stakers vote on the correct answer using offchain information. This layered structure is fast when there’s consensus and robust when there’s conflict, making UMA more flexible, cost-effective, and secure than traditional oracles.

    Can UMA verify data about real-world events?

    Yes. UMA can verify outcomes of real-world events like elections, sports results, weather outcomes, or legal rulings inasmuch as there's public, credible evidence that voters can independently verify.

    Is UMA only for DeFi?

    No. UMA can be used anywhere trustless verification is needed. While its roots are in DeFi, UMA supports use cases across prediction markets, DAO governance, crosschain interop, insurance, gaming, and much more.


    How UMA Works

    What is the optimistic oracle?

    UMA’s is a decentralized verification protocol that lets anyone propose data onchain. If no one disputes the data within a predefined liveness period, it's considered verified. If disputed, the claim goes to a community vote via the DVM.

    What is the DVM?

    The is UMA’s dispute resolution system. It uses a commit-reveal voting process where UMA tokenholders vote on the correct answer to a disputed data request. Honest voters earn rewards; incorrect or absent voters are penalized.

    How long does it take to verify data with UMA’s system?

    If undisputed, data is verified after the liveness period, which is configurable and should be set based on your use case. Currently, integrations set their liveness period between 2 hours to 2 days. If undisputed, the data is verified after the liveness period. In the rare case of a dispute, the DVM vote resolves the case within 2-4 days.

    What is the economic model behind UMA?

    UMA relies on the principle of economic guarantees. Economic incentives are in place for every participant, from proposers, disputers, and voters—to ensure that everyone behaves honestly. This economic model ensures that corrupting the protocol (e.g., by submitting false data or voting dishonestly) is more expensive than the potential profit from doing so.

    Can I trust UMA without understanding how it works?

    Yes, UMA is designed to be trustless. The economic game theory ensures that data is highly likely to be accurate, even if you don’t personally verify each step.


    oSnap and DAO Tooling

    What is oSnap?

    is UMA’s governance automation tool. It connects Snapshot votes with onchain execution, letting DAOs run offchain votes and trustlessly execute them onchain with UMA’s OO securing the results. Notable users include Across, Developer DAO, Nexus Mutual, and many more.

    Does oSnap ensure the integrity of governance execution?

    Yes. By anchoring Snapshot votes to UMA’s decentralized verification process, oSnap ensures that governance outcomes cannot be tampered with between voting and execution.

    How does oSnap ensure secure governance execution?

    oSnap posts a bond-backed proposal to the OO after a Snapshot vote concludes. If no one disputes the validity of the vote outcome, the proposal is executed onchain automatically. If disputed, the DVM resolves it through tokenholder voting.


    UMA Participants (Proposers, Disputers, and Voters)

    Proposing Data

    What kinds of data can be proposed?

    Any peice of information that can be verified with public evidence or consensus: asset prices, sporting event outcomes, governance results, hack confirmations, crosschain transfers, and more.

    How do I propose data?

    Use the to submit data to the OO. Under the “Propose” tab, you can view the full list of live queries and choose which one you want to propose an answer to. You’ll need to post a bond and specify details for the request. If undisputed during the liveness window, the data is finalized and published onchain.

    What are the incentives for honest behavior as a proposer?

    When a proposer is correct, they receive a posted financial reward. However, when a proposer is incorrect, they lose their bond. This encourages honest participation. Dishonest participation can result in financial losses.

    What are the risks of participating as a proposer?

    If you propose incorrectly or too early, you risk losing your bond.

    Can I automate participation as a proposer?

    Yes. Bots can be written to monitor for proposals based on predefined logic. UMA encourages automation for higher participation, but does not provide these services.

    Disputing Data

    How do I dispute incorrect data?

    Submit a dispute through the within the liveness period. Under the “Verify” tab, you can view the full list of live proposals currently in their challenge period and choose which one you want to dispute. You'll need to post a bond and the request will escalate to the DVM for resolution.

    What are the incentives for honest behavior as a disputer?

    When a disputer is correct, they receive half of the proposer’s bond. However, when a disputer is incorrect, they lose their bond. This encourages honest participation. Dishonest participation can result in financial losses.

    What are the risks of participating as a disputer?

    If you dispute incorrectly, you risk losing your bond.

    Can I automate participation as a disputer?

    Yes. Bots can be written to monitor for proposals and auto-dispute based on predefined logic. UMA encourages automation for higher participation, but does not provide these services.

    Voting

    How do I vote on disputes?

    To vote on disputes and earn rewards, you must stake $UMA in the . From there, you can commit and reveal your votes. You cal also view upcoming votes, your $UMA rewards, and voting history.

    What is the minimum UMA token amount needed to vote?

    There is no minimum. Your influence is proportional to the amount of tokens staked, but participation is open and inclusive.

    You need to stake a minimum of 1000 $UMA to receive voting gas rebates.

    How does DVM voting work?

    DVM voting uses a commit-reveal system:

    1. Commit: Submit a hashed vote (24 hour window).

    2. Reveal: Later, reveal your vote to show your answer (24 hour window).

    How do voting rewards work?

    Rewards are paid in $UMA tokens. When you stake $UMA in the , you start earning rewards automatically. Your staked tokens receive a share of UMA emissions, displayed as an APY in the dApp (~17%).

    Disputes come through the dApp in voting rounds, in which you are responsible for participating. If you vote incorrectly or miss a vote, you lose 0.1% of your staked $UMA per incorrect vote. If you vote accurately, you earn extra rewards in proportion to your staked $UMA. These rewards are collected from inaccurate and absent voters, and are redistributed to accurate voters at the end of each voting round.

    Note: You must successfully commit and reveal your vote on time in order for your vote to count.

    For more info: read our full .

    How is the correct answer decided in UMA’s voting system

    In UMA’s DVM, the correct vote is determined by majority consensus. During the voting process, $UMA token stakers participate in a shielded commit-reveal scheme to cast their votes on disputed assertions. After the reveal period, token-weighted votes are tallied, and if any single voting option reaches the consensus threshold (currently 65% of staked UMA), it is considered the correct outcome. This reflects the collective judgment of informed participants, incentivized to vote accurately through rewards and penalties.

    Note that UMA uses the Schelling Point principle: the assumption that rational, well-informed voters will independently converge on the same answer. There’s no single source of truth, just the consensus of honest participants acting in their own best interest.

    How much can I earn for voting correctly?

    Voter APYs typically range between 16% and 21%, depending on emissions and participation. If you restake your rewards, you can capitalize on compound interest. Additionally, $UMA penalties from inaccurate and absent voters are redistributed as extra rewards to accurate voters at the end of each round.

    What happens if I vote incorrectly?

    Your staked $UMA tokens are slashed whenever you vote incorrectly. You lose approximately 0.1% of your staked amount of $UMA per vote.

    What happens if I miss a vote?

    Your staked $UMA tokens are slashed whenever you miss a vote. You lose approximately 0.1% of your staked amount of $UMA per vote

    What is P4?

    P4 is the voting option for when a proposal is submitted too early.

    Many proposals get disputed for being too early. For example, someone may submit the Eagles as the winner of the Super Bowl five minutes before the game ends. Even if the Eagles end up winning, they weren’t the winners at the time the proposal was submitted, therefore, the proposal is too early. In these situations, you should vote P4.

    Always make sure to check the proposal timestamp and take it into consideration when voting.

    Learn more about P4 .

    Voting gas is expensive. Do I get a refund?

    Yes! As long as you are staking a minimum of 1000 $UMA, you will receive an ETH gas rebate at the end of each month paid in full, gwei for gwei. See more details .

    Are there community discussions when voting on disputes?

    Yes! You can find live discussions in the and in the in the #evidence-rationale channel.

    What are the incentives for honest behavior as a voter?

    Incorrect voters are slashed, losing 0.1% of their staked $UMA per incorrect vote. Correct voters receive the slashed $UMA as a reward (in addition to their emissions APY). Therefore voters are incentivized to vote with the majority. Since votes are committed in secret, voters cannot copy other voters, and instead vote for the best answer where other voters will congregate.

    What prevents a consensus of stakers corrupting an oracle result?

    Simply put, economic incentives. All voters have staked $UMA with a one week lock up. If they corrupt an oracle result, the value of their staked $UMA will fall drastically before the can unstake and sell. This aligns voters with the long-term success of UMA and the integrity of the Optimistic Oracle.

    What are the risks of voting?

    If you vote incorrectly or miss voting rounds, you lose approximately 0.1% of your staked amount of $UMA per vote.

    Can I automate participation as a voter?

    Yes. Bots can be written to cast votes based on predefined logic. UMA encourages automation for higher participation, but does not provide these services.


    Technical Questions

    What is intersubjective data

    Intersubjective data is information that may not be purely objective, but is still publicly verifiable and widely agreed upon by informed observers. It’s the sweet spot between “hard facts” and “personal opinion.” Things like election outcomes, sports results, or whether a protocol got hacked fall into this category.

    What is a liveness period, and how is it determined?

    The liveness period, also known as the “challenge period”, is a window of time after a data proposal during which someone can raise a dispute. This duration is configurable and often depends on the use case’s sensitivity or urgency.

    The most common liveness period ranges from 2 hours to 2 days. Many prediction markets, like Polymarket, use this configuration. Across Protocol also uses a 2-hour liveness period because it best suits its crosschain interop use case.

    What chains does UMA support?

    UMA is currently deployed and fully supported (including Oracle UI, DVM support, and oSnap functionality) on the following mainnets:

    • Ethereum Mainnet

    • Polygon Mainnet


    Recent Optimistic Oracle Upgrades

    What does UMIP-183 do, and why is it useful?

    introduced the MULTIPLE_VALUES price identifier, allowing a single data request to return up to seven values. This is a major win for prediction markets, sports betting apps, and any protocol resolving multiple outcomes at once.

    By batching outcomes into one transaction, protocols can:

    • Drastically reduce gas costs.

    What is UMIP-185, and how does it improve performance?

    allows proposers to submit hashed or offchain-referenced data instead of full ancillary strings. This reduces the size of onchain transactions, which:

    • Lowers gas fees.

    • Speeds up proposal submissions.

    What is the “slow proposer penalty,” and why was it added?

    To discourage latency in oracle activity, UMA introduced a penalty for proposers who wait until the end of the liveness window to submit data. This incentivizes faster responses and ensures that applications relying on the oracle don’t get bottlenecked by late proposals.

    Faster proposers = faster oracle = better UX for users.

    How do these improvements affect the developer experience?

    All of these upgrades are designed to make UMA’s oracle more composable, efficient, and scalable. Whether you're resolving crosschain messages, prediction markets, or governance proposals, these tools help reduce cost and complexity while preserving trustlessness.


    Security

    How secure is UMA’s economic model?

    UMA’s security comes from game theory, not just code. The protocol is designed so that honest behavior is always the most profitable strategy and dishonest actions are economically irrational.

    At the core of this is UMA’s use of the Schelling Point principle: rational voters, acting independently, are incentivized to report the truth because they know others will too. Those who vote correctly earn rewards. Those who vote incorrectly or don’t vote at all are penalized via slashing.

    For an attacker to corrupt UMA’s oracle, they’d need to acquire 51% of all UMA tokens, then convince a majority of that voting power to agree on a false outcome. Not only would this be prohibitively expensive, but it would also damage the value of the token they control.

    This structure creates a powerful economic feedback loop:

    How secure is the DVM?

    To corrupt the DVM, an attacker would need to acquire 51% of all UMA tokens and convince a majority of voting power to support a dishonest resolution. This would be extremely costly, and would cost far more than the potential upside of submitting incorrect data.

    What security audits has UMA undergone?

    At UMA, we take security seriously. The protocol has undergone multiple audits by reputable firms. Notably, OpenZeppelin conducted a comprehensive audit of UMA's Across V2 contracts, providing insights and recommendations to enhance security. Additionally, UMA maintains a bug bounty program to encourage responsible disclosure of vulnerabilities. Detailed information about UMA's security audits and bug bounty program can be found in the.

    How does UMA handle potential oracle manipulations or attacks?

    UMA employs a combination of economic incentives and community consensus to mitigate the risk of oracle manipulation:

    • Participants proposing data are required to post bonds, which they forfeit if their data is successfully disputed. On the other hand, they earn rewards for proposing accurate data.

    • Disputers must also post bonds, which they forfeit if their dispute is deemed inaccurate by the DVM. On the other hand, they earn rewards for disputing inaccurate proposals.


    Compatibility and Limitations

    Are there any limitations on the types of data UMA can verify?

    UMA's oracle is designed to verify any data that is publicly available and independently verifiable. In particular, the OO and DVM are best built to process objective and intersubjective data. This includes a wide range of data types, such as asset prices, event outcomes, and real-world occurrences.

    However, the OO is not suitable for data that is purely subjective or lacks a clear, verifiable source. For instance, personal opinions or unverifiable claims fall outside the scope of what UMA can accurately verify.​

    Is UMA compatible with other oracle systems?

    Yes, UMA is designed to be complementary to other oracle systems. It can function alongside traditional oracles, providing an additional layer of verification or serving as a fallback mechanism.


    Operational Edge Cases

    What happens if a vote in the DVM is inconclusive or tied?

    In the rare event of an inconclusive or tied vote within the DVM, the dispute is rolled over into the next voting round.

    A rolled vote happens when a dispute doesn’t get resolved in the current voting round and gets pushed to the next one. This only happens if the vote doesn’t meet two quorum thresholds: GAT and SPAT.

    • GAT (God Awful Threshold) is a fixed minimum amount of UMA that must vote for the result to count. In DVM 2.0, that number is 5 million UMA.

    How does UMA handle network congestion or high gas periods?

    UMA is built to handle network congestion by operating across multiple L2s like Arbitrum and Optimism, reducing gas fees. On top of that, upgrades like UMIP-185 improve efficiency by letting proposers use hashes or pointers instead of submitting full data onchain, cutting gas costs further. UMA also offers gas rebates for voters, so participation stays affordable even in high-fee environments.


    Building and Integrating with UMA

    What developer resources are available to get started?

    Visit for integration guides, tutorials, contract templates, and walkthroughs. is also active for dev support.

    How do I integrate UMA’s optimistic oracle into my project?

    You can use UMA's OOV3 smart contracts to submit and verify data. Integration info and quick-start guides are available on UMA's .

    Are there different versions of the optimistic oracle?

    Yes. UMA’s OO is constantly being improved to evolve and serve in-demand use cases over time. Currently, there are two versions of the OO available:

    1. OOV2: Implements the use of data requests. Integrations must submit data requests that can then be answered by third-party proposers. Rules must be included in the request to establish the specific parameters for proposers and disputers to follow.

    2. OOV3

    Which version of UMA’s optimistic oracle should I use?

    The primary use cases for OOV2 include prediction markets, sports betting applications, and insurance protocols.

    The primary use cases for OOV3 include crosschain infrastructure, content moderation, transaction verification, governance, and insurance protocols.

    How customizable is the UMA oracle’s logic for unique applications?

    Very. UMA was built with flexibility in mind. You can customize nearly every parameter of a request to fit your specific use case, including:

    • Question format: You decide what you're asking and how it's phrased.

    • Liveness period: Set how long others have to challenge your data.

    Can I test UMA locally or on testnet?

    Yes. UMA offers contracts on major Ethereum testnets. Developers can simulate oracle requests, disputes, bonding, and DVM voting in staging environments. Here is the full list of supported testnet chains:

    • Ethereum Sepolia

    • Arbitrum Sepolia

    What are common use cases for UMA?
    • Prediction markets (e.g. Polymarket)

    • Crosschain bridges (e.g. Across Protocol)

    • DAO governance (e.g. oSnap with Nexus Mutual, Developer DAO)

    Why would I use UMA instead of a traditional price feed oracle?

    Price feed oracles can only handle one type of data: prices. UMA is built to handle any publicly verifiable information.

    That’s why UMA is the go-to oracle for onchain applications such as prediction markets, crosschain interop protocols, IP ownership layers, and many more—because each of these rely on access to verified intersubjective data. Price feed oracles simply can’t provide that. UMA can.

    Additionally, most traditional price feed oracles constantly push data onchain, even when it isn’t needed. This wastes gas and introduces attack vectors. UMA’s OO only verifies data when requested, making it more gas-efficient and censorship-resistant. It also supports any type of data, not just prices, allowing for use cases like governance execution, crosschain messages, and real-world event verification.

    There’s also a major cost advantage. Setting up and maintaining a price feed on traditional oracles is expensive. It often requires upfront coordination, whitelisting, and ongoing fees. UMA is fully permissionless and free to use

    How does Polymarket use UMA?

    Polymarket leverages UMA's OOV2 to resolve the outcomes of its prediction markets in a decentralized and trustless manner. When Polymarket creates a prediction market, a data query is sent to the OO. Anyone can then propose the outcome to UMA's OO, which assumes the proposed result is correct unless challenged within a 48-hour predefined dispute window.

    If a dispute arises, it is escalated to UMA's DVM, where $UMA token holders vote to determine the accurate outcome. This system allows Polymarket to handle a wide range of markets, including those based on natural language and intersubjective data, which traditional oracles cannot process.

    How does Across use UMA?

    Across is a that uses a unique variation of UMA’s OOV3 to verify crosschain Intents, which are statements of a user’s bridging transaction, before relayers are repaid. This gives Across security guarantees without needing to validate every transaction in real-time.


    Governance

    How is UMA governed?

    UMA is governed by its community of $UMA tokenholders.

    Major protocol upgrades, parameter changes, and funding decisions are proposed, discussed, and voted on by the UMA community, primarily through offchain Snapshot votes and confirmed onchain when needed.

    Proposal discussions are hosted on .

    How can I participate in UMA governance?

    To participate, hold $UMA, stake it to vote, and take part in governance proposals through the and . Important proposals are discussed in the UMA Discord and forum before voting begins.

    What kinds of decisions are made through governance?

    Governance decisions include protocol upgrades, parameter changes (such as inflation rates or bond sizes), budget allocations, grants, and strategic initiatives for UMA’s growth and development.

    How does UMA handle proposals to change protocol parameters?

    Changes to UMA’s core protocol, such as inflation rates, contract upgrades, or bond sizes, are governed directly by $UMA tokenholders. Proposals are typically discussed in the community forum and Discord, then voted on through the , which uses the same secure commit-reveal process as oracle dispute resolution.

    While Snapshot can be used for informal temperature checks, it is not where binding decisions happen. Final decisions are made through onchain voting via the DVM, ensuring that changes are trustlessly approved by the UMA community.

    What is the difference between dispute resolutions and governance votes on the Voter Dapp?

    Unlike dispute resolutions, voters who vote against the consensus on governance votes are not slashed. If a voter does not submit a vote on a governance vote, they are still slashed. This allows voters to vote their personal opinions without the economic disincentive of slashing.

    What is the difference between protocol governance and oSnap execution?

    Protocol governance refers to changing the UMA protocol itself (e.g. inflation rate, contract upgrades, etc.). oSnap is a tool built with the OO and used to execute DAO votes trustlessly. oSnap can be used by any DAO; the UMA DAO and many other notable DAOs currently uses oSnap.

    What is the role of the DVM in UMA governance?

    The DVM is the venue where all binding governance votes take place. It’s the same secure, commit-reveal voting system used to resolve oracle disputes, except instead of resolving data proposals, it’s used to approve or reject protocol upgrades, parameter changes, and funding decisions.

    In UMA, the DVM is more than a dispute resolution system. It’s the foundation of onchain governance. Every major decision made by the DAO goes through the DVM, giving $UMA tokenholders full control over the protocol’s future.


    Tokenomics

    What is the $UMA token used for?

    $UMA is the core utility and governance token of the protocol. It’s used to stake, vote, and secure the oracle. Tokenholders help verify data, resolve disputes, and steer the protocol’s direction by participating in governance. In short: UMA aligns incentives around truth.

    The value of the $UMA token is directly tied to its role in maintaining honest oracle outcomes and decentralized governance.

    What is the total supply and inflation schedule of the UMA token?

    The supply of $UMA isn’t fixed. It’s dynamic and governed by the DAO. The protocol uses controlled inflation to incentivize participation and long-term security. The current inflation rate is set at 0.05% of the total token supply, distributed to active, correct voters in the DVM.

    Learn more about the $UMA token supply .

    How are new UMA tokens distributed?

    Token emissions are controlled by governance. UMA emissions are used to provide staking rewards to stakers who vote on disputes to secure the protocol.

    Where can I track UMA's token metrics?

    The current supply of $UMA and emission rates are defined onchain and can be found .


    Community and Ecosystem

    How can I contribute to UMA beyond voting?

    There are tons of ways to get involved! You can build integrations, write code, create content, improve the docs, join governance discussions, or just hang out in the and vibe with the community. Whether you're technical or not, there's space for you to contribute.

    Are there developer grants available?

    Yes. UMA offers grants to developers and teams building tools, integrations, or initiatives that advance the ecosystem. To apply, you’ll start by posting a proposal in the category of UMA’s governance forum. From there, the community will review and provide feedback.

    If the proposal gains traction, it can proceed to a Snapshot vote, and if successful, be submitted onchain with help from Risk Labs or directly by the proposer. All grant proposals are evaluated based on their technical feasibility, ecosystem impact, and funding requirements. If you have any questions about our grant program, please reach out to us in our .

    Yes. UMA offers grants to support developers and teams building tools, integrations, or infrastructure that strengthens the ecosystem.

    To apply, start by posting your idea in the category in the UMA governance forum. The community will review and provide feedback. If your proposal gains traction, it can move to a Snapshot vote, and if approved, it’ll execute onchain with help from Risk Labs or directly by the proposer.

    What community resources exist?

    Here’s where you can plug into UMA’s community and stay up to date:

    • – Join conversations, ask questions, or just vibe.

    • – Home of governance discussions and funding proposals.

    Sandboxed Oracle Environment

    Only required for testing the dispute flow

    Whenever the assertion is disputed on a production network this triggers DVM request to be resolved by UMA voters. This might be impractical to fully simulate this in a testing environment, hence, developers can use mocked oracle contract to resolve requests as they had been returned by DVM.

    Interacting with Optimistic Oracle requires having whitelisted price identifier and bonding currency. In production networks these are approved by UMA token holders as part of governance voting. When testing, it might be easier for developers to use their own set of UMA ecosystem contracts where they have full control over such whitelisting process. Follow the written tutorial below or check out the video tutorial on Youtube.

    Deploying sandboxed Oracle environment

    A set of sandboxed UMA ecosystem contracts can be deployed using forge script from .

    After cloning the repository make sure you have the latest Foundry version by running foundryup command (see more installation details on ). From the root of the repository install dependencies with:

    All script parameters are controlled through environment variables that should be exported before running the script:

    • ETH_RPC_URL: URL of the RPC node to use for broadcasting deployment transactions on the desired test network.

    • MNEMONIC: Mnemonic of the account to use for deployment (derived account with 0 index will be used by default).

    • ETHERSCAN_API_KEY: API key for Etherscan, used for verifying deployed contracts.

    Once all required environment variables are setup, deploy and verify the set of sandboxed UMA ecosystem contracts with:

    At the top of the script output the addresses of the deployed contracts should be logged:

    • Finder: Used to locate other UMA ecosystem contract addresses. Deployment script will have added new Store, AddressWhitelist, IdentifierWhitelist, MockOracleAncillary and OptimisticOracleV3 implementations.

    • Store: Stores final fees of bonding currencies. The script will have set the final fee of default currency to half of provided minimum bond amount since Optimistic Oracle V3 calculates minimum bond twice the value of this final fee.

    Resolving dispute requests

    Whenever the assertion is disputed, Optimistic Oracle V3 calls requestPrice method on the Oracle that triggers DVM vote on mainnet. In the sandboxed environment this would resolve to MockOracleAncillary contract instead.

    The disputed request is uniquely identified by its identifier, timestamp and ancillary data that should be referenced by the testing developer pushing resolved price to the mocked oracle. The MockOracleAncillary contract will emit PriceRequestAdded event with following parameters:

    • address indexed requester: Address of the calling contract (Optimistic Oracle V3 in the sandboxed setup).

    • bytes32 indexed identifier: Identifier referencing the rules on how the request should be resolved. By default Optimistic Oracle V3 uses ASSERT_TRUTH identifier unless the integrating contract provided other value.

    • uint256 time

    Note that production voting contract on mainnet emits this differently and above PriceRequestAdded is provided only as a convenience for developers when interacting with the MockOracleAncillary contract in their testing environment.

    MockOracleAncillary contract provides two alternative methods for testing developers to resolve request:

    • pushPrice(bytes32 identifier, uint256 time, bytes memory ancillaryData, int256 price) where request is referenced by its individual parameters.

    • pushPriceByRequestId(bytes32 requestId, int256 price) where request is referenced by the hashed value of its identifying parameters.

    While testing developer can pass any int256 price value, Optimistic Oracle V3 can only interpret value of 1e18 to represent truthful assertion. Any other value would settle assertion as being false. Also note that MockOracleAncillary contract will only accept the first pushed price to resolve a given request.

    Example dispute flow

    As an illustration to the section above this example walks through resolving disputed assertion with cast tool from Foundry. This also requires jq being installed for parsing returned values.

    Just for the sake of simplicity set MINIMUM_BOND environment variable to 0 when running forge script command as discussed in the . This would allow to skip minting and approving assertion/dispute bonds. Take a note of deployed contracts log and export Optimistic Oracle V3 address to OOV3_ADDRESS and MockOracleAncillary address to MOCK_ORACLE_ADDRESS environment variables.

    Also to keep this simple perform all steps from the same address:

    Start with generating test assertion and grab the resulting assertionId emitted by Optimistic Oracle V3 (corresponds to topic index 1 in the AssertionMade event):

    Dispute the above assertion and grab the resulting requestId emitted by MockOracleAncillary (corresponds to topic index 3 in the PriceRequestAdded event):

    Now resolve the disputed assertion as truthful by pushing 1e18 as price to MockOracleAncillary contract:

    This allows us to settle the assertion at Optimistic Oracle V3:

    Finally, you can verify that Optimistic Oracle V3 has correctly settled the assertion (this should return true):

    Further sandbox configuration

    The deployment script documented in the covers most common use cases and should be sufficient to test example contracts from the . Though, when developing your own integrating contracts it might be required to further configure the sandboxed oracle environment.

    Whitelisting of bonding currencies

    In case the integrating contract requires handling assertion bonds in multiple currencies all of them should be approved at the AddressWhitelist contract. On production this should go through UMA governance while in the sandboxed environment the deployer owns this contract and can call addToWhitelist method directly. Assuming the address of AddressWhitelist contract is exported to ADDRESS_WHITELIST and required bonding currency is exported to BONDING_CURRENCY environment variables, this can be done by:

    In order to test the scenario on how the integrating contracts would behave if UMA governance removed support for a particular bonding currency, you can test this by calling removeFromWhitelist method on the AddressWhitelist contract:

    Note that Optimistic Oracle V3 is caching whitelisted bonding currencies. Hence, before testing impact on the integrating contracts somebody should sync the contract cache (anyone has authority to do this):

    Changing the final fee

    In case the UMA governance was to change the configured final fee for a particular bonding currency this would also change the minimum assertion bond required by Optimistic Oracle V3. In order to test such impact on integrating contracts in the testing environment, the deployer would need to call setFinalFee on the Store contract (exported as STORE_ADDRESS). E.g. to set final fee to 1000e18, you would call:

    Again, before testing impact on integrating contracts someone would need to sync new final fee at the Optimistic Oracle V3:

    Whitelisting of identifiers

    If the integrating contract plans to make assertions with multiple identifiers, the developer would need to add them to IdentifierWhitelist contract (exported as IDENTIFIER_ADDRESS) in the sandboxed environment, e.g. adding CUSTOM_IDENTIFIER:

    In order to test the scenario on how the integrating contracts would behave if UMA governance removed support for a particular identifier, you can test this by calling removeSupportedIdentifier method on the IdentifierWhitelist contract:

    Note that Optimistic Oracle V3 is caching whitelisted identifiers. Hence, before testing impact on the integrating contracts somebody should sync the contract cache (anyone has authority to do this):

    oSnap

    How to verify oSnap Proposals

    What is the ASSERT_TRUTH identifier?

    oSnap uses the ASSERT_TRUTH identifier can be found here. ASSERT_TRUTH is intended to be used as a default price identifier for UMA's Optimistic Oracle V3 contract that allows asserters to make claims about the state of the world.

    Price settlement can happen only in one of two ways:

    • Return the 1 value if the claim is true.

    • Return the 0 value if the claim is false or cannot be resolved.

    Part 1: Snapshot Proposal Created

    When a Snapshot proposal is created, a Discord ticket is created with a Tenderly simulation of the transaction payload. Here is an example:

    The main objective of verifying the Snapshot proposal before voting is to ensure:

    • The transaction payload can be executed

    • Comparing the intent of the proposal against the transaction payload

    • The transaction payload doesn't have any unintended consequences or malicious intent

    In the Tenderly simulation, if the Status value is not Success, that is an indicator the transaction payload is unable to be executed and requires further review.

    The input shows the transactions array that will be executed if the Snapshot proposal passes:

    Verifying the transaction data

    1. Go to .

    2. Input the contract ABI into the ABI section

      1. Take the ‘to’ value from the transaction object and input it into etherscan (or the block explorer based on the chainID. For etherscan, you would go to }.

    Here is what the example would look like:

    The ‘Output’ for a Transfer should look as the below:

    Verify the following:

    • For any BigNumber values, go to and input BigNumber.from("{INPUT_VALUE}").toString(). For example, BigNumber.from("0x14adf4b7320334b9000000").toString() would be 25000000000000000000000000. To scale this value, go to the token contract address and check decimals. For the ACX token, the decimals are 18 so the scaled value is 25000000. You can use if the decimals are 18.

    • Confirm that the above value is mentioned in the actual Snapshot proposal.

    Part 2: oSnap Transactions Proposed

    After a Snapshot proposal is completed, if the proposal is valid the transactions are proposed which creates another Discord ticket. is an example thread in the UMA Discord.

    The first objective is to verify the oSnap rules against Snapshot Proposal. Click the Snapshot space URL, in the above example that is . Go through the list of proposals and confirm the explanation from the Discord message matches the Snapshot space.

    Validators should do the following to verify the oSnap proposal:

    • Check the Snapshot space referenced in the rules string.

    • Check that the IPFS hash passed as the explanation lines up with an actual vote in that Snapshot space. They should be able to cross-reference the value with a link from a specific Snapshot proposal.

    • Check the Snapshot proposal tied to the IPFS explanation value met the minimum voting period and quorum.

    Compare Snapshot IPFS Transaction data against Proposed Transactions

    1. Go to the Snapshot proposal and click the ‘View Details’ link in the Transactions container:

    1. Copy the “transactions” array into . You should use Firefox or Brave so that backslashes “\” aren’t included in the array which will give you an error message when trying to parse:

    3. In the Discord post, click the transaction:’

    Then copy the ‘Transaction Hash’:

    Go to and paste the ‘Transaction Hash’. Then click ‘Show’ to check the input data.

    In the Discord Ticket, paste the screenshots of Tenderly and json formatter and also paste the transaction data into another thread message as below:

    The following should be verified:

    • ‘data’ from Tenderly matches the transaction data from Snapshot.

    • ‘value’ from Tenderly matches the transaction data from Snapshot.

    • ‘to’ from Tenderly matches the transaction data from Snapshot.

    • Verify the explanation:

    Event-Based Prediction Market

    Building a prediction market that uses the UMA Optimistic Oracle for settlement and event identification

    In this section, we'll talk about the , which you can find in the . This tutorial will show how event-based OO data requests can be used in a binary prediction market.

    You will find out how this smart contract works and how to test it and deploy it. Refer to the contract for additional information on the event-based price requests.

    The Event-Based Prediction Market

    This smart contract lets you set up prediction markets that are based on an event-based price request.

    New Network Requests

    The following are the evaluation criteria UMA considers when adding Optimistic Oracle support for a new network. UMA aims to support as many networks as possible to deliver the best experience for our integrating protocols and users. However, integrating a new network requires a significant investment. Therefore, the evaluation criteria were established to ensure that the benefits to UMA's integrating protocols and users outweigh the development, security, and operational costs of adding a new network.

    Please note that these requirements are subject to change as the EVM (Ethereum Virtual Machine) and Layer 2 ecosystem continue to evolve. Meeting these requirements is the initial step in our evaluation process and does not guarantee support.

    Non-Negotiable Criteria:

    The below are a pre-requisite to any consideration:

    EVM-Compatible Network a canonical token and message bridge to mainnet

  • ≥ 2 or more Independent RPC Node Providers (without block range limits for log queries)

  • 30-Day Moving Average TVL on the network > $75M

  • Block Explorer with Etherscan-Compatible API, contract verification and ABI fetching

  • Availability of token mappings data source with Ethereum mainnet

  • Dedicated support channel containing technical members of the network with priority support commitment to advise on contract development and debug data quality

  • Subgraph support for testnet and mainnet

  • Wallet connector libraries support for testnet and mainnet

  • Get in Touch with UMA

    • Drop a message in the UMA Discord Server

    • Send an email to [email protected]

    DEFAULT_IDENTIFIER: Default identifier used by Optimistic Oracle V3 when resolving disputes. If not provided, this defaults to ASSERT_TRUTH identifier. The script will also whitelist this identifier.

  • DEFAULT_LIVENESS: Default liveness in seconds used by Optimistic Oracle V3 when settling assertions. If not provided, this defaults to 7200 seconds.

  • DEFAULT_CURRENCY: Default currency used by Optimistic Oracle V3 when bonding assertions and disputes. The script will also whitelist this currency. If not provided, the script would also deploy a mintable ERC20 token and use it as the default currency based on following parameters:

    • DEFAULT_CURRENCY_NAME: Name of the new token. If not provided, this defaults to Default Bond Token.

    • DEFAULT_CURRENCY_SYMBOL: Symbol of the new token. If not provided, this defaults to DBT.

    • DEFAULT_CURRENCY_DECIMALS: Number of decimals of the new token. If not provided, this defaults to 18.

  • MINIMUM_BOND: Minimum bond amount in Wei of default currency required by Optimistic Oracle V3 when accepting new assertions. If not provided, this defaults to 100e18 Wei.

  • AddressWhitelist: Stores approved currency addresses that can be used for bonding assertions and disputes. The script will have already whitelisted the default currency.

  • IdentifierWhitelist: Stores approved identifiers that can be used to resolve disputes at DVM. The script will have already whitelisted the default identifier.

  • MockOracleAncillary: Optimistic Oracle will use this contract to resolve disputes equivalent to DVM voting on mainnet. Once requested, anyone can push desired test price through this mock oracle contract.

  • TestnetERC20: Unless existing default currency was provided the script will have deployed this new token that is whitelisted as a bonding currency. Anyone can mint new tokens by calling its allocateTo(address ownerAddress, uint256 value) method.

  • OptimisticOracleV3: Optimistic Oracle that resolves assertions made by integrating contracts.

  • : Optimistic Oracle V3 will set this to timestamp when the original assertion was made.
  • bytes ancillaryData: Optimistic Oracle V3 will put the assertionId and address of the asserter referencing the disputed assertion.

  • bytes32 indexed requestId: This is hashed value of identifier, time and ancillary data provided by the MockOracleAncillary contract just as convenient method to resolve request by one parameter instead of three separate parameters.

  • Optimistic Oracle V3 developers quick-start repository
    Foundry book
    sandbox deployment section
    section above
    Optimistic Oracle V3 integration quickstart repository
    For example, you could ask a question like, "Will BTC be over $1M when the first Moon hotel opens?"

    (Note: Although these are called "price" requests in the code, you can request any kind of data from the optimistic oracle. If it's helpful, you can mentally replace "price" with "data" when you see it in the code and documentation.)

    In addition, an event-based price request cannot expire early and automatically returns the requester's reward in the event of a dispute. By participating in the contract, users are issued long and short position tokens, which, when held, provide exposure to the prediction market. This contract's logic is a streamlined version of the LongShortPair with an event-based pricing request.

    Development environment and tests

    Clone the dev-quickstart repo

    To install dependencies, you will need to install the long-term support version of nodejs, currently nodejs v16, and yarn. You can then install dependencies by running yarn with no arguments:

    Compiling your contracts

    We will need to run the following command to compile the contracts and make the typescript interfaces so that they are easy to work with:

    Contract design

    Contract creation and initialization

    The contract is created by setting up the prediction market with a series of parameters. With the parameters, you can choose what kind of collateral you want to use with _collateralToken. With _pairName, we can choose a name for the pair of long and short tokens. _customAncillaryData is where we define the price request question. The addresses of the _finder and _timerAddress set the rest of the contracts addresses we interact with. For reference, here is the full list of UMA contract deployments.

    Once the contract has been deployed, the owner can call initializeMarket() after approving the proposerReward amount to be paid to the wallet that resolves the price request. To keep things simple, proposerReward is set to 10e18.

    Also observe how priceIdentifier is set to "YES_OR_NO_QUERY". This function sets up the prediction market by getting the proposer reward and calling _requestOraclePrice. This last function starts the price request in Optimistic Oracle V2 and sets up a number of options that are explained below.

    _requestOraclePrice is in charge of initializing the price request in the Optimistic Oracle V2 by performing the following actions:

    1. Create the price request with the above-mentioned parameters.

    2. Define the custom liveness period that a proposed oracle response must sit through before being accepted as truth.

    3. Specify the bond that the proposer and disputer must post in order to resolve a request.

    4. Set the type of request to Event Based.

    5. Turn on the priceSettled and priceDisputed callbacks so that our contract can use OO callbacks to respond to these kinds of events

    Long and Short tokens creation and redemption

    Any user can now call the create function with the tokensToCreate parameter to mint the same number of short and long tokens. Having both tokens in the same proportion means being in a neutral position, as is the case when calling create.

    Holding only long tokens (by transferring short tokens to another wallet or adding liquidity to an AMM pair), gives exposure to the long position and vice versa.

    At any time a token holder with both tokens in the same proportion can exchange them for collateral with `redeem`.

    Any long-short token holder can settle tokens for collateral with settle if the oracle has processed the price request.

    The returned collateral amount is a function of longTokensToRedeem, shortTokensToRedeem, and settlementPrice.

    Price request lifecycle callbacks: priceSettled and priceDisputed

    When the price request we set up above is settled in the Optimistic Oracle V2, the priceSettled function of this contract is invoked.

    This function calculates and stores settlementPrice as 0, 0.5, or 1. This number is used in the settle function to calculate the collateral to pay in exchange for long tokens and short tokens.

    In the same way, this contract's priceDisputed function is called when a price request is disputed. This function re-starts the same price request with the bond amount that was given back to the requester, which in our case is the EventBasedPredictionMarket.

    Tests

    To execute the EventBasedPredictionMarket tests, run:

    Deployment

    Before deploying the contract check/edit the default arguments defined in the deployment script.

    To deploy EventBasedPredictionMarket in Görli network, run:

    Optionally, you can verify the deployed contract on Etherscan:

    Event Based Prediction market contract
    developer's quick-start repo
    Optimistic Oracle V2
    forge install
    forge script \
    --broadcast \
    --fork-url $ETH_RPC_URL \
    --mnemonics "$MNEMONIC" \
    --sender $(cast wallet address --mnemonic "$MNEMONIC") \
    --verify \
    script/OracleSandbox.s.sol
    export USER_ADDRESS=$(cast wallet address --mnemonic "$MNEMONIC")
    export ASSERTION_TX=$(cast send --mnemonic "$MNEMONIC" --json $OOV3_ADDRESS "assertTruthWithDefaults(bytes,address)" $(cast --from-utf8 "test claim") $USER_ADDRESS | jq -r '.transactionHash')
    export ASSERTION_ID=$(cast receipt --json $ASSERTION_TX | jq -r --arg OOV3_LOWERCASE $(echo $OOV3_ADDRESS | tr [:upper:] [:lower:]) '.logs[] | select(.address==$OOV3_LOWERCASE).topics[1]')
    export DISPUTE_TX=$(cast send --mnemonic "$MNEMONIC" --json $OOV3_ADDRESS "disputeAssertion(bytes32,address)" $ASSERTION_ID $USER_ADDRESS | jq -r '.transactionHash')
    export REQUEST_ID=$(cast receipt --json $DISPUTE_TX | jq -r --arg MOCK_LOWERCASE $(echo $MOCK_ORACLE_ADDRESS | tr [:upper:] [:lower:]) '.logs[] | select(.address==$MOCK_LOWERCASE).topics[3]')
    cast send --mnemonic "$MNEMONIC" $MOCK_ORACLE_ADDRESS "pushPriceByRequestId(bytes32,int256)" $REQUEST_ID $(cast --to-wei 1)
    cast send --mnemonic "$MNEMONIC" $OOV3_ADDRESS "settleAssertion(bytes32)" $ASSERTION_ID
    cast call $OOV3_ADDRESS "getAssertionResult(bytes32)(bool)" $ASSERTION_ID
    cast send --mnemonic "$MNEMONIC" $ADDRESS_WHITELIST "addToWhitelist(address)" $BONDING_CURRENCY
    cast send --mnemonic "$MNEMONIC" $ADDRESS_WHITELIST "removeFromWhitelist(address)" $BONDING_CURRENCY
    cast send --mnemonic "$MNEMONIC" $OOV3_ADDRESS "syncUmaParams(bytes32,address)" $(cast --format-bytes32-string "") $BONDING_CURRENCY
    cast send --mnemonic "$MNEMONIC" $STORE_ADDRESS "setFinalFee(address,(uint256))" $BONDING_CURRENCY "($(cast --to-wei 1000))"
    cast send --mnemonic "$MNEMONIC" $OOV3_ADDRESS "syncUmaParams(bytes32,address)" $(cast --format-bytes32-string "") $BONDING_CURRENCY
    cast send --mnemonic "$MNEMONIC" $IDENTIFIER_ADDRESS "addSupportedIdentifier(bytes32)" $(cast --format-bytes32-string "CUSTOM_IDENTIFIER")
    cast send --mnemonic "$MNEMONIC" $IDENTIFIER_ADDRESS "removeSupportedIdentifier(bytes32)" $(cast --format-bytes32-string "CUSTOM_IDENTIFIER")
    cast send --mnemonic "$MNEMONIC" $OOV3_ADDRESS "syncUmaParams(bytes32,address)" $(cast --format-bytes32-string "CUSTOM_IDENTIFIER") 0x0000000000000000000000000000000000000000
    git clone [email protected]:UMAprotocol/dev-quickstart.git
    cd dev-quickstart
    yarn
    yarn hardhat compile
        constructor(
            string memory _pairName,
            ExpandedERC20 _collateralToken,
            bytes memory _customAncillaryData,
            FinderInterface _finder,
            address _timerAddress
        ) ...
    function _requestOraclePrice() internal {
        OptimisticOracleV2Interface optimisticOracle = getOptimisticOracle();
    
        collateralToken.safeApprove(address(optimisticOracle), proposerReward);
    
        optimisticOracle.requestPrice(
            priceIdentifier,
            requestTimestamp,
            customAncillaryData,
            collateralToken,
            proposerReward
        );
    
        // Set the Optimistic oracle liveness for the price request.
        optimisticOracle.setCustomLiveness(
            priceIdentifier,
            requestTimestamp,
            customAncillaryData,
            optimisticOracleLivenessTime
        );
    
        // Set the Optimistic oracle proposer bond for the price request.
        optimisticOracle.setBond(priceIdentifier, requestTimestamp, customAncillaryData, optimisticOracleProposerBond);
    
        // Make the request an event-based request.
        optimisticOracle.setEventBased(priceIdentifier, requestTimestamp, customAncillaryData);
    
        // Enable the priceDisputed and priceSettled callback
        optimisticOracle.setCallbacks(priceIdentifier, requestTimestamp, customAncillaryData, false, true, true);
    
        priceRequested = true;
    }
        function create(uint256 tokensToCreate) public requestInitialized {
            collateralToken.safeTransferFrom(msg.sender, address(this), tokensToCreate);
    
            require(longToken.mint(msg.sender, tokensToCreate));
            require(shortToken.mint(msg.sender, tokensToCreate));
    
            emit TokensCreated(msg.sender, tokensToCreate, tokensToCreate);
        }
        function redeem(uint256 tokensToRedeem) public {
            require(longToken.burnFrom(msg.sender, tokensToRedeem));
            require(shortToken.burnFrom(msg.sender, tokensToRedeem));
    
            collateralToken.safeTransfer(msg.sender, tokensToRedeem);
    
            emit TokensRedeemed(msg.sender, tokensToRedeem, tokensToRedeem);
        }
        function settle(uint256 longTokensToRedeem, uint256 shortTokensToRedeem)
            public
            returns (uint256 collateralReturned)
        {
            require(receivedSettlementPrice, "price not yet resolved");
    
            require(longToken.burnFrom(msg.sender, longTokensToRedeem));
            require(shortToken.burnFrom(msg.sender, shortTokensToRedeem));
    
            // settlementPrice is a number between 0 and 1e18. 0 means all collateral goes to short tokens and 1e18 means
            // all collateral goes to the long token. Total collateral returned is the sum of payouts.
            uint256 longCollateralRedeemed = (longTokensToRedeem * settlementPrice) / (1e18);
            uint256 shortCollateralRedeemed = (shortTokensToRedeem * (1e18 - settlementPrice)) / (1e18);
    
            collateralReturned = longCollateralRedeemed + shortCollateralRedeemed;
            collateralToken.safeTransfer(msg.sender, collateralReturned);
    
            emit PositionSettled(msg.sender, collateralReturned, longTokensToRedeem, shortTokensToRedeem);
        }
    function priceSettled(
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData,
        int256 price
    ) external {
        OptimisticOracleV2Interface optimisticOracle = getOptimisticOracle();
        require(msg.sender == address(optimisticOracle), "not authorized");
    
        require(identifier == priceIdentifier, "same identifier");
        require(keccak256(ancillaryData) == keccak256(customAncillaryData), "same ancillary data");
    
        // We only want to process the price if it is for the current price request.
        if (timestamp != requestTimestamp) return;
    
        // Calculate the value of settlementPrice using either 0, 0.5e18, or 1e18 as the expiryPrice.
        if (price >= 1e18) {
            settlementPrice = 1e18;
        } else if (price == 5e17) {
            settlementPrice = 5e17;
        } else {
            settlementPrice = 0;
        }
    
        receivedSettlementPrice = true;
    }
    function priceDisputed(
        bytes32 identifier,
        uint256 timestamp,
        bytes memory ancillaryData,
        uint256 refund
    ) external {
        OptimisticOracleV2Interface optimisticOracle = getOptimisticOracle();
        require(msg.sender == address(optimisticOracle), "not authorized");
    
        requestTimestamp = getCurrentTime();
        require(timestamp <= requestTimestamp, "different timestamps");
        require(identifier == priceIdentifier, "same identifier");
        require(keccak256(ancillaryData) == keccak256(customAncillaryData), "same ancillary data");
        require(refund == proposerReward, "same proposerReward amount");
    
        _requestOraclePrice();
    }
    yarn test test/EventBasedPredictionMarket/*
    NODE_URL_5=YOUR_GOERLI_NODE MNEMONIC=YOUR_MNEMONIC yarn hardhat deploy --network goerli --tags EventBasedPredictionMarket
    ETHERSCAN_API_KEY=YOUR_API_KEY yarn hardhat etherscan-verify --network goerli --license AGPL-3.0 --force-license --solc-input

    Resolve: Rewards and slashing is based on voting accuracy.

    Votes are shielded, meaning that voters cannot see each other's votes until after the reveal phase starts.

    Optimism Mainnet

  • Arbitrum Mainnet

  • Base Mainnet

  • Blast Mainnet

  • Core Mainnet

  • Story Mainnet

  • For the most up-to-date list of supported networks, including testnets and partially supported chains, you can find UMA's network information here.

    Simplify resolution logic.
  • Settle multiple events faster and more efficiently.

  • Use cases like Polymarket and sports betting platforms directly benefit from this added scale and flexibility.

    Makes oracle usage more cost-effective in congested markets.

    This is especially helpful for integrations that involve complex or large datasets.

    Truthful participation is rewarded.

  • Dishonesty is costly.

  • Corruption is uneconomical.

  • That’s how UMA turns incentive design into a security system at scale.

  • Voters stake $UMA, which can be slashed if they vote inaccurately or are absent for voting rounds. On the other hand, they earn staking rewards for participating and voting accurately.

  • $UMA stakers participate in securing the DVM by voting on oracle resolutions. While small slashing and reward mechanisms exist (~0.1% of stake), the real security comes from the economic incentive to protect the system. If the DVM were corrupted, UMA’s value would likely collapse, meaning attackers would lose far more than they could gain.

  • This economic structure creates a financial deterrent against dishonest behavior. The system is built in such a way where honesty is profitable and lying is expensive.

    SPAT (Schelling Point Activation Threshold) is a new rule in DVM 2.0. It requires at least 65% of staked $UMA to vote and agree on the same outcome.

    If either threshold isn’t met, the vote rolls into the next round. It's designed this way to make sure there's both broad participation and meaningful agreement before a dispute is finalized.​

    : Unlike OOV2, OOV3 doesn’t implement data requests. Instead, integrations skip that step and submit their own data proposals along with the rules. The challenge period and dispute process remains the same.

    Bond size: Increase the required stake for proposers or disputers to raise the cost of dishonest participation.

  • Resolution criteria: Add detailed instructions or requirements to help voters resolve disputes clearly and accurately.

  • Data format: You define the format of the data to be verified (e.g. booleans, multiple-choice, integers, or encoded data using upgrades like UMIP-185).

  • Optimism Sepolia

  • Polygon Mumbai

  • Polygon Amoy

  • Base Sepolia

  • Blast Sepolia

  • Core Testnet

  • Story Odyssey

  • You can view the full list of supported chains here.

  • IP dispute verification (e.g. Story Protocol)

  • AI agent verification (e.g. Axal)

  • Insurance protocol

  • . There are no fees to access the oracle. You only pay for gas and bonding if you interact with it directly.
    Grants are evaluated based on:
    • Technical feasibility

    • Ecosystem impact

    • Budget/funding needs

    Have questions? Come chat with us in Discord.

    UMA Snapshot Space – Where tokenholders vote on proposals.

  • UMA Docs – Developer documentation, guides, and protocol deep dives.

  • UMA Blog – Insights, announcements, and ecosystem updates.

  • optimistic oracle (OO)
    Data Verification Mechanism (DVM)
    oSnap
    UMA OO dApp
    UMA OO dApp
    UMA Voter dApp
    UMA Voter dApp
    Voting FAQ
    here
    here
    UMA Voter dApp
    UMA Discord server
    UMIP-183
    UMIP-185
    docs.uma.xyz
    UMA’s Discord
    developer docs
    crosschain bridge
    UMA’s Discourse page
    UMA Voter dApp
    UMA’s Snapshot Space
    UMA Voter dApp
    here
    here
    UMA Discord
    Funding Proposals
    Discord
    Funding Proposals
    UMA Discord
    UMA Discourse
    Click the ‘contract’ tab
  • Scroll down to the ‘Contract ABI’ section and copy everything

  • Paste it into the ABI section

  • Search for the token in coingecko.com with the token address and confirm there is liquidity.

    Check that the Snapshot proposal passed according to the Snapshot strategy.
  • Go to https://playground.ethers.org/ and input the following explanation to ethers.utils.toUtf8String(“{explanation}”).toString()

  • Take the returned value and input it into the following url ‘https://snapshot.4everland.link/ipfs/{explanation} and verify that the data matches from Snapshot

  • https://lab.miguelmota.com/ethereum-input-data-decoder/example/
    https://etherscan.io/address/{to
    https://playground.ethers.org/
    https://eth-converter.com/
    Here
    https://snapshot.org/#/acrossprotocol.eth
    https://jsonformatter.org/
    https://dashboard.tenderly.co/

    Network Information

    Monitored

    Risk Labs operates monitoring bots for the following networks and integrations for additional resiliency.

    UMA Contract Addresses
    Chain ID
    Fully Permissionless Settlement
    DVM Support
    Oracle UI

    Unmonitored

    The following networks are supported, but Risk Labs does not provide additional monitoring

    If you plan to integrate UMA's optimistic oracle, we recommend you run your own monitoring bots to provide additional resiliency.

    UMA's data verification mechanism (DVM), which is used to resolve disputes, is on Ethereum mainnet. Where possible, UMA uses a chain's native messaging bridge to relay dispute and governance information between that chain and Ethereum.

    On chains where no such native messaging bridge exists, UMA uses a multi-sig controlled by UMA core engineers at Risk Labs to relay disputes to the DVM, to return data from the DVM to requesters on that chain, and to execute governance actions (for instance, adding new identifiers).

    UMA Contract Addresses
    Chain ID
    Fully Permissionless Settlement
    DVM Support
    Oracle UI

    Deprecated

    UMA Contract Addresses
    Chain ID
    Fully Permissionless Settlement
    DVM Support
    Oracle UI
    {
      "method": "transfer",
      "types": [
        "address",
        "uint256"
      ],
      "inputs": [
        "9040e41eF5E8b281535a96D9a48aCb8cfaBD9a48",
        {
          "type": "BigNumber",
          "hex": "0x14adf4b7320334b9000000"
        }
      ],
      "names": [
        "to",
        "amount"
      ]
    }
    Tenderly:
    [
      {
        "to": "0x44108f0223a3c3028f5fe7aec7f9bb2e66bef82f",
        "operation": 0,
        "value": "0",
        "data": "0xa9059cbb0000000000000000000000009040e41ef5e8b281535a96d9a48acb8cfabd9a4800000000000000000000000000000000000000000014adf4b7320334b9000000"
      }
    ]
    
    Snapshot IPFS:
    [
      {
        "operation": "0",
        "data": "0xa9059cbb0000000000000000000000009040e41ef5e8b281535a96d9a48acb8cfabd9a4800000000000000000000000000000000000000000014adf4b7320334b9000000",
        "to": "0x44108f0223A3C3028F5Fe7AEC7f9bb2E66beF82F",
        "value": "0"
      }
    ]

    137

    Yes

    Yes

    (testnet)

    80002

    Yes

    No

    10

    Yes

    Yes

    42161

    Yes

    Yes

    8453

    Yes

    Yes

    (testnet)

    84532

    Yes

    No

    No

    81457

    Yes

    Yes

    (testnet)

    168587773

    Yes

    No

    No

    1514

    Multi-sig relay

    Yes

    43114

    Multi-sig relay

    Yes

    No

    No

    (Deprecated)

    1116

    n/a

    No

    No

    ((testnet)(deprecated)

    42

    n/a

    No

    No

    (testnet)(deprecated)

    4

    n/a

    No

    No

    ((testnet)(deprecated)

    5

    Yes

    No

    No

    (testnet)(deprecated)

    80001

    Yes

    No

    (testnet)(deprecated)

    421611

    Yes

    No

    No

    (Deprecated)

    100

    n/a

    No

    No

    Ethereum Mainnet (Across only)

    1

    Yes

    Yes

    Yes

    Polygon Mainnet (Polymarket only)

    137

    Yes

    Yes

    Yes

    Ethereum Mainnet

    1

    Yes

    Yes

    Yes

    Ethereum Sepolia (testnet)

    11155111

    Yes

    Story Odyssey (testnet)(deprecated)

    1516

    Yes

    No

    Yes

    Boba Mainnet (Deprecated)

    288

    n/a

    No

    No

    What types of projects are best suited to use UMA?

    Any project that requires robust, onchain data verification. The most popular use cases in production include prediction markets (e.g. ), crosschain bridges (e.g. ), DAO governance (e.g. oSnap integrations with Developer DAO, Everclear, Nexus Mutual, etc.), and IP ownership protocols (e.g. ).

    Yes
    Polygon Mainnet
    Yes
    Polygon Amoy
    Yes
    Optimism Mainnet
    Yes
    Arbitrum Mainnet
    Yes
    Base Mainnet
    Yes
    Base Sepolia
    Blast Mainnet
    Yes
    Blast Sepolia
    Story Mainnet
    Yes
    Avalanche C-Chain
    Core Mainnet
    Ethereum Kovan
    Ethereum Rinkeby
    Ethereum Göerli
    Polygon Mumbai
    Yes
    Arbitrum Rinkeby
    Gnosis Chain Mainnet
    Polymarket
    Across Protocol
    Story Protocol

    Data Asserter

    Using the Optimistic Oracle V3 to assert arbitrary off-chain data on-chain.

    This section covers the Data Asserter contract, which is available in the Optimistic Oracle V3 quick-start repo. This tutorial shows an example of how to build an arbitrary data asserter contract, using the UMA Optimistic Oracle V3 (OOV3) contract. This enables you to assert to the correctness of some off-chain process and store the output on-chain. This tutorial acts as a starting point to show how the OOV3 can be flexibility used in a sample integration.

    Data Asserter

    This smart contract allows data providers to assert the correctness of a data point, within any arbitrary data set, and bring the result on-chain. This contract is designed to be maximally open ended, enabling any kind of data to be asserted. For example, and for illustrative purposes of this tutorial, we will assert weather data on-chain. Note, though, that this kind of assertion flow and the associated OOV3 integration could build a wide range of assertions with arbitrary complexity. For example you could use the same structure to bring on-chain complex data associated with Beacon chain validator set to build a Liquid staking derivative, enable complex off-chain computation with on-chain outputs or anything that has a defined deterministic input output relationship.

    Anyone can assert a data point against the Data Asserter contract, with a known dataId and datapoint. Independent 3rd parties can then verify the correctness of this data against the dataId.

    For our example we will be asserting the output of a very simple numerical computation: 69+420. This is meant to show the basic idea without overcomplicating the off-chain part. Note, though, that the dataId prop used here could represent any kind of unique data identifier (a row in a database table, a validator address or a complex structure used to associate any kind of data to a given value.

    Development environment

    This project uses as the Ethereum testing framework. You will also need to install Foundry, refer to if you don’t have it already.

    You will also need git for cloning the repository, as well as bash shell and jq tool in order to parse transaction outputs when interacting with deployed contracts.

    Clone the UMA and install the dependencies:

    Contract implementation

    The contract discussed in this tutorial can be found at dev-quickstart-oov3/src/DataAsserter.sol () within the repo.

    Contract creation and initialization

    To initialize the state variables of the contract, the constructor takes two parameters:

    1. _defaultCurrency parameter in the constructor identifies the token used for bonds of data assertions. This token should be approved as whitelisted UMA collateral. Please check for production networks or call getWhitelist() on the contract for any of the test networks. Note that the deployed Optimistic Oracle V3 instance already has its defaultCurrency added to the whitelist, so it can also be used by the Data Asserter contract. Alternatively, you can approve a new token address with addToWhitelist method in the Address Whitelist contract if working in a sandboxed UMA environment.

    2. _optimisticOracleV3

    Asserting data

    assertDataFor method allows any data provider to assert some value of data for the associated dataId. The caller sets the asserter as the address that will receive bonds at resolution of the data assertion (this could be their address as well).

    Internally, this function pulls the associated assertion bond (global for all assertions within the DataAssertion contract) from the caller, makes an assertion call to the Optimistic Oracle V3 and stores the assertion within the contracts internal assertionsData mapping. Lastly, an event is emitted.

    For the context of this example we will be considering the dataId simply as the URL that would be called to fetch the weather data from wttr.in and the data value as the result from this call. Both are bytes32 encoded.

    The call to the Optimistic Oracle V3 looks as follows:

    Lets break this down step by step:

    • First, the value for the claim filed is constructed to be a human readable string as the concatenation of a number of different data points. This is meant to be parsable by the validation network and enable both Humans and software verifiers alike to assess the correctness of the claim. Note that within the Optimistic Oracle V3 the claim field (this prop in this function call) is not stored on-chain; it is simply emitted and is used by off-chain actors to verify the correctness of the claim.

    • Next, the asserter field is passed in from this function call. This is who will receive the bonds back at resolution of the assertion, assuming the asserter was correct.

    Resolving and subsequently fetching data assertions

    Once data has been asserted, the act of verifying it is passed over to the Optimistic Oracle V3 and the associated network of data verifiers. Due to the presence of a bond (reward for catching invalid assertions), we can be confident that in real world someone would verify this assertion (if the bond is high enough, and the liveness is long enough we have high guarantees of this).

    If the assertion passes the assertionLiveness without dispute then it can be settled. The data assertion contract showcases the OOV3's concept of assertionResolvedCallback which enables the OOV3 to settle downstream contracts that are dependent on the resolution of an assertion. Once an assertion is settleable (it has: a) passed liveness and b) not been disputed) anyone can call on the OOV3. This function acts to settle the assertion within the OO and call into the callback recipient, set during the assertDataFor function call.

    Looking within the Data Asserter contract, we can see what happens when the assertionResolvedCallback is hit from the OOV3 on settlement:

    This function effectively:

    • enforce the inbound caller is the OOV3. Else, revert

    • If the assertion was resolved as truthful (it would not be if it was disputed and the dispute proved to be correct) then:

      • set the data assertion status to true,

    Once settled, we can now call the getData function with the assertionId.This will return the data value and the accompanying resolution status (was it resolved truthfully, or not).

    Disputing data assertions

    If we want to dispute an asserted data point one must simply call the method on the OOV3. In here, you provide the associated assertionId (the same field that was returned when calling assertDataand the disputer address (the address that will receive the bonds back at the resolution of the dispute).

    Tests and deployment

    All the unit tests covering the functionality described above are available . To execute all of them, run:

    Deployment

    Before deploying and interacting with the contracts export the required environment variables. Note that there are a number of ways to interact with these contracts. The simplest setup is to fork Goerli testnet into a local development environment, using Anvil, and run the steps against the fork. To create an Anvil fork run the following:

    Replacing xxx with your infura key. This will create a local fork of the Goerli testnet, running on 127.0.0.1:8545. It will also expose a test mnemonic that you can use which has pre-loaded Eth within the fork.

    (Note: to set environment variables, as those listed below, use the export syntax in your shell. for example export ETH_RPC_URL=XXX

    • ETHERSCAN_API_KEY: your secret API key used for contract verification on Etherscan if deploying on a public network (not required if you want to do this against a local testnet).

    • ETH_RPC_URL: your RPC node used to interact with the selected network. For this tutorial it will be easiest to do this against the Goerli fork by setting ETH_RPC_URL=http://127.0.0.1:8545

    • MNEMONIC

    Use cast command from Foundry to locate the address of Optimistic Oracle V3 and its default bonding token:

    You should be able to see both of these values set in your env with echo $OOV3_ADDRESS and echo $DEFAULT_CURRENCY_ADDRESS

    To deploy the Data Asserter contract, run forge create command.

    (Note if you hit an error like Error accessing local wallet. Did you set a private key, mnemonic or keystore? then you might be hitting a foundry related issue that should be resolved by updating your foundry installation with foundryup.

    Finally, we can verify the deployed (if deployed to a public network) contract with forge verify-contract:

    Interacting with deployed contract

    The following section provides instructions on how to interact with the deployed contract from the foundry cast tool, though one can also use it for guidance for interacting through another interface (e.g. Remix or Etherscan).

    Initial setup

    Export derivation index for the asserting user that will be needed when signing transactions:

    Make sure the user address above have sufficient funding for the gas to execute the transactions.

    Next, set up the bytes32 encoding for the dataId and data, as discussed in the section. The dataId field will be the simplest command that can be re-produced by independent verifiers. We use bc (arbitrary-precision arithmetic language and calculator) that should be available on most operating systems:

    The data field will be the asserted output of the above bc command:

    Note that at any point you can look at your env by running printenv within your console to see the things we've set up to this point.

    Asserting the data point

    Next, we will call the Data Asserter contract and assert the data point and data ID that we set within our environment. Note that on the Goerli testnet the default bond for the default currency is set to 0. This is done to somewhat simplify the interactions: you don't need to mint yourself any USDC and you don't need to approve the Data Asserter to pull it from your account. Clearly, this is different to how this would be structured in reality but for demonstration purposes it keeps thing easier.

    What we are doing here is calling the assertDataFor(bytes32,bytes32,address)with the props DATA_ID, DATA and DATA_ASSERTER, that we set earlier. We are taking the output of the transaction and storing the transactionHash within the ASSERTION_TX variable.

    We can fetch the associated assertionId from the DataAssertionResolved event that should be the last event in the assertion transaction. The emitted event has the structure:

    We can fetch indexed props from cast by using the receipt function in conjunction with jq. To fetch the 3rd indexed prop (assertionId) from the last event, we would run:

    Next, we can view the data asserted object using the --abi-decode call. This will return the props in the assertionData mapping, relating to this structure:

    The last prop in the output (resolved) should be false at this moment.

    Settling the assertion

    Now, let's move forward 2 hours to go pass the challenge window of the assertion:

    Now, we can submit the settlement transaction to the OOV3 as we've passed liveness:

    If we call the assertionData mapping again, we'll see that the assertion has settled. The last prop in the output (resolved) should be true:

    We can now call the getData method directly and store output in IS_RESOLVED and RESOLVED_DATA variables:

    IS_RESOLVED should now be true:

    The decoded value of RESOLVED_DATA should be 489 as originally asserted:

    Conclusion

    This tutorial has shown you how to use the Data Asserter sample tutorial, along with the Optimistic Oracle V3. This is meant to act as a starting point for further contracts to be built on. Next steps should be looking at the other OOV3 tutorials or trying to build your own integration! If you have questions please message us on Discord or create a Github issue and we'll happily help you with your integration.

    Escalation Managers

    Using the full policy escalation manager as an example for modular functionality you could implement with custom escalation managers

    Table of Contents

    is used to locate the address of UMA Optimistic Oracle V3. Address of
    OptimisticOracleV3
    contact can be fetched from the relevant
    file, if you are on a live network, or you can provide your own contract instance if deploying UMA Oracle contracts in your own sandboxed testing environment.

    Next, we have the callback recipient set to address(this). The OOV3 has the concept of callbacks wherein at the settlement of an assertion the asserter can choose to optionally call out from the OO into another contract. In this context, we want the OOV3 to call back into the Data Asserter contract when the assertion is settled (this will become clearer in the following section).

  • We have no Sovereign security enabled here (this is an advanced topic and does not need to be covered here).

  • Default liveness, bond and identifier are set.

  • No domain is set (this is an external concept that helps 3rd parties identify assertions).

  • remove the data from the temporary dataAssertion structure
  • if it was resolved as not truthful (deleted) then simply delete it from the temp structure assertionsData

  • : your passphrase used to derive private keys of deployer (index 0) and any other addresses interacting with the contracts. The simplest setup with this is to re-use the Anvil default unlocked accounts, if you are using the local testnet environment, you can have:
  • FINDER_ADDRESS: address of the Finder contract used to locate other UMA ecosystem contracts (in order to resolve disputes you would need to use the one from a sandboxed environment). For Goerli, you can use:

  • forge
    Foundry installation documentation
    Optimistic Oracle V3 quick-start repository
    here
    Approved Collateral Types
    Address Whitelist
    settleAssertion
    disputeAssertion(bytes32 assertionId, address disputer)
    here
    Asserting Data
    networks
    export FINDER_ADDRESS=0xE60dBa66B85E10E7Fd18a67a6859E241A243950e
    git clone https://github.com/UMAprotocol/dev-quickstart-oov3.git
    cd dev-quickstart-oov3
    forge install
        constructor(address _defaultCurrency, address _optimisticOracleV3) {
            defaultCurrency = IERC20(_defaultCurrency);
            oo = OptimisticOracleV3Interface(_optimisticOracleV3);
            defaultIdentifier = oo.defaultIdentifier();
        }
        function assertDataFor(
            bytes32 dataId,
            bytes32 data,
            address asserter
        ) public returns (bytes32 assertionId) { ... }
            assertionId = oo.assertTruth(
                abi.encodePacked(
                    "Data asserted: 0x", // in the example data is type bytes32 so we add the hex prefix 0x.
                    ClaimData.toUtf8Bytes(data),
                    " for dataId: 0x",
                    ClaimData.toUtf8Bytes(dataId),
                    " and asserter: 0x",
                    ClaimData.toUtf8BytesAddress(asserter),
                    " at timestamp: ",
                    ClaimData.toUtf8BytesUint(block.timestamp),
                    " in the DataAsserter contract at 0x",
                    ClaimData.toUtf8BytesAddress(address(this)),
                    " is valid."
                ),
                asserter,
                address(this), // Callback recipient
                address(0), // No sovereign security.
                assertionLiveness,
                defaultCurrency,
                bond,
                defaultIdentifier,
                bytes32(0) // No domain.
            );
    // OptimisticOracleV3 resolve callback.
        function assertionResolvedCallback(bytes32 assertionId, bool assertedTruthfully) public {
            require(msg.sender == address(oo));
            // If the assertion was true, then the data assertion is resolved.
            if (assertedTruthfully) {
                assertionsData[assertionId].resolved = true;
                DataAssertion memory dataAssertion = assertionsData[assertionId];
                emit DataAssertionResolved(dataAssertion.dataId, dataAssertion.data, dataAssertion.asserter, assertionId);
                // Else delete the data assertion if it was false to save gas.
            } else delete assertionsData[assertionId];
        }
    forge test --match-path *DataAsserter*
    anvil --fork-url https://goerli.infura.io/v3/xxx
    export OOV3_ADDRESS=$(cast call $FINDER_ADDRESS "getImplementationAddress(bytes32)(address)" \
    	$(cast --format-bytes32-string "OptimisticOracleV3"))
    export DEFAULT_CURRENCY_ADDRESS=$(cast call $OOV3_ADDRESS "defaultCurrency()(address)")
    export DATA_ASSERTER=$(forge create --json src/DataAsserter.sol:DataAsserter \
    	--mnemonic "$MNEMONIC" \
    	--constructor-args $DEFAULT_CURRENCY_ADDRESS $OOV3_ADDRESS \
    	| jq -r .deployedTo)
    forge verify-contract \
    	--chain-id $(cast chain-id) \
    	--constructor-args $(cast abi-encode "constructor(address,address)" \
    	$DEFAULT_CURRENCY_ADDRESS $OOV3_ADDRESS) $DATA_ASSERTER DataAsserter
    export ASSERTER_ID=1
    export DATA_ID=$(cast --format-bytes32-string "echo '69+420' | bc")
    echo "DATA_ID=$(echo $DATA_ID)"
    export DATA=$(cast --format-bytes32-string $(echo '69+420' | bc))
    echo "DATA=$(echo $DATA)"
    export ASSERTION_TX=$(cast send --json \
    	--mnemonic "$MNEMONIC" --mnemonic-index $ASSERTER_ID \
    	$DATA_ASSERTER \
    	"assertDataFor(bytes32,bytes32,address)" $DATA_ID $DATA $DATA_ASSERTER \
    	| jq -r .transactionHash)
        event DataAssertionResolved(
            bytes32 indexed dataId,
            bytes32 data,
            address indexed asserter,
            bytes32 indexed assertionId
        );
    export ASSERTION_ID=$(cast receipt --json $ASSERTION_TX | jq -r .logs[-1].topics[3])
        struct DataAssertion {
            bytes32 dataId; // The dataId that was asserted.
            bytes32 data; // This could be an arbitrary data type.
            address asserter; // The address that made the assertion.
            bool resolved; // Whether the assertion has been resolved.
        }
    cast --abi-decode "assertionsData(bytes32)(bytes32,bytes32,address,bool)" \
    	$(cast call $DATA_ASSERTER "assertionsData(bytes32)" $ASSERTION_ID)
    cast rpc evm_increaseTime 7200
    cast rpc evm_mine
    cast send --mnemonic "$MNEMONIC" $OOV3_ADDRESS "settleAssertion(bytes32)" $ASSERTION_ID
    cast --abi-decode "assertionsData(bytes32)(bytes32,bytes32,address,bool)" \
    	$(cast call $DATA_ASSERTER "assertionsData(bytes32)" $ASSERTION_ID)
    read -r IS_RESOLVED RESOLVED_DATA \
    	< <(cast --abi-decode "getData(bytes32)(bool,bytes32)" \
    	$(cast call $DATA_ASSERTER "getData(bytes32)" $ASSERTION_ID) \
    	| awk '{s=(NR==1?s:s " ")$0}END{print s}') 
    echo $IS_RESOLVED
    cast --parse-bytes32-string $RESOLVED_DATA
    export MNEMONIC="test test test test test test test test test test test junk"
    Use Cases
  • Events

  • Functions

  • Getting Started

  • Introduction

    The Full Policy Escalation Manager is an example implementation of Escalation Manager that allows for a high level of control over the arbitration process in the Optimistic Oracle V3. It can be used to set various policy parameters such as who is able to assert truths, who is able to file disputes, and whether disputes should be arbitrated via the escalation manager or the UMA Data Verification Mechanism (DVM). By using the Escalation Managers, such as the Full Policy Escalation Manager, users can better tailor the arbitration process to suit their specific needs and security requirements.

    An Escalation Manager is a smart contract that is used in the Optimistic Oracle V3 to handle the escalation policy for assertions and can also be used to arbitrate disputes. When one party makes an assertion, it might be challenged by another, known as the disputer. In the event of a dispute, the Escalation Manager is used to decide how the dispute should be handled and how the Optimistic Oracle V3 should respond to it.

    The Full Policy Escalation Manager is an Escalation Manager implementation that allows the contract owner to set all policy parameters and store arbitration resolutions for the Escalation Manager.

    Some of the key functionality that the Full Policy Escalation Manager allows are:

    • Enabling a whitelist of asserting callers, asserters and disputers. This allows the owner to limit who can assert truths, and who can dispute assertions.

    • Determining whether disputes should be arbitrated by the Escalation Manager or by the Data Verification Mechanism (DVM).

    • Determining whether the resolution of a potential dispute arbitrated by the Oracle should be disregarded (i.e a disputed assertion defaults to false outcome).

    • Storing and managing the arbitration resolutions for a given identifier, time and ancillary data.

    This smart contract is ideal for use cases where a high degree of control over the behaviour of the Escalation Manager is needed, and where the owner wants to have a say in how disputes are handled and acts as a good starting point for projects that want to build their own escalation managers that implement custom logic.

    Use Cases

    The FullPolicyEscalationManager can be used in a variety of ways depending on the specific needs of the project. Below are a few examples of possible use cases and how to configure the escalation manager for each:

    • Blocking assertions by untrusted parties: In this case, the project may want to prevent assertions from being made by certain parties that are not trusted. To accomplish this, the blockByAssertingCaller and/or blockByAsserter parameters can be set to true and the corresponding whitelists can be populated with trusted parties using the setAssertingCallerWhitelist and setAsserterWhitelist functions.

    • Validation of disputers: In some cases, the project may want to prevent disputes from being filed by untrusted parties. To accomplish this, the validateDisputers parameter can be set to true and the whitelistedDisputeCallers whitelist can be populated with trusted parties using the setDisputeCallerWhitelist function.

    • Allowing arbitration via the escalation manager: By default, disputes are arbitrated via the UMA DVM. However, in some cases, the project may want to use the escalation manager to arbitrate disputes instead. To accomplish this, the arbitrateViaEscalationManager parameter can be set to true.

    • Discarding the oracle resolution: In some cases, the project may want to disregard the oracle's resolution when arbitrating disputes. To accomplish this, the discardOracle parameter can be set to true.

    • Custom arbitration resolution: If the project wants to define a custom resolution for a given identifier, time, and ancillary data, it can be set using the setArbitrationResolution function.

    • Mixing different options: The FullPolicyEscalationManager can be customized to mix different options, such as allowing arbitration via the escalation manager, but also blocking assertions by untrusted parties, or validating disputers but also allowing custom arbitration resolution.

    It's important to note that the values of blockByAssertingCaller, blockByAsserter, validateDisputers, arbitrateViaEscalationManager, discardOracle are set to false by default.

    Events

    • EscalationManagerConfigured: Emitted when the escalation manager is configured using the configureEscalationManager function. The event contains the following parameters:

      • blockByAssertingCaller: A boolean indicating whether assertions are allowed only by whitelisted asserting callers.

      • blockByAsserter: A boolean indicating whether assertions are allowed only by whitelisted asserters.

      • validateDisputers: A boolean indicating whether the escalation managershould validate disputers via the whitelistedDisputeCallers mapping.

      • arbitrateViaEscalationManager: A boolean indicating whether it is determined that the escalation manager should arbitrate disputes.

      • discardOracle: A boolean indicating whether the escalation manager should disregard the Oracle’s resolution of disputes.

    • ArbitrationResolutionSet: Emitted when an arbitration resolution is set using the setArbitrationResolution function. The event contains the following parameters:

      • identifier: The identifier of the assertion.

      • time

    • DisputeCallerWhitelistSet: Emitted when a dispute caller is added or removed from the whitelistedDisputeCallers mapping using the addDisputeCallerToWhitelist and removeDisputeCallerFromWhitelist functions. The event contains the following parameters:

      • disputeCaller: The address of the dispute caller that was added or removed from the whitelist.

    • AssertingCallerWhitelistSet: Emitted when an asserting caller is added or removed from the whitelistedAssertingCallers mapping using the addAssertingCallerToWhitelist and removeAssertingCallerFromWhitelist functions. The event contains the following parameters:

      • assertingCaller: The address of the asserting caller that was added or removed from the whitelist.

    • AsserterWhitelistSet: Emitted when an asserter is added or removed from the whitelistedAsserters mapping using the addAsserterToWhitelist and removeAsserterFromWhitelist functions. The event contains the following parameters:

      • asserter: The address of the asserter to add.

    Functions

    getAssertionPolicy

    This function returns the Assertion Policy defined by the contract's parameters and functions.

    Parameters

    • assertionId: the ID of the assertion to get the policy for.

    Returns

    • AssertionPolicy memory: an object that contains the following properties:

      • blockAssertion: a boolean indicating whether the assertion is blocked or not.

      • arbitrateViaEscalationManager: a boolean indicating whether the arbitration should be done via the escalation manager if it is configured.

      • discardOracle: a boolean indicating whether to ignore the Oracle (DVM or EM) resolution if it is configured.

      • validateDisputers: a boolean indicating whether to validate disputers if it is configured.

    Notes

    If no configuration is done after deployment, this function returns an all false default policy.

    getPrice

    The getPrice function allows developers to retrieve the resolved price for a given identifier and timestamp. It replicates the interface of the corresponding DVM function to allow the user to use his own dispute arbitration system when arbitrating via the escalation manager in a DVM-compatible manner. It is useful when you want to get the resolved price for a specific request.

    Parameters

    • identifier: A unique identifier that identifies the price requested.

    • time: A unix timestamp of the price request.

    • ancillaryData: Arbitrary data appended to a price request to give the voters more info from the caller.

    Returns

    • int256: representing the resolved price for the given identifier and timestamp.

    Notes

    If the price is not available, the method reverts. Also, the function requires that the arbitration resolution has been set before calling it.

    isDisputeAllowed

    This function returns whether a given disputerCaller is authorized to dispute a given assertionId or not.

    Parameters

    • assertionId: The ID of the assertion to check the disputerCaller for.

    • disputeCaller: The address of the disputeCaller to check.

    Returns

    • bool: true if the disputerCaller is authorized to dispute the assertion, false otherwise.

    Notes

    • In order for this function to be used by the Optimistic Oracle V3, validateDisputers must be set to true.

    • The whitelistedDisputeCallers is a mapping that contains the addresses of the authorized disputers, which are set through the setDisputeCallerInWhitelist function.

    configureEscalationManager

    This function is used to configure the escalation manager and define the assertion policy for each configuration's rules.

    Parameters

    • _blockByAssertingCaller: A boolean value that indicates if assertions are allowed only by whitelisted asserting callers.

    • _blockByAsserter: A boolean value that indicates if assertions are allowed only by whitelisted asserters.

    • _validateDisputers: A boolean value that indicates if the escalation manager should validate disputers via whitelistedDisputeCallers.

    • _arbitrateViaEscalationManager: A boolean value that indicates if the escalation manager should arbitrate instead of the DVM.

    • _discardOracle: A boolean value that indicates if the escalation manager should disregard the Oracle's (DVM or EM) resolution.

    Notes

    • This function can only be called by the contract's owner.

    • It is important to note that this function only activates the rules that will be executed, each rule must additionally be defined using the other functions.

    • The _blockByAsserter must be true if _blockByAssertingCaller is true.

    • When this function is called, an event EscalationManagerConfigured is emitted with the parameters of the function call.

    setArbitrationResolution

    This function is used to set the arbitration resolution for a given identifier, time, and ancillary data. This function should be used by the contract owner whenever a dispute arises and it should be arbitrated by the Escalation Manager. The owner of the contract is responsible for determining how to resolve the dispute.

    Parameters

    • identifier: A unique identifier that represents the price requested. This is used to identify the price request in question.

    • time: A unix timestamp of the price request.

    • ancillaryData: Arbitrary data that is appended to a price request to give the voters more information from the caller.

    • arbitrationResolution: A boolean value that indicates if the assertion should be resolved as true (true) or false (false).

    Notes

    • This function is only callable by the owner of the contract.

    • This function requires that the arbitrationResolutions[requestId].valueSet is equal to false, otherwise the function will revert with the error message "Arbitration already resolved".

    • A ArbitrationResolutionSet event is emitted with the parameters identifier, time, ancillaryData, and arbitrationResolution when this function is called.

    • The getRequestId function is used to generate a requestId to uniquely identify the price request. The requestId is generated from the identifier, time, and ancillaryData parameters.

    setDisputeCallerInWhitelist

    The setDisputeCallerInWhitelist function allows the owner of the FullPolicyEscalationManager contract to add or remove a given address (disputeCaller) to the whitelist of addresses that are able to file disputes.

    Parameters

    • disputeCaller: The address of the dispute caller to add or remove from the whitelist.

    • value: A boolean value that represents whether the disputeCaller is being added (true) or removed (false) from the whitelist.

    Notes

    This function is only used if the validateDisputers parameter is set to true. When a dispute caller is added or removed from the whitelist, the DisputeCallerWhitelistSet event is emitted with the disputeCaller and value as the arguments.

    setWhitelistedAssertingCallers

    This function allows the owner of the contract to add or remove an address from the whitelist of asserting callers that are authorized to make assertions.

    Parameters

    • assertingCaller: The address of the asserting caller to add or remove from the whitelist.

    • value: A boolean value that represents whether the asserting caller is being added (true) or removed (false) from the whitelist.

    Notes

    • This function can only be called by the owner of the contract.

    • An event AssertingCallerWhitelistSet is emitted upon the successful execution of this function, which includes the assertingCaller and the value as the arguments.

    • The whitelist of asserting callers is used when the blockByAssertingCaller configuration is set to true. In this case, only addresses in the whitelist are allowed to make assertions.

    setWhitelistedAsserters

    This function allows an owner to add or remove an address from the whitelist of authorized asserters.

    Parameters

    • asserter: The address of the asserter to add or remove from the whitelist.

    • value: A boolean value that determines whether the asserter is added or removed from the whitelist. true represents adding the asserter to the whitelist and false represents removing the asserter from the whitelist.

    Notes

    • This function can only be called by the contract owner.

    • This function must be used in conjunction with setWhitelistedAssertingCallers in order to have an effect. This means that if setWhitelistedAssertingCallers is set to true, the assertion will only be made by an address that is in both whitelists whitelistedAssertingCallers and whitelistedAsserters.

    • When an asserter is added or removed from the whitelist, an event AsserterWhitelistSet is emitted with the asserter and value as the arguments.

    Getting started

    To get started with the Full Policy Escalation Manager, the first step is to deploy the contract on the EVM network. This can be done using hardhat and a library such as ethers.js. Here is an example of how to deploy the contract:

    Once the contract is deployed, it can be configured to handle disputes in different ways, depending on the use case. The configureEscalationManager function can be used to set the rules for how disputes should be handled. Here are some examples of how to configure the contract for different use cases:

    Example 1:

    Example 2:

    Example 3:

    The Full Policy Escalation Manager can be configured for a variety of use cases depending on the requirements. The examples above show how to deploy the contract, configure it for different use cases and whitelist asserting callers, asserters and disputers. Keep in mind that the contract can only be configured by the owner and that the parameters of configureEscalationManager function must be set according to the desired use case.

    Introduction

    Insurance Claim Arbitration

    Using the Optimistic Oracle to allow for verification of insurance claims

    This section covers the insurance claims arbitration contract, which is available in the developer's quick-start repo. This tutorial shows an example of how insurance claims can be resolved and settled through the Optimistic Oracle V2 contract.

    You will find out how to test and deploy this smart contract and how it integrates with the Optimistic Oracle.

    Insurance Arbitrator Contract

    This smart contract allows insurers to issue insurance policies by depositing the insured amount, designating the insured beneficiary, and describing the insured event.

    Anyone can submit a claim that the insured event has occurred at any time. Insurance Arbitrators resolve the claim through the Optimistic Oracle by passing a question with a description of the insured event in ancillary data using the YES_OR_NO_QUERY price identifier specified in .

    If the claim is confirmed and settled through the Optimistic Oracle, this contract automatically pays out insurance coverage to the beneficiary. If the claim is rejected, the policy continues to be active and ready for subsequent claim attempts.

    Development environment and tests

    Clone repository and Install dependencies

    Clone the UMA dev-quickstart repository and install the dependencies. To install dependencies, you will need to install the long-term support version of nodejs, currently Nodejs v16, and yarn. You can then install dependencies by running yarn with no arguments:

    Compiling your contracts

    We will need to run the following command to compile the contracts and make the Typescript interfaces so that they are easy to work with:

    Contract implementation

    The contract discussed in this tutorial can be found at dev-quickstart/contracts/InsuranceArbitrator.sol () within the repo.

    Contract creation and initialization

    _finder parameter in the constructor points the Insurance Arbitrator to the Finder contract that stores the addresses of the rest of the UMA contracts. The Finder address can be fetched from the relevant file, if you are on a live network, or you can provide your own Finder instance if deploying UMA in your own sandboxed testing environment.

    _currency parameter in the constructor identifies the token used for settlement of insurance claims, as well as the bond currency for proposals and disputes. This token should be approved as whitelisted UMA collateral. Please check for production networks or call getWhitelist() on the contract for any of the test networks.

    Alternatively, you can approve a new token address with addToWhitelist method in the Address Whitelist contract if working in a sandboxed UMA environment.

    _timer is used only when running unit tests locally to simulate the advancement of time. For all the public networks (including testnets) the zero address should be used.

    As part of initialization, the oo variable is set to the address of the OptimisticOracleV2 implementation as discovered through getImplementationAddress method in the contract.

    Issuing insurance

    issueInsurance method allows any insurer to deposit insuredAmount of currency tokens by designating an insurance beneficiary (insuredAddress) and defining the insured event (insuredEvent). Before calling this method, the insurer should have approved this contract to spend the required amount of currency tokens.

    Internally, the issued policy is stored in the insurancePolicies mapping using the calculated policyId key that is generated by hashing the current block number with the provided insurance parameters in the internal _getPolicyId function.

    After pulling insuredAmount from the caller in the issueInsurance method, the contract emits a PolicyIssued event including the policyId parameter that should be used when claiming insurance.

    Submitting insurance claim

    Anyone can submit an insurance claim on the issued policy by calling the submitClaim method with the relevant policyId parameter. This method will initiate both a data request and proposal with the Optimistic Oracle. A proposal bond is required, hence the caller should have approved this contract to spend the required amount of currency tokens for the proposal bond.

    After checking that the policyId represents a valid unclaimed insurance policy, the contract gets the current timestamp and composes ancillaryData that will be required for making requests and proposals to the Optimistic Oracle:

    The resulting timestamp and ancillaryData parameters are hashed in the internal _getClaimId method that is used as a key when storing the linked policyId in the insuranceClaims mapping. This information will be required when receiving a callback from the Optimistic Oracle.

    The concatenated ancillaryData will have a valid question as specified in for YES_OR_NO_QUERY price identifier.

    An Optimistic Oracle data request is initiated without providing any proposer reward since the proposal will be done within the submitClaim method:

    Before the proposal is made, the Optimistic Oracle allows the requesting contract (this Insurance Arbitrator) to set additional parameters like bonding, liveness, and callback settings. This requires passing the same priceIdentifier, timestamp, and ancillaryData parameters to identify the request.

    Total bond to be pulled from the claim initiator consists of the Optimistic Oracle proposer bond and final fee for the relevant currency token. This contract sets the proposer bond as a fixed percentage (constant oracleBondPercentage) from insuredAmount. When calling the setBond method, the Optimistic Oracle calculates and returns the total bond that would be pulled when making the proposal:

    Optimistic Oracle liveness is set by calling the setCustomLiveness method. This contract uses 24 hours so that verifiers have sufficient time to check the claim, but one can adjust the optimisticOracleLivenessTime constant for testing. (You probably don't want to wait a full day to resolve your test requests!)

    In contrast to earlier versions, the Optimistic Oracle V2 by default does not use callbacks and requesting contracts have to explicitly subscribe to them if intending to perform any logic when a data request has changed state. Here, in calling setCallbacks, this contract only subscribes to a callback for settlement, as implemented in the priceSettled method. (Note: Subscribing to any other callbacks that are not implemented in the requesting contract would make data requests unresolvable.)

    After totalBond amount of currency token is pulled from the claim initiator and approved to be taken by Optimistic Oracle, this contract proposes 1e18 representing an answer of YES to the raised question. Requesting and proposing affirmative answers atomically allows us to reduce the number of steps taken by end users and it is most likely expected that the insured beneficiary would be initiating the claim.

    Disputing insurance claim

    For the sake of simplicity this contract does not implement a dispute method, but the disputer can dispute the submitted claim directly through Optimistic Oracle before the liveness passes by calling its disputePrice method:

    The disputer should pass the address of this Insurance Arbitrator contract as requester and all the other parameters from the original request when the claim was initiated as emitted by the Optimistic Oracle in its RequestPrice event.

    If the claim is disputed, the request is escalated to the UMA DVM and it can be settled only after UMA voters have resolved it. To learn more about the DVM, see the docs section on the DVM: .

    Settling insurance claim

    Similar to disputes, claim settlement should be initiated through the Optimistic Oracle contract by calling its settle method with the same parameters:

    In case the liveness has expired or a dispute has been resolved by the UMA DVM, this call would initiate a priceSettled callback in the Insurance Arbitrator contract:

    Based on the received callback parameters, this contract can identify the relevant claimId that is used to get the stored insurance policy:

    Importantly, all callbacks should be restricted to accept calls only from the Optimistic Oracle to avoid someone spoofing a resolved answer:

    Depending on the resolved answer, this contract would either pay out the insured beneficiary and delete the insurance (in case of 1e18 representing the answer YES, the insurance claim was valid) or reject the payout and re-open the policy for any subsequent claims:

    Tests and deployment

    All the unit tests covering the functionality described above are available . To execute all of them, run:

    Before deploying the contract check the comments on available environment variables in .

    In the case of the Görli testnet, the defaults would use the Finder instance that references the implementation for resolving DVM requests. This exposes a pushPrice method to be used for simulating a resolved answer in case of disputed proposals. Also, the default Görli deployment would use the already whitelisted TestnetERC20 currency that can be minted by anyone using its allocateTo method.

    To deploy the Insurance Arbitrator contract on Görli, run:

    Optionally you can verify the deployed contract on Etherscan:

    Interacting with deployed contract

    The following section provide instructions on how to interact with the deployed contract from the Hardhat console, though one can also use it for guidance for interacting through another interface (e.g. Remix or Etherscan).

    Start Hardhat console with:

    Initial setup

    From the Hardhat console, start by adding the required getAbi dependency for interacting with UMA contracts and use the first two accounts as insurer and insured beneficiary:

    Grab the deployed Insurance Arbitrator contract:

    Issue insurance

    Assuming TestnetERC20 was used as currency when deploying, mint the required insurance amount (e.g. 10,000 TEST tokens) and approve the Insurance Arbitrator to pull them:

    Issue the insurance policy and grab the resulting policyId from the emitted PolicyIssued event:

    Submit insurance claim

    First calculate the expected proposer bond:

    Fetch the expected final fee from the Store contract (which is discovered through the Finder):

    Calculate the expected total bond and provide funding/approval for the insured claimant:

    Now initiate the insurance claim and grab request details from the RequestPrice event emitted by the Optimistic Oracle:

    Dispute insurance claim

    Before liveness passes, the insurer can dispute the claim through the Optimistic Oracle. First, they must fund and approve with the same bonding amount:

    If you are on a testnet like Göerli, in order to simulate UMA voting on a testnet, you can use the :

    Now initiate the dispute and grab the vote request details from the PriceRequestAdded event emitted by the Mock Oracle:

    Settle insurance claim

    Before settling the claim, we can take a look at the vote request as seen by UMA voters:

    The ancillaryData should start with q:"Had the following insured event occurred as of request timestamp: Bad things have happened?". It is then followed by the ooRequester key with our Insurance Arbitrator address in its value.

    In order to simulate YES as the resolved answer we would pass 1e18 as the price parameter in the Mock Oracle pushPrice method:

    Now we can settle the request through the Optimistic Oracle and observe the emitted ClaimAccepted from our Insurance Arbitrator contract:

    The above settlement transaction should also transfer insuredAmount tokens to the insured beneficiary as well as return the proposer bond to the claim initiator.

    Alternatively, if 0 value was resolved, the settlement transaction should emit the ClaimRejected event without paying out the insuredAmount and returning the bond to the disputer, along with half of the proposer's bond.

    const hre = require("hardhat");
    
    import { FullPolicyEscalationManagerEthers__factory } from "@uma/contracts-node";
    
    const { getContractFactory } = hre.ethers;
    
    const { getAddress } = require("@uma/contracts-node");
    
    async function main() {
      console.log("Running FullPolicyEscalationManager Deployments🔥");
    
      const networkId = Number(await hre.getChainId());
    
      const optimisticOracleV3 = getAddress("OptimisticOracleV3", networkId);
    
      const fullPolicyEscalationManagerFactory: FullPolicyEscalationManagerEthers__factory = await getContractFactory(
        "FullPolicyEscalationManager"
      );
    
      const fullPolicyEscalationManager = await fullPolicyEscalationManagerFactory.deploy(optimisticOracleV3);
    
      console.log("Deployed FullPolicyEscalationManager: ", fullPolicyEscalationManager.address);
    }
    
    main()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error);
        process.exit(1);
      });
    //Configure the contract to block assertions by asserting callers that are not whitelisted
    await fullPolicyEscalationManager.configureEscalationManager(true, false, false, false, false);
    
    //Whitelist an asserting caller and asserter
    await fullPolicyEscalationManager.setWhitelistedAssertingCallers("0x123456789abcdef0123456789abcdef0123456789", true);
    //Configure the contract to validate disputers and arbitrate via the escalation manager
    await fullPolicyEscalationManager.configureEscalationManager(false, false, true, true, false);
    
    //Whitelist a dispute caller
    await fullPolicyEscalationManager.setDisputeCallerInWhitelist("0x123456789abcdef0123456789abcdef0123456789", true);
    //Configure the contract to disregard the oracle's resolution
    await fullPolicyEscalationManager.configureEscalationManager(false, false, false, false, true);
    : The time of the assertion.
  • ancillaryData: The ancillary data of the assertion.

  • resolution: The resolution of the arbitration.

  • whitelisted: A boolean indicating whether the dispute caller was added (true) or removed (false) from the whitelist.
    whitelisted: A boolean indicating whether the asserting caller was added (true) or removed (false) from the whitelist.
    whitelisted: true represents adding and false represents removing the asserter from the whitelist.
    UMIP-107
    here
    networks
    protocol
    Approved Collateral Types
    Address Whitelist
    Finder
    UMIP-107
    how does UMA's DVM work
    here
    the deployment script
    Mock Oracle
    Mock Oracle
    git clone [email protected]:UMAprotocol/dev-quickstart.git
    cd dev-quickstart
    yarn
    yarn hardhat compile
        constructor(
            FinderInterface _finder,
            address _currency,
            address _timer
        ) Testable(_timerAddress) {
            finder =_finderAddress;
            currency = IERC20(_currency);
            oo = OptimisticOracleV2Interface(finder.getImplementationAddress(OracleInterfaces.OptimisticOracleV2));
        }
        function issueInsurance(
            string calldata insuredEvent,
            address insuredAddress,
            uint256 insuredAmount
        ) external returns (bytes32 policyId) ...
        function submitClaim(bytes32 policyId) ...
            uint256 timestamp = getCurrentTime(); // note that `getCurrentTime` is exported from testable to enable easy time manipulation.
            bytes memory ancillaryData = abi.encodePacked(ancillaryDataHead, claimedPolicy.insuredEvent, ancillaryDataTail);
            bytes32 claimId = _getClaimId(timestamp, ancillaryData);
            insuranceClaims[claimId] = policyId;
            oo.requestPrice(priceIdentifier, timestamp, ancillaryData, currency, 0);
            uint256 proposerBond = (claimedPolicy.insuredAmount * oracleBondPercentage) / 1e18;
            uint256 totalBond = oo.setBond(priceIdentifier, timestamp, ancillaryData, proposerBond);
            oo.setCustomLiveness(priceIdentifier, timestamp, ancillaryData, optimisticOracleLivenessTime);
            oo.setCallbacks(priceIdentifier, timestamp, ancillaryData, false, false, true);
            oo.proposePriceFor(msg.sender, address(this), priceIdentifier, timestamp, ancillaryData, int256(1e18));
        function disputePrice(
            address requester,
            bytes32 identifier,
            uint256 timestamp,
            bytes memory ancillaryData
        ) ...
        function settle(
            address requester,
            bytes32 identifier,
            uint256 timestamp,
            bytes memory ancillaryData
        ) ...
        function priceSettled(
            bytes32, // identifier passed by Optimistic Oracle, but not used here as it is always the same.
            uint256 timestamp,
            bytes memory ancillaryData,
            int256 price
        ) ...
            bytes32 claimId = _getClaimId(timestamp, ancillaryData);
            require(address(oo) == msg.sender, "Unauthorized callback");
            // Deletes insurance policy and transfers claim amount if the claim was confirmed.
            if (price == 1e18) {
                delete insurancePolicies[policyId];
                currency.safeTransfer(claimedPolicy.insuredAddress, claimedPolicy.insuredAmount);
    
                emit ClaimAccepted(claimId, policyId);
                // Otherwise just reset the flag so that repeated claims can be made.
            } else {
                insurancePolicies[policyId].claimInitiated = false;
    
                emit ClaimRejected(claimId, policyId);
            }
    yarn test test/InsuranceArbitrator/*
    NODE_URL_5=YOUR_GOERLI_NODE MNEMONIC=YOUR_MNEMONIC yarn hardhat deploy --network goerli --tags InsuranceArbitrator
    ETHERSCAN_API_KEY=YOUR_API_KEY yarn hardhat etherscan-verify --network goerli --license AGPL-3.0 --force-license --solc-input
    NODE_URL_5=YOUR_GOERLI_NODE MNEMONIC=YOUR_MNEMONIC yarn hardhat console --network goerli
    const { getAbi } = require("@uma/contracts-node");
    const [insurer, insured] = await ethers.getSigners();
    const insuranceArbitratorDeployment = await deployments.get("InsuranceArbitrator");
    const insuranceArbitrator = new ethers.Contract(
    	insuranceArbitratorDeployment.address,
    	insuranceArbitratorDeployment.abi,
    	ethers.provider
    );
    const insuredAmount = ethers.utils.parseEther("10000");
    const currency = new ethers.Contract(await insuranceArbitrator.currency(), getAbi("TestnetERC20"), ethers.provider);
    await (await currency.connect(insurer).allocateTo(insurer.address, insuredAmount)).wait();
    await (await currency.connect(insurer).approve(insuranceArbitrator.address, insuredAmount)).wait();
    const issueReceipt = await (await insuranceArbitrator.connect(insurer).issueInsurance(
    	"Bad things have happened",
    	insured.address,
    	insuredAmount
    )).wait();
    const policyId = (await insuranceArbitrator.queryFilter(
    	"PolicyIssued",
    	issueReceipt.blockNumber,
    	issueReceipt.blockNumber
    ))[0].args.policyId;
    const proposerBond = insuredAmount.mul(await insuranceArbitrator.oracleBondPercentage()).div(ethers.utils.parseEther("1"));
    const finder = new ethers.Contract(await insuranceArbitrator.finder(), getAbi("Finder"), ethers.provider);
    const store = new ethers.Contract(await finder.getImplementationAddress(
    	ethers.utils.formatBytes32String("Store")),
    	getAbi("Store"),
    	ethers.provider);
    const finalFee = (await store.computeFinalFee(currency.address)).rawValue;
    const totalBond = proposerBond.add(finalFee);
    await (await currency.connect(insured).allocateTo(insured.address, totalBond)).wait();
    await (await currency.connect(insured).approve(insuranceArbitrator.address, totalBond)).wait();
    const oo = new ethers.Contract(await insuranceArbitrator.oo(), getAbi("OptimisticOracleV2"), ethers.provider);
    const claimReceipt = await (await insuranceArbitrator.connect(insured).submitClaim(policyId)).wait();
    const request = (await oo.queryFilter("RequestPrice", claimReceipt.blockNumber, claimReceipt.blockNumber))[0].args;
    await (await currency.connect(insurer).allocateTo(insurer.address, totalBond)).wait();
    await (await currency.connect(insurer).approve(oo.address, totalBond)).wait();
    const mockOracle = new ethers.Contract(await finder.getImplementationAddress(
    	ethers.utils.formatBytes32String("Oracle")),
    	getAbi("MockOracleAncillary"),
    	ethers.provider);
    const disputeReceipt = await (await oo.connect(insurer).disputePrice(
    	request.requester,
    	request.identifier,
    	request.timestamp,
    	request.ancillaryData
    )).wait();
    const voteRequest = (await mockOracle.queryFilter(
    	"PriceRequestAdded",
    	disputeReceipt.blockNumber,
    	disputeReceipt.blockNumber
    ))[0].args;
    console.log("identifier:", ethers.utils.parseBytes32String(voteRequest.identifier));
    console.log("time:", Number(voteRequest.time));
    console.log("ancillaryData:", ethers.utils.toUtf8String(voteRequest.ancillaryData));
    await (await mockOracle.connect(insured).pushPrice(
    	voteRequest.identifier,
    	voteRequest.time,
    	voteRequest.ancillaryData,
    	ethers.utils.parseEther("1")
    )).wait();
    const settleReceipt = await (await oo.connect(insured).settle(
    	request.requester,
    	request.identifier,
    	request.timestamp,
    	request.ancillaryData
    )).wait();
    const claimSettlementEvent = (await insuranceArbitrator.queryFilter(
    	"ClaimAccepted",
    	settleReceipt.blockNumber,
    	settleReceipt.blockNumber
    ))[0];
    console.log(claimSettlementEvent);

    Mainnet Voting Entities

    Entities

    • User

    • Collateral

    User

    Description:

    Field
    Type
    Description

    Collateral

    Description:

    Field
    Type
    Description

    PriceIdentifier

    Description:

    Field
    Type
    Description

    PriceRequest

    Description:

    Field
    Type
    Description

    PriceRequestRound

    Description:

    Field
    Type
    Description

    VoterGroup

    Description:

    Field
    Type
    Description

    CommittedVote

    Description:

    Field
    Type
    Description

    RevealedVote

    Description:

    Field
    Type
    Description

    RewardsClaimed

    Description:

    Field
    Type
    Description

    FinancialContract

    Description:

    Field
    Type
    Description

    BigInt

    Provides a lower bound on the number of votes a user has correctly voted for. Users may not have retrieved rewards for all of their correct votes

    votesCommited

    Int!

    String!

    isOnWhitelist

    Boolean!

    Is token currently whitelisted as collateral

    finalFee

    BigDecimal

    PriceRequestRound

    PriceRequestRound entity corresponding to the last round of voting

    time

    BigInt!

    identifier

    PriceIdentifier!

    PriceIdentifier for the request

    ancillaryData

    String

    resolutionTransaction

    Bytes

    Transaction where the resolution of the request took place

    resolutionTimestamp

    Bigint

    Timestamp when the resolution of the request took place

    resolutionBlock

    BigInt

    Block number when the resolution of the request took place

    rounds

    List of all the rounds involved in this PriceRequest

    committedVotes

    List of all the votes committed on this request

    revealedVotes

    List of all the votes revealed on this request

    rewardsClaimed

    List of all the rewards claimed events for this request

    String

    time

    BigInt!

    snapshotId

    BigInt

    votersAmount

    BigDecimal!

    Total amount of users who voted on this round

    votersClaimedAmount

    BigDecimal!

    Total amount of users who claimed rewards on this round

    totalVotesRevealed

    BigDecimal!

    totaRewardsClaimed

    BigDecimal!

    totalSupplyAtSnapshot

    BigDecimal

    tokenVoteParticipationRatio

    BigDecimal

    Ratio of the total supply of tokens that were weighted on this vote

    tokenVoteParticipationPercentage

    BigDecimal

    Ratio of correct voters over total voters on this price request

    votersEligibleForRewardRatio

    BigDecimal

    Ratio of correct voters over total voters on this price request

    votersEligibleForRewardsPercentage

    BigDecimal

    Percentage of correct voters over total voters on this price request

    votersClaimRatio

    BigDecimal

    Ratio of correct voters who claimed their rewards

    votersClaimedPercentage

    BigDecimal

    Percentage of correct voters who claimed their rewards

    tokensClaimedRatio

    BigDecimal

    Ratio of rewards claimed over total supply of voting token

    tokensClaimedPercentage

    BigDecimal

    Percentage of rewards claimed over total supply of voting token

    getPercentageRaw

    BigDecimal

    getPercentage expressed exactly as in the contract. 1 = 100%

    getPercentage

    BigDecimal

    getPercentage expressed as a percentage value

    inflationRateRaw

    BigDecimal

    inflationRate expressed exactly as in the contract. 1 = 100%

    inflationRate

    BigDecimal

    inflationRate expressed as a percentage value

    winnerGroup

    VoterGroup

    committedVotes

    revealedVotes

    groups

    rewardsClaimed

    totalVoteAmount

    BigDecimal!

    totalVoteAmount

    BigInt

    votersAmount

    BigDecimal!

    won

    Boolean!

    PriceRequest!

    time

    BigInt!

    round

    PriceRequestRound!

    voter

    User!

    PriceRequest!

    time

    BigInt!

    round

    PriceRequestRound!

    price

    BigInt!

    voter

    User!

    numTokens

    BigInt!

    group

    VoterGroup!

    PriceRequest!

    time

    BigInt!

    round

    PriceRequestRound!

    claimer

    User!

    numTokens

    BigInt!

    NumTokens will be 0 if the claim is not 'valid'. This can happen if the function was called for a voter who didn't get the correct vote for example

    group

    VoterGroup!

    id

    ID!

    Utility entity that links data from a single Ethereum address. Id of the entity is the Ethereum address itself

    address

    Bytes!

    countReveals

    BigInt

    Number of price requests that this user has revealed a vote for, and therefore participated in as a voter

    id

    ID!

    Represents approved collateral that is whitelisted in the AddressWhitelist and whose fees are set in the Store. Id of the entity is its address

    decimals

    Int!

    name

    String!

    id

    ID!

    isSupported

    Boolean!

    Depicts whether this PriceIdentifier is currently among the identifiers supported on the whitelist. It will only be false if it was removed from the whitelist

    priceRequests

    PriceRequest!

    List of all the PriceRequest entities related to this particular PriceIdentifier

    id

    ID!

    ID is the PriceIdentifier ID + the timestamp

    isResolved

    Boolean!

    Depicts whether the request has been resolved

    price

    BigInt

    Price resolved for this request

    id

    ID!

    ID is the PriceIdentifier ID + the timestamp + the roundId + ancillaryData (if available)

    request

    PriceRequest!

    identifier

    PriceIdentifier!

    id

    ID!

    Just a helper entity to group voters who voted the same price result. ID is composed of round ID + voted price

    price

    BigInt!

    round

    PriceRequestRound!

    id

    ID!

    Committed votes won't show the price until a reveal happens and a RevealedVote is created

    identifier

    PriceIdentifier!

    ancillaryData

    String

    id

    ID!

    identifier

    PriceIdentifier!

    ancillaryData

    String

    id

    ID!

    identifier

    PriceIdentifier!

    ancillaryData

    String

    id

    ID!

    This entity represents a contract that can make price requests to the DVM. ID is the address of the contract

    creator

    Bytes!

    registrationTimestamp

    BigInt!

    PriceIdentifier
    PriceRequest
    PriceRequestRound
    VoterGroup
    CommittedVote
    RevealedVote
    RewardsClaimed
    FinancialContract

    countRetrievals

    symbol

    latestRound

    ancillaryData

    votes

    request

    request

    request

    PriceRequestRound!
    CommittedVote!
    RevealedVote!
    RewardsClaimed!
    CommittedVote!
    RevealedVote!
    VoterGroup!
    RewardsClaimed!
    RevealedVote!