JS: Ties, Extensions, Slashing

This page covers special conditions the oracle enforces during resolution and inactivity periods. It focuses on app integration and user flows.

Ties and voting extension

When calling resolveQuery(queryId), the contract:

  • Finds the answer with the highest total collateral weight.
  • If multiple answers tie for highest weight, it:
    • Sets currentEndBlock = block.number + tieExtensionPeriod()
    • Emits VotingExtended
    • Reverts the transaction (so your call fails)

What to do in your app:

  1. Catch the revert, treat it as “tie → extended voting”.
  2. Re-read details and surface the new currentEndBlock to users.
  3. Allow more votes during the extension.
  4. Retry resolution after the new end block.

Example:

import { BrowserProvider, Contract } from 'ethers'
import OracleArtifact from '../../../artifacts/contracts/FarmTruth.sol/DecentralizedOracle.json'

const browser = new BrowserProvider((globalThis as any).ethereum)
const signer = await browser.getSigner()

const ORACLE_ADDRESS = '0xFA4595F636887CA28FCA3260486e44fdcc8c8A71'
const oracle = new Contract(ORACLE_ADDRESS, (OracleArtifact as any).abi, signer)

async function tryResolve(queryId: bigint) {
  try {
    const tx = await oracle.resolveQuery(queryId)
    await tx.wait()
    return { resolved: true }
  } catch (e) {
    // Likely tie or too early
    const d = await oracle.getQueryDetails(queryId)
    const extendedEnd = d[3]
    const inTieExtension = d[14]
    return {
      resolved: false,
      reason: 'tie_or_too_early',
      inTieExtension,
      currentEndBlock: extendedEnd.toString()
    }
  }
}

UI tips:

  • Show a banner “Tie detected. Voting extended until block X.”
  • Offer a refresh button that re-checks details.

Inactivity slashing

If a query receives zero votes and passes a grace period after currentEndBlock, anyone may call slashInactiveQuery(queryId). Effects:

  • The query is marked resolved.
  • Half of the initial deposit is burned, the other half returned to the creator.
  • Emits QuerySlashed.

When it applies:

  • No votes were cast (query.totalCollateral == 0).
  • Caller waits until currentEndBlock + inactivityThreshold.
  • Designed to discourage spam queries that never attract participation.

Example read/check pattern:

import { JsonRpcProvider, Contract } from 'ethers'
import OracleArtifact from '../../../artifacts/contracts/FarmTruth.sol/DecentralizedOracle.json'

const provider = new JsonRpcProvider(process.env.RPC!)
const ORACLE_ADDRESS = '0xFA4595F636887CA28FCA3260486e44fdcc8c8A71'
const oracle = new Contract(ORACLE_ADDRESS, (OracleArtifact as any).abi, provider)

async function canSlash(queryId: bigint) {
  const d = await oracle.getQueryDetails(queryId)
  const currentEndBlock = d[3]
  const resolved = d[7]
  if (resolved) return false

  // If your app also tracks inactivityThreshold off-chain:
  // read it from the contract (public var) if exposed; otherwise
  // show generic “grace period after end” messaging and let the caller try.

  // You can also check distribution = 0 votes
  const count = await oracle.getQueryAnswersCount(queryId)
  return count === 0n && (await provider.getBlockNumber()) > currentEndBlock
}

Note: Only call slashing if you explicitly want to finalize a dead query. Most apps will avoid exposing this action to end users and instead handle it through a mod or automated janitor.

User messaging and UX

  • Resolving:
    • If revert occurs, show “Either voting not ended or tie detected; extended to block X.”
    • Provide a countdown to currentEndBlock.
  • Voting during extension:
    • Encourage users to add collateral to break the tie.
  • Inactivity:
    • Avoid creating queries that users are unlikely to vote on.
    • Consider off-chain notifications to participants to reduce inactive outcomes.
  • getQueryDetails(queryId) → includes currentEndBlock, inTieExtension, and canBeResolved hint.
  • getQueryAnswersCount(queryId) → quick zero-vote check.
  • resolveQuery(queryId) → may revert on tie or too-early resolution.
  • slashInactiveQuery(queryId) → finalizes zero‑vote queries after grace period.

Navigate next:

  • Pagination and listing → ./pagination
  • Reference snippets → ./snippets

Back to: