Contract reference
The Noeracle Soroban contract verifies signed prices inline in a consumer transaction and exposes a free best-effort read for the cache.
| Network | Stellar Testnet |
| Contract | CAYIP67UDVX5UPXGN3XDAWVIEFBAVG6G7LUESEOU3NUQKTWN55W34YBG |
| Source | oracle_v0/ |
Entrypoints
update_batch_ed25519_args
The production pull-mode entrypoint. Called inline in a consumer transaction.
fn update_batch_ed25519_args(
env: Env,
assets: Vec<BytesN<8>>,
prices: Vec<i128>,
timestamp: u64,
round_id: u64,
pubkey: BytesN<32>,
sigs: Vec<BytesN<64>>,
) -> Result<(), Error>
Verifies one Ed25519 signature per asset, checks that pubkey is a registered publisher, rejects rounds signed more than 60 seconds before the current ledger time, and writes each newer entry to temporary storage. Lagging rounds are silent no-ops — they never fail the consumer's transaction, because transaction landing order does not track round order across independent pull consumers.
get_price
fn get_price(env: Env, asset: BytesN<8>) -> Option<PriceEntry>
Returns the latest verified price for an asset, or None if TTL has expired. Free read. Freshness is opportunistic — high-traffic assets stay warm; low-traffic assets go cold.
init / set_publishers (admin)
fn init(env: Env, admin: Address, publishers: Vec<BytesN<32>>) -> Result<(), Error>
fn set_publishers(env: Env, publishers: Vec<BytesN<32>>) -> Result<(), Error>
init is called once at deploy. set_publishers rotates the publisher set; admin-authenticated.
Errors
| Code | Variant | When |
|---|---|---|
| 1 | AlreadyInitialized | init called more than once |
| 2 | NotInitialized | set_publishers or update_* called before init |
| 3 | BatchLengthMismatch | assets.len(), prices.len(), and sigs.len() differ |
| 4 | UnknownPublisher | pubkey is not in the registered set |
| 5 | StalePrice | now - timestamp > 60 seconds |
Signed message format
Publisher signatures cover a fixed 40-byte layout. The same layout is used identically by the contract, the attestation service, the SDK, and the host-isolated benchmark suite — kept in lockstep by a cross-language conformance test.
asset (8 bytes)
price (i128 big-endian, 16 bytes)
timestamp (u64 big-endian, 8 bytes)
round_id (u64 big-endian, 8 bytes)
Storage and TTL
| Key | Storage | TTL threshold | TTL extend |
|---|---|---|---|
PriceTemp(asset) | Temporary | 360 ledgers (~30 min) | 720 ledgers (~1 hr) |
PricePers(asset) | Persistent | 60,480 ledgers (~3.5 days) | 120,960 ledgers (~7 days) |
Publishers | Instance | — | — |
Production prices live in temporary storage — no rent accrual, clean failure semantics when entries expire. Persistent storage is reserved for RWA records (NAV history etc.) in future versions.