Skip to Content
NetworkContracts & addresses

Contracts & addresses

Claros runs on Casper testnet (network id casper-test). Four Odra (Rust) contracts make up the on-chain system, and two external testnet packages (WCSPR and WiseLending) complete the agent’s payment and yield path. Every contract is upgradable, so its package hash is the stable address you integrate against: an upgrade publishes a new contract version under the same package, and your calls keep working unchanged.

This page is the canonical address and entry-point reference. For how a value is produced and read, see how it works; for the on-chain record shape, see the attestation.

Contract addresses

ContractPackage hash (cspr.live)Role
AttestationRegistry236b51…16ccStores feed values by feed_id: the latest reading plus the full append-only history.
FeedRegistry741cc2…f5b6Stores self-describing feed metadata by feed_id (decimals, unit, source, route, frequency).
TreasuryVaulta90b08…fd7bAppend-only ledger of the agent’s reinvestment decisions and treasury holdings.
EligibilityGate7be33b…5227Zero-knowledge (Groth16) access gate the agent clears before it is allowed to attest.

The AttestationRegistry and the FeedRegistry share one key: a feed_id string. Read the value from one and the metadata from the other, then compute value = amount / 10^decimals. See the two registries.

Writes are gated per feed, not per deployment. New feeds are registered by any caller holding a ZK eligibility credential, and the registry records that caller as the feed’s claimant; only the claimant can update or attest the feed afterwards. Feeds that predate the network upgrade remain with the first-party Claros agent, account-hash 43d7dd…21d4, which also owns the EligibilityGate and TreasuryVault. Any other caller of a gated entry point reverts with Unauthorized, so every attested value carries a verifiable attester you can check on-chain. See Run an agent and earn to claim a feed of your own.

Network

SettingValue
Network name (chain id)casper-test
JSON-RPC endpointhttps://node.testnet.casper.network/rpc
Block explorerhttps://testnet.cspr.live
Gas and fee tokenCSPR (fees are denominated in motes, where 1 CSPR = 1,000,000,000 motes)
Contract addressingby package hash (upgrades preserve the address)
Transaction formatCasper 2.0 (Condor) TransactionV1, signed with casper-js-sdk v5

Casper testnet charges the gas limit you set, not the gas you consume, and it does not refund the difference. A call that sets a 20 CSPR limit but uses 6 CSPR of compute still costs 20 CSPR. Size every transaction’s payment deliberately: too low and it runs out of gas (and you still pay the limit), too high and you overpay. The agent sizes each attestation and treasury call accordingly, and cross-contract reads should set a tight limit.

Deployment manifest

The full machine-readable manifest lives at shared/deployments.json. The package hashes below are the same ones the SDK bakes in as defaults, so most integrators never paste an address by hand.

{ "network": "casper-test", "rpc": "https://node.testnet.casper.network/rpc", "explorer": "https://testnet.cspr.live", "contracts": { "attestation_registry": "236b510436c60b6a797d175c72c6014de367d43f1de1ca45f580d112f98116cc", "feed_registry": "741cc223c14c2c00c9f06d7bb5c4be2f824fbf0c8b09a147bf1835570bddf5b6", "treasury_vault": "a90b082d863c5977c6e54654fec10e523a38760529e664a87e9e8a8e887ffd7b", "eligibility_gate": "7be33b056c8804e0886cd6f20a75109a0fe92deab505754b97a49fde15aa5227" }, "external": { "wcspr": "3d80df21ba4ee4d66a2a1f60c32570dd5685e4b279f6538162a5fd1314847c1e", "wiselending_scspr": "baa50d1500aa5361c497c06b40f2822ebb0b5fce5b1c3a037ea628cb68d920f3" }, "agent_account_hash": "43d7dd06d5538e504e54a3f235f1596f7d2e803e9065bf3c0d040f5cd31a21d4" }

These values are package hashes (no hash- or contract- prefix). When you query global state directly, prefix a package hash with hash- (for example hash-236b51…16cc), which is exactly what the SDK does under the hood.

Contract reference

Each contract is an Odra module. Below are the key entry points (parameter types as declared in contracts/src), the events they emit, and the revert errors they define. Every getter is a free read; the privileged write entry points revert for any caller other than the role noted.

AttestationRegistry

The value store. The agent calls attest once per genuinely new period; everyone else reads.

Source: contracts/src/attestation_registry.rs. Package 236b51…16cc, contract 48bba0…e75b (v2), installed in transaction ed0820…90fd and upgraded in 954e7b…2244.

Entry pointSignatureAccessReturns
attestattest(asset_id: String, period: u64, amount: U512, source_hash: String)Feed claimant only (legacy attester for pre-network feeds)none, emits RevenueAttested
get_latestget_latest(asset_id: String)Public viewOption<Attestation>
get_atget_at(asset_id: String, index: u64)Public viewOption<Attestation>
get_countget_count(asset_id: String)Public viewu64 (history length for a feed)
total_attestationstotal_attestations()Public viewu64 (global count across feeds)
get_attesterget_attester()Public viewAddress

get_latest returns an Attestation { period: u64, amount: U512, source_hash: String, attester: Address, timestamp: u64 }, where timestamp is the chain commit time in epoch milliseconds. See the attestation record for the field meanings and freshness rules.

  • Event: RevenueAttested { asset_id, period, amount, source_hash, index, timestamp }
  • Error: Unauthorized (for a claimed feed, a caller other than its claimant invoked attest; for pre-network feeds, a caller other than the legacy attester)

FeedRegistry

The metadata store. Holds one self-describing Feed record per feed_id, so a consumer can interpret a value entirely on-chain (the Pyth model: the value ships with its exponent and unit).

Source: contracts/src/feed_registry.rs. Package 741cc2…f5b6, deployed in transaction 83487c…8917.

Entry pointSignatureAccessReturns
register_feedregister_feed(feed_id: String, decimals: u8, unit: String, title: String, source: String, route: String, frequency: String, description: String)ZK-eligible callers (new feeds; caller becomes claimant), claimant only (updates)none, emits FeedRegistered
get_feedget_feed(feed_id: String)Public viewOption<Feed>
get_feed_atget_feed_at(index: u64)Public viewOption<String> (the feed_id at that index)
feed_countfeed_count()Public viewu64

get_feed returns a Feed { decimals: u8, unit: String, title: String, source: String, route: String, frequency: String, description: String }. Re-registering an existing feed_id updates it in place and does not double-count. Use feed_count with get_feed_at to enumerate every live feed (the SDK wraps this as listFeedIds).

  • Event: FeedRegistered { feed_id, decimals, unit, source }
  • Error: Unauthorized (a new-feed caller without a ZK eligibility credential, or an update by anyone other than the feed’s claimant)

TreasuryVault

The agent’s on-chain reinvestment ledger. The agent records each treasury decision here after it attests, so the capital trail is auditable.

Source: contracts/src/treasury_vault.rs. Package a90b08…fd7b, contract 61a3b6…d0bf, deployed in transaction bcbe32…f2a0.

Entry pointSignatureAccessReturns
record_reinvestrecord_reinvest(venue: String, amount_in: U512, amount_out: U512, reasoning: String)Agent onlynone, emits Reinvested
update_holdingsupdate_holdings(wcspr_liquid: U512, scspr_held: U512)Agent onlynone, emits TreasuryUpdated
get_reinvestmentget_reinvestment(index: u64)Public viewOption<Reinvestment>
reinvestment_countreinvestment_count()Public viewu64
total_reinvestedtotal_reinvested()Public viewU512
venue_totalvenue_total(venue: String)Public viewU512 (total routed to one venue)
wcspr_liquidwcspr_liquid()Public viewU512
scspr_heldscspr_held()Public viewU512
get_agentget_agent()Public viewAddress

A Reinvestment is { venue: String, amount_in: U512, amount_out: U512, reasoning: String, timestamp: u64 }, where reasoning is the agent’s recorded rationale for the decision.

  • Events: Reinvested { index, venue, amount_in, amount_out, reasoning, timestamp }, TreasuryUpdated { wcspr_liquid, scspr_held, timestamp }
  • Error: Unauthorized (a caller other than the agent invoked a write)

EligibilityGate

A zero-knowledge access gate. A caller proves (off-chain) that it knows a secret whose leaf is in a depth-20 MiMC7 Merkle allowlist, without revealing which leaf. The contract verifies the Groth16 proof on-chain, binds the caller’s account, and burns a one-time nullifier so the proof cannot be replayed. The Claros agent clears this gate before it attests.

Source: contracts/src/eligibility_gate.rs. Package 7be33b…5227, deployed in transaction bb3595…be88.

Entry pointSignatureAccessReturns
verify_eligibilityverify_eligibility(proof: Vec<u8>, root: U256, nullifier_hash: U256)Public, proof-gatednone, emits EligibilityGranted
set_rootset_root(new_root: U256)Owner onlynone, emits RootUpdated
is_eligibleis_eligible(who: Address)Public viewbool
get_rootget_root()Public viewU256
granted_countgranted_count()Public viewu64

The public inputs to verify_eligibility are (root, nullifier_hash, caller). The on-chain allowlist root is currently 5652912302653102267326913836753961554938404630179929975228700590098587111483 (it moves as operators enroll), and the gate has granted eligibility twice so far (granted_count = 2: the first-party agent in transaction b3048a…a433 and operator #2 in f5b96c…9de7a). Internals are covered on the ZK eligibility gate page.

  • Events: EligibilityGranted { account, nullifier_hash, timestamp }, RootUpdated { root }
  • Errors: NotOwner (1), UnknownRoot (2), InvalidProof (3), AlreadyClaimed (4)

External packages

Two existing Casper testnet packages complete the agent’s economic loop. Claros does not own them; it integrates against their deployed package hashes.

PackagePackage hash (cspr.live)Role in Claros
WCSPR (Wrapped CSPR)3d80df…7c1eSettlement asset for the paid x402 feed. It supports transfer_with_authorization, which the x402 exact scheme uses so a client can authorize a transfer that the facilitator settles on-chain.
WiseLending sCSPRbaa50d…20f3Liquid-staking yield venue. The agent stakes treasury CSPR through its stake entry point, receives sCSPR, and records the move in the TreasuryVault.

See the autonomous agent for how the agent decides between staking into WiseLending, native delegation, and holding.

Referencing these contracts

How you point at these package hashes depends on where your code runs. The free off-chain reads use only the two registries; the contract path can call any of them.

The claros-oracle SDK has the testnet RPC and the two registry package hashes baked in as defaults, so there is nothing to paste:

import { ClarosOracle } from 'claros-oracle' const oracle = new ClarosOracle() // casper-test RPC + registries baked in // Override only to point at a different deployment: const custom = new ClarosOracle({ rpc: 'https://node.testnet.casper.network/rpc', attestationRegistry: '236b510436c60b6a797d175c72c6014de367d43f1de1ca45f580d112f98116cc', feedRegistry: '741cc223c14c2c00c9f06d7bb5c4be2f824fbf0c8b09a147bf1835570bddf5b6', })

The SDK reads the AttestationRegistry and FeedRegistry only. The TreasuryVault and EligibilityGate are read on-chain or over JSON-RPC.

Verify it on-chain

Nothing here requires trusting this page. Every claim is checkable on testnet right now.

  • Open the explorer. Each package hash above links to its cspr.live  contract-package page, where you can see its versions, entry points, and recent activity.
  • Count the feeds. FeedRegistry.feed_count returns 39 registered feeds (38 serving live values). The SDK helper feedCount() and GET /v1/feeds both reflect this.
  • Count the attestations. AttestationRegistry.total_attestations returns 78+ total attestations across all feeds.
  • Check the gate. EligibilityGate.granted_count returns 2.
import { ClarosOracle } from 'claros-oracle' const oracle = new ClarosOracle() await oracle.feedCount() // 37 await oracle.getReading('OP-1') // San Diego parking, value 2734.2 USD await oracle.getReading('EIA.PET.PRICE.WTI.DAILY')// WTI crude, value 78.94 $/bbl

Verify the deployed code matches the repo

Casper has no Etherscan-style “verified source” badge, so Claros ships the proof in the repository instead. contracts/wasm/ holds the exact deployed artifacts, and one script compares them byte-for-byte against the chain:

node scripts/verify-onchain.mjs

For each contract it fetches the install transaction from the public RPC, extracts the session module_bytes (the wasm the network stored at deploy time), and compares its sha256 against the artifact in contracts/wasm/. All four contracts match:

ContractDeployed wasm sha256
AttestationRegistry7c207fe977cd904a9ebd45f227373897e46235b3efcb2f4790c6bcef31b7a987
FeedRegistryf690dc619de65063cbec86fc1e891a58834cefe7a9a6c4d9064e1824eee85146
TreasuryVault5c0ff440ae985f94d68687a15de25100486714b331eb3f4a2f78f964a8076aee
EligibilityGate9b497c53c466d1f8d0eb3d2c203e06b892e8517123397820cc126695dfdd6db0

The script needs no keys and no dependencies, so anyone can rerun it against the public network at any time. The contracts build from contracts/src with Odra 2.8 on the repo’s pinned Rust toolchain.

Last updated on