Repository navigation
Oracle Service
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
- Appendices
This document describes Sigvara’s off-chain oracle service that computes normalized reputation scores for agents and anchors them on chain. The service exposes a small REST API for attestation submission, score preview, evidence retrieval, health checks, metrics, and operator controls. Internally it coordinates chain interaction, optional payment scanning, scoring computation, persistent state, and Prometheus-style metrics. It also supports a checker mode where a second operator independently recomputes pending scores and reports divergences to the slashing committee.
The oracle is designed so that anyone can audit its outputs: it publishes Merkle roots over the evidence used to compute each score, and serves the underlying events with proofs.
This page describes the oracle as it is on main. The testnet oracles each run one pinned commit (SIGVARA_COMMIT in the environment file) and report it in /health. Both run cf76691 (pull request 138) as of 2 November 2026, which is the oracle code on main apart from a patch release of dotenv, and /health reports the commit each one runs. A change merged to main reaches them only when someone changes the pin and recreates the container.
Section sources
The oracle is a Node.js application built around a single HTTP server entry point and several focused modules:
-
index.js— HTTP server, configuration, route handlers, epoch scheduler, and orchestration of chain, payments, scoring, store, cache, badge, jobs, and metrics. -
http-helpers.js— JSON helpers, bearer-token authentication and credential scopes, body parsing, rate limiting, client identification (withTRUSTED_PROXIES), canonical request-target parsing, and startup policy checks. -
scoring.js— Pure functions computing the six-factor reputation score. -
epoch-policy.js— Epoch scheduling validation, primary/checker decision logic, divergence comparison, chunked mapping utilities, and the clock-skew and stale-scoring checks. -
store.js— Persistent JSON-backed state for attestations, flags, links, cooldowns, payment events, scan checkpoints, and divergences, with a.bakof the previous save and a recordedschemaVersionandchainId. -
metrics.js— In-memory Prometheus counters and gauges exposed at/metrics. -
config.js: Startup checks on the numeric settings and onORACLE_MODE. A value that is set and unusable stops the process, and a blank value means unset. -
secrets.js: Reads the signing key from the file named byORACLE_PRIVATE_KEY_FILEor fromORACLE_PRIVATE_KEY, and refuses a malformed key with a message that never contains the value. -
state-serialize.js: Writes the state file in pieces of about 1 MB that join to exactly whatJSON.stringifywould produce. - Supporting modules referenced by the entry point include chain interaction, external ERC-8004 integration, payment scanning, Merkle tree utilities, response caching, badge generation, job registry reading, and payment accounting.
-
payer-outcome.js: The checks on an outcome the payer signed (ADR 0006): its shape and timing, the EIP-712 signature by recovery or through ERC-1271, and reading another operator'sGET /outcomespages. -
evidence-as-of.js: The payment evidence as it stood when a pending proposal was made, which a checker scores that proposal over.
graph TB
Client["Client"] --> HTTP["HTTP Server<br/>index.js"]
HTTP --> Helpers["Auth & Rate Limiting<br/>http-helpers.js"]
HTTP --> Store["Persistent State<br/>store.js"]
HTTP --> Scoring["Score Computation<br/>scoring.js"]
HTTP --> EpochPolicy["Epoch Decisions<br/>epoch-policy.js"]
HTTP --> Metrics["Prometheus Metrics<br/>metrics.js"]
HTTP --> Chain["Chain Interaction"]
HTTP --> Payments["Payment Accounting"]
HTTP --> External["ERC-8004 External Score"]
HTTP --> Jobs["ERC-8183 Job Registry"]
HTTP --> Cache["Response Cache"]
HTTP --> Badge["Badge Generator"]
HTTP --> PaymentScan["Payment Scanner"]
Diagram sources
Section sources
- HTTP server and routing: The entry point configures environment variables, initializes chain and external integrations, loads persistent state, and exposes endpoints such as
/health,/metrics,/attest,/flag,/flag/resolve,/link,/score/:didHash,/evidence/:didHash,/outcomes,/badge/:address.svg,/jobs/:address,/epoch, and/divergence. Numeric settings andORACLE_MODEare validated before anything else starts, and a request target must be a path in canonical form or the answer is400 bad request target. An error a route does not handle itself is logged and answered500 internal error. - Authentication: Bearer tokens are loaded from
ORACLE_ADMIN_TOKENand namedORACLE_TOKEN_<NAME>values. Tokens are compared using constant-time comparison, and callers are attributed by name.ORACLE_SCOPES_<NAME>can limit a credential to some ofattest,flag,linkandepoch. - Rate limiting: A fixed-window limiter (60 requests per caller per minute) protects write endpoints and the expensive read endpoints, with a separate bucket for each kind of route: writes,
/evidence,/divergence, and the other reads. The caller is the socket address, or an address read from the right ofX-Forwarded-Forwhen the connection arrives from loopback or from a proxy listed inTRUSTED_PROXIES. - Persistence: Attestation counts, flag timestamps, agent links, cooldowns, payment events, deduplication keys, divergences, and scan checkpoints are persisted to a mounted volume, together with a
schemaVersionand thechainIdthe state belongs to. Writes go to a temp file in pieces, are flushed with fsync and renamed into place, and the file being replaced is kept as<state>.bak. - Metrics: Prometheus-format exposition includes epoch lifecycle, proposal/finalization outcomes, attestations, flags, links, badges, jobs, payment scans, throttling, refused or unconfirmed transactions, epoch-fee charges, stranded proposals, refused HTTP requests, evidence cache statistics, and the import of payer-signed outcomes from other operators.
Section sources
- index.js:76-209
- http-helpers.js:61-113
- http-helpers.js:145-361
- store.js:503-541
- metrics.js:8-107
- config.js
- state-serialize.js
Sigvara sits on top of ERC-8004 identity and feedback. The oracle consumes multiple signals:
- Payment-backed attestations: Success or failure tied to an on-chain settlement, reported by a token holder.
- Payer-signed outcomes: The payer's own EIP-712 signature that the work was delivered, which needs no token and which each operator imports from the others (ADR 0006).
- On-chain payment scanning: Optional pull-based discovery of transfers to registered agents.
- Flags: Community watchdog penalties.
- ERC-8004 feedback: Cross-protocol trust signal for linked identities.
- Counterparty standing: Payer reputation influences propagation.
- Tenure: Activity span weighted by recency.
The oracle proposes a computed score and Merkle root to SigvaraReputation; after a challenge window, it finalizes. Two operators may run: a primary proposing and finalizing, and a checker auditing proposals and reporting divergences.
graph TB
subgraph Sources["Signal Sources"]
CA["CounterAudit<br/>Attestations"]
WD["Watchdog<br/>Flags"]
CH["Chain<br/>Transfers"]
EREP["ERC-8004<br/>Feedback"]
end
subgraph Oracle["Oracle Service"]
API["REST API"]
Scan["Payment Scanner"]
Score["Scorer"]
Store["State Store"]
Metrics["Metrics"]
end
subgraph Contracts["On-Chain"]
REP["SigvaraReputation"]
STAKING["SigvaraStaking"]
end
CA --> API
WD --> API
CH --> Scan
EREP --> Score
API --> Store
Scan --> Store
Store --> Score
Score --> REP
STAKING --> REP
REP --> API
API --> Metrics
Diagram sources
Section sources
-
GET /health: Operational status including epoch timing, uptime, store writability, persistence result, where the state was loaded from (stateSource:file,freshorbackup), the chain the RPC was last seen on beside the one configured (chainId,expectedChainId), the commit the deployment reports, external feed reachability, payment scan progress, and job registry status. Returns 503 when the state path is not writable, state persistence is failing, or scoring is stale: no successful epoch for two epoch intervals, counted from process start until the first success. -
GET /metrics: Prometheus exposition for monitoring and alerting.
Section sources
-
POST /attest: Submits work-outcome attestations. With payment verification required, a positive attestation needs no token because the verified payment is the credential for the payment, but without a token it is stored with no outcome (outcomeRecorded: false); recording an outcome takes a bearer token or the payer's signature, and a negative attestation always requires a token. An outcome the payer signed goes inpayerOutcomeinstead ofsuccessand needs no token, wherePAYER_OUTCOMESis on; the operators take "delivered" only for now. The endpoint verifies the settlement against the chain, credits the payer from transfer logs, enforces cooldowns, and returns standardized error codes for rejected payments, already-credited settlements, cooldowns, and RPC failures. While the oracle cannot write its state file it answers 202 withdurable: falseinstead of 200.
Request/response patterns:
- Positive verified payment: minimal request with settlement transaction hash; response includes credited payer, amount, updated tally, and whether an outcome was recorded.
- Negative or unverified: requires auth; returns appropriate rejection code when credentials or payment checks fail.
- Payer-signed outcome:
payment.txHashpluspayerOutcome, no token. The response carriesoutcomeHash, and a second outcome for the same leg gets 409outcome_recordedwithheldOutcomeHashandsameOutcome.
Section sources
-
GET /score/:didHash: Computes and returns the current score without writing to chain. Uses chain clock for deterministic time-dependent factors and reads agent info, counterparty standing, flags, external score, and payment-derived factors, the same inputs the epoch uses. When the node cannot answer, after retries, the route answers502withcode: "rpc_error"; any other failure is a generic500, because the route is public and does not echo error text.
Section sources
-
GET /evidence/:didHash: Serves the Merkle root, count, and evidence entries with leaf hashes and Merkle proofs. Unauthenticated and rate-limited. Includes committed fields so verifiers know exactly what is covered. Each entry names itsoutcomeSource(payer_signedorcredentialed, this oracle's label and not part of the leaf), and wherePAYER_OUTCOMES_PUBLISH=ona payer-signed entry carries the signed payload, with the signing domain served aspayerOutcomeDomain.counterauditPacketIdis listed underunverifiedFields: a pointer this oracle checks only for shape.
Section sources
-
GET /outcomes?since=<ms>: The payer-signed outcomes this oracle has taken, oldest first, 500 to a page, with the signingdomainand anextcursor (acceptedAt, this oracle's own time of taking each). Unauthenticated, because each outcome verifies on its own. Served only withPAYER_OUTCOMESon andPAYER_OUTCOMES_PUBLISH=on, and 404 otherwise. - Import: an oracle with
PAYER_OUTCOMES_PEERSset reads each listed operator's/outcomesat the start of every epoch, before scoring, and puts each outcome through the same checks as aPOST /attest, at the block the peer recorded (checkedAtBlock). An outcome must reach it withinPAYER_OUTCOMES_IMPORT_GRACE_HOURS(6 by default) of its deadline. One it already holds is kept, and a different one served for the same payment is counted as a conflict. Imported outcomes are served on at this oracle's own/outcomes.
Section sources
-
POST /flag: Raises community flags; each flag costs points in the community factor. -
POST /flag/resolve: Clears flags raised previously; clamps to zero and reports before/after counts. -
POST /link: Links an agent to an ERC-8004 identity for cross-protocol scoring. -
POST /epoch: Manually triggers an epoch run; answers202, or409if one is already running.
All require bearer tokens unless explicitly exempted. A credential restricted with ORACLE_SCOPES_<NAME> gets 403 on a write outside its scopes.
Section sources
-
GET /badge/:address.svg: Embeddable SVG badge showing finalized on-chain score bands. Caches responses and sets CORS headers for embedding.
Section sources
-
GET /jobs/:address: Reads ERC-8183 job registry data observationally. Disabled unless configured; returns 501 when disabled.
Section sources
-
GET /divergenceandGET /divergence/:didHash: Checker-mode only. Reports disagreements between this operator’s recomputation and the pending on-chain proposal, including per-factor deltas and evidence roots. Each record also says whether this operator's evidence as it stood at the proposal matched the root the proposal committed to (evidenceMatchesProposal) and gives that root (ownEvidenceRootAtProposal). The collection holds the 100 most recent, newest first, withtotalandtruncated, and reportsseesProposalsso an empty list cannot be mistaken for "checked, found nothing". A primary answers 404.
Section sources
- Bearer token authentication uses constant-time comparison across all configured tokens.
- Named credentials allow revocation and attribution without rotating all secrets.
-
ORACLE_SCOPES_<NAME>restricts a credential to some ofattest,flag,linkandepoch. An unknown scope, or a restriction naming a credential that does not exist, stops the process at startup, andadminis never restricted. A token shorter than 32 characters works but is named in a startup warning. - A non-loopback bind with no configured credential is refused at startup to prevent exposing write endpoints. A loopback bind may run without one for local testing.
Section sources
| Endpoint | Method | Auth | Request Body | Response Summary | Error Codes |
|---|---|---|---|---|---|
/health |
GET | None | None | Operational status object | 200, 503 |
/metrics |
GET | None | None | Prometheus text | 200 |
/attest |
POST | Required for negative/unverified; positive verified payment exempt (recorded with no outcome unless a token is sent), and a payer-signed outcome needs none |
didHash, success or payerOutcome, optional payment.txHash, optional packetId
|
Credited payer, amount, updated tally, and outcomeHash for a payer-signed outcome |
200, 202, 400, 401, 402, 403, 409, 429, 502 |
/flag |
POST | Required | didHash |
Updated flag count | 200, 202, 400, 401, 403, 429 |
/flag/resolve |
POST | Required |
didHash, optional count
|
Before/after/resolved counts | 200, 202, 400, 401, 403, 429 |
/link |
POST | Required |
didHash, agentId
|
Link confirmation | 200, 202, 400, 401, 403, 429, 502 |
/score/:didHash |
GET | None | Path parameter | Computed score object | 200, 429, 500, 502 |
/evidence/:didHash |
GET | None | Path parameter | Root, count, evidence array with proofs | 200, 400, 429 |
/outcomes |
GET | None | Optional since query (ms) |
Payer-signed outcomes, oldest first, with the signing domain and a next cursor |
200, 400, 404, 429 |
/badge/:address.svg |
GET | None | Address path | SVG image | 200, 404 |
/jobs/:address |
GET | None | Address path | Job registry summary | 200, 429, 501, 502 |
/epoch |
POST | Required | None | Epoch trigger result | 202, 401, 403, 409, 429 |
/divergence |
GET | None | Optional :didHash path parameter |
Divergence records | 200, 400, 404, 429 |
Section sources
- HTTP helpers enforce maximum body size and return structured errors for invalid JSON.
- Attestation endpoint distinguishes RPC failures from business rejections (cooldown, self-payment, already credited).
- A request target that is not a canonical path is refused with
400 bad request targetbefore routing, and a handler that throws costs one request (500 internal error), not the process. - Epoch execution wraps chain reads and writes in guards; transient RPC failures increment metrics and skip rather than crash the process.
- A transaction whose fee would exceed
MAX_FEE_GWEI, or whose worst-case cost would exceedMAX_TX_COST, is refused before it is signed. One not mined withinTX_WAIT_SECONDSis replaced once, at the same nonce and twice the fee, and is counted as unconfirmed if that does not land either. - Health endpoint returns 503 when the state path is not writable, state persistence fails, or epochs are stale.
- Metrics track propose/finalize attempts, successes, errors, throttling, and slot-taken outcomes separately.
Section sources
The epoch pipeline transforms raw attestations and chain observations into normalized reputation scores:
- Check that the RPC is on the expected chain and that the chain's clock is within
MAX_CLOCK_SKEW_SECONDSof the host's (an epoch that fails either check does not run), import payer-signed outcomes from the operators inPAYER_OUTCOMES_PEERSif set, then acquire registered agents and scan recent payments if enabled. - Read agent info, pending score, and fee coverage concurrently in chunks.
- Filter slashed and uncovered agents; prepare candidates.
- For each candidate, perform guard reads (bonded status, fresh status) and decide whether to finalize, propose, or skip based on challenge window.
- Compute measured factors from payment events, flags, external score, activity, and propagation.
- Call pure scoring function to produce six factors and total.
- In checker mode, re-read the pending slot, score the proposal at its own timestamp over the evidence as it stood then (the payments settled by
proposedAt, with an outcome a payer signed later read as unreported when that makes the root match the one the proposal committed to), and compare. Record a divergence when the total or a single factor differs by more than the tolerance, finalize an agreed score once its window has elapsed, and propose only into an empty slot (or one whose proposer has lost its authority) throughproposeIfEmpty. - Propose or finalize on chain, waiting a bounded time for each transaction; update metrics and persist state.
flowchart TD
Start(["Epoch Start"]) --> Checks["Check Chain ID and Clock"]
Checks --> Agents["Fetch Registered Agents"]
Agents --> Scan["Optional Payment Scan"]
Scan --> Phase1["Phase 1: Batch Agent Info, Pending, Coverage"]
Phase1 --> Filter["Filter Slashed/Uncovered"]
Filter --> Phase2["Phase 2: Guard Reads per Chunk"]
Phase2 --> Decision{"Action?"}
Decision --> |Skip| NextAgent["Next Agent"]
Decision --> |Finalize-Then-Propose| Finalize["Finalize Existing Proposal"]
Finalize --> Compute["Compute Measured Factors"]
Decision --> |Propose| Compute
Compute --> Score["computeScore()"]
Score --> Checker{"Checker Mode?"}
Checker --> |Yes| Compare["Compare Against Pending"]
Compare --> Record{"Divergence?"}
Record --> |Yes| Divergence["Record Divergence"]
Record --> |"No, slot empty"| Propose["Propose New Score"]
Record --> |"No, proposal pending"| Agreed["Skip, or Finalize After Window"]
Checker --> |No| Propose
Propose --> Persist["Persist State"]
Divergence --> Persist
Agreed --> Persist
Persist --> End(["Epoch Complete"])
Diagram sources
Section sources
The six-factor model produces a normalized score:
- Fee score: Real volume when payment verification is enabled; otherwise a proxy based on attestation count.
- Success score: Weighted success ratio with a prior to avoid scale invariance.
- Age score: Tenure curve over activity span with recency weighting.
- External score: ERC-8004 feedback for linked identities, clamped to contract cap.
- Community score: Penalty from unresolved flags.
- Propagation score: Inherited trust from counterparties’ external standing.
classDiagram
class Scorer {
+computeScore(opts)
+feeScore(attestationTotal)
+successScore(successful, total, prior)
+ageScore(registeredAtSeconds, activity, nowMs)
+communityScore(unresolvedFlags)
}
class Inputs {
+registeredAt
+attestations
+flags
+externalScore
+measuredFeeScore
+activity
+propagation
+now
}
Scorer --> Inputs : "reads"
Diagram sources
Section sources
- Chain interaction: Initializes provider, reads agent info, pending scores, challenge windows, latest block timestamp, fee gating, and performs propose/finalize transactions. Reads are retried with backoff; writes are not resent blindly, and are checked for throttling, signed only under the fee caps, and waited for a bounded time (one same-nonce replacement at twice the fee).
- Payment scanning: Optionally scans ERC-20 Transfer logs to agent addresses, plans credits, validates with a canary, persists checkpoints, and avoids losing evidence during RPC refusals.
- External integrations: ERC-8004 external score for linked identities; ERC-8183 job registry observation.
Section sources
Prometheus-style metrics cover epoch lifecycle, proposal/finalization outcomes, attestations, flags, links, badges, jobs, payment scans, throttling, evidence cache, and checker comparisons. Others cover sigvara_oracle_tx_refused_total{reason} (a transaction refused for its fee, or sent and never seen mined), sigvara_oracle_fee_charges_total{result}, sigvara_oracle_proposals_stranded_total, sigvara_oracle_http_refused_total{reason}, and the payer-outcome import (sigvara_oracle_payer_outcomes_imported_total, sigvara_oracle_payer_outcome_import_refused_total, sigvara_oracle_payer_outcome_import_errors_total and sigvara_oracle_payer_outcome_conflicts_total). All are exposed at /metrics and should be scraped by Prometheus or compatible tools.
Section sources
The oracle’s runtime dependencies are minimal:
- Node.js runtime version requirement.
-
dotenvfor environment loading. -
ethersfor Ethereum JSON-RPC interaction.
graph LR
App["oracle/index.js"] --> Dotenv["dotenv"]
App --> Ethers["ethers"]
App --> HttpHelpers["http-helpers.js"]
App --> Scoring["scoring.js"]
App --> EpochPolicy["epoch-policy.js"]
App --> Store["store.js"]
App --> Metrics["metrics.js"]
Diagram sources
Section sources
- Concurrency control: Epoch phase one batches independent reads in chunks to avoid overwhelming RPC providers while still benefiting from ethers batched JSON-RPC calls.
- Guard batching: Pre-write guards are issued in parallel per chunk to reduce round trips.
- Time determinism: All time-dependent scoring uses chain-provided timestamps to ensure two operators compute identical results.
- Evidence caching:
/evidencerebuilds Merkle trees; a response cache reduces expensive recomputation. - Merkle caching: Stored payment events are frozen, and
merkle.jscaches each leaf and each agent's root by identity, so an epoch in which an agent's evidence has not changed reuses its root instead of hashing every payment again. - Payment scan pacing: Configurable pace between
getLogscalls prevents provider refusal during long catch-ups. - Flag and event pruning: Decay-based pruning keeps state bounded.
- State saves: The state file is written in pieces, so the memory peak of a save is the live state plus one piece rather than several copies of the whole file.
Common issues and diagnostics:
- Missing or unusable settings: Startup exits when required variables are absent, when a numeric setting is set to something that is not a plain number in range (a blank value counts as unset), or when both
ORACLE_PRIVATE_KEYandORACLE_PRIVATE_KEY_FILEare set. - Bad epoch interval: Validation rejects intervals that would cause continuous epoch runs.
- Checker misconfiguration: Checker mode refuses fee registry configuration and warns if epoch cadence is too slow relative to the challenge window.
- State persistence failures:
/healthreports writability and last persist result; investigate volume mounts and disk space. A state file that exists but cannot be read falls back to the.bakof the previous save (the bad file is kept as<state>.corrupt-<time>) andstateSourcereadsbackup; the process stops if there is no usable backup. A file written by a newer version, or saved on another chain than the RPC reports, also stops it. - Payment verification disabled: Without verification, fee score proxies HTTP request counts and is not a trustworthy signal.
- Payment scan empty but broken: Canary detects filter/query failures; monitor
sigvara_oracle_payment_scan_canary_failures_total. - Stale epochs:
/healthreturns 503 when no successful epoch occurred within twice the epoch interval, counted from process start until the first success. - Rate limiting: Requests exceeding 60 per caller per minute in a route's bucket receive 429; if every visitor behind a proxy is limited together, set
TRUSTED_PROXIESto the proxy network. - Throttled writes: Separate metrics distinguish provider throttling from proposal/finalization errors.
- Payer-signed outcome on one operator only: the other normally imports it at its next epoch, within about an hour. After two hours, read the
payer outcomes fromlog line and the import counters and runnode scripts/check-live.mjs outcomes;docs/operations-runbook.md, section 2, says what each refusal and stall means.
Section sources
Sigvara’s oracle service provides a transparent, auditable reputation system anchored on chain. Its REST API supports secure attestation submission, public score and evidence access, and operator controls. The epoch pipeline combines payment-backed attestations, optional chain-scanned payments, flags, external feedback, counterparty standing, and tenure into a normalized score. Checker mode adds independent recomputation and divergence reporting, enabling the slashing committee to act within challenge windows. Docker deployment, environment configuration, and Prometheus metrics support production operations.
- Service builds from
oracle/Dockerfile, binds port3030on localhost, mountsoracle_statevolume to/data, and joins a shared network. - Environment file is expected at
./oracle/.env. -
docker-compose.mainnet.ymlbuilds the primary, checker and watcher from one pinned commit (SIGVARA_REF), reads the signing key from a file secret, and runs the container as an unprivileged user on a read-only root filesystem.
graph TB
Compose["docker-compose.oracle.yml"] --> Service["oracle service"]
Service --> Volume["oracle_state:/data"]
Service --> Port["127.0.0.1:3030"]
Service --> Network["sigvara-mesh"]
Diagram sources
Section sources
- Required: RPC URL, oracle private key (or
ORACLE_PRIVATE_KEY_FILE, naming a file that holds it), identity address, reputation address. - Recommended: Admin token,
EXPECTED_CHAIN_ID, state path, attestation cooldown, andTRUSTED_PROXIESbehind a reverse proxy. - Optional: Epoch interval, host/port, scan ranges, fee registry, external ERC-8004 settings, payment verification and scanning parameters, job registry settings, transaction wait and fee caps (
TX_WAIT_SECONDS,MAX_FEE_GWEI,MAX_TX_COST), the clock-skew limit (MAX_CLOCK_SKEW_SECONDS), and payer-signed outcomes (PAYER_OUTCOMES,PAYER_OUTCOMES_PUBLISH,PAYER_OUTCOMES_PEERS,PAYER_OUTCOMES_IMPORT_GRACE_HOURS,PAYER_OUTCOME_WINDOW_DAYS,PAYER_NEGATIVE_MIN_AMOUNT). Set the payer-outcome settings the same on every operator.
Section sources
- Primary operator proposes and finalizes scores.
- Checker operator recomputes pending scores, records divergences, and finalizes only when it agrees and the challenge window has elapsed. It proposes only into an empty slot, through
proposeIfEmpty, to cover a silent primary. That call also replaces a pending proposal whose proposer has lost its authority, on the Arc testnet since 26 October 2026 (the September contract reverted for any pending proposal). - Watcher monitors checker availability and divergence alerts, re-checking live chain state before escalation. It also alerts when the checker is unreachable, cannot be read, is not a checker, or has not completed an epoch within
MAX_SILENCE_MINUTES(counted from its start if it never has), and when its own polls keep failing. - Separation of hosts and RPC providers reduces shared failure modes.
- Each operator lists the other in
PAYER_OUTCOMES_PEERSand imports its payer-signed outcomes, so an outcome posted to one reaches both. A token holder's outcome stays with the operator it was posted to.
Section sources
- Agent Registration and Lifecycle
- Contract Overview and Architecture
- Economic Security Model and Incentives
- Evidence Verification and Merkle Proofs
- Key Management and Rotation
- Maturity Mechanism and Score Release
- Proposal Workflow and Challenge System
- Score Storage and Data Model
- SigvaraIdentity Contract
- SigvaraOracleBond Contract
- SigvaraReputation Contract
- SigvaraStaking Contract
- Slashing Lifecycle and Dispute Resolution
- Stake Management Functions
- Status Management and Control
- Token and Fee Contracts
- Unbonding Period and Withdrawal Security
- Anti-Manipulation and Security Measures
- Community Flag Processing
- Evidence Sources and Verification
- External Trust Integration
- Merkle Proof System
- Oracle Score Computation
- Payment-Backed Attestations
- Scoring Model and Formulas
- Agent Creation and Key Management
- Agent Operations
- Agent Registration Workflow
- Challenge-Response Authentication
- Gate Access Control
- Integration Patterns and Examples
- SDK Overview and Setup
- Verifier Functions