Skip to main content

Reflector — live oracle feeds (X1)

Goal: replace the testnet mock feed with a live Reflector SEP-40 oracle in the oracle-adapter. Everything below was researched from official sources and adversarially re-verified; each contract ID was confirmed live via stellar-cli against soroban-testnet.stellar.org.

✅ Live on testnet (done)

The vault's NAV now reads a live Reflector feed. The reflector-feed shim (deployed on testnet) maps our LEOD symbol → Reflector's Asset::Other("USDC") on the CEX/DEX feed — a stable ~$1 par-NAV proxy, since no RWA feed exists on Reflector testnet (see below). oracle-adapter.get_nav(LEOD) returns the live price (≈ $1.0008), self-refreshing every ~5 min, so it never goes stale. This powers the live performance dashboard.

Sourcing discipline

Version-volatile facts here are dated (2026-07-17) and cited, per the repo's INTEGRATIONS/ rule. The canonical copy is INTEGRATIONS/reflector.md.

Contract IDs (verified)

Feeds published in Stellar's oracle providers list and confirmed on-chain:

FeedNetworkContract ID
Stellar DEXtestnetCAVLP5DH2GJPZMVO7IJY4CVOD5MWEFTJFVPD2YY2FQXOQHRGHK4D6HLP
External CEX/DEXtestnetCCYOZJCOPG34LLQQ7N24YXBM7LL62R7ONMZ3G6WZAAYPB5OYKOMJRN63
Fiat / FXtestnetCCSSOHTBL3LEWUCBBEB5NJFC2OKFRC74OWEIJIZLRJBGAAU4VMU5NV4W
Stellar DEXmainnetCALI2BYU2JE6WVRUFYTS6MSBNEHGJ35P4AVCZYF3B6QOE3QKOB2PLE6M
External CEX/DEXmainnetCAFJZQWSED6YAWZU3GWRTOCNPPCGBN32L7QV43XX5LZLFTK6JLN34DLN
Fiat / FXmainnetCBKGPWGKSKZF52CFHMTRR23TBWTPMRDIYZ4O2P5VS65BMHYH4DXMCJZC

Interface

Reflector implements SEP-40. The asset selector is an enum:

enum Asset { Stellar(Address), Other(Symbol) } // Stellar assets vs external symbols
struct PriceData { price: i128, timestamp: u64 }

fn lastprice(asset: Asset) -> Option<PriceData>;
fn price(asset: Asset, timestamp: u64) -> Option<PriceData>;
fn decimals() -> u32; // = 14 on all three testnet feeds (live-queried)
fn resolution() -> u32; // = 300 (5-min heartbeat) on all three
fn base() -> Asset; // Other("USD") on CEX/DEX + FX; a Stellar-asset SAC on the DEX feed
  • Decimals = 14, resolution = 300 s — confirmed live on all three testnet feeds.
  • Pulse feeds are free, 5-minute cadence; history retention 24 h.

Adapter mapping

Leontief's adapter takes asset: Symbol; Reflector takes asset: Asset. The integration maps our Symbol asset-id to Asset::Other(Symbol) (for symbol-priced assets) or Asset::Stellar(Address) (for Stellar-asset-priced ones), reads the i128 price + u64 timestamp, and normalizes from 14 decimals → SCALE (10¹²). Recalibrate max_age_secs to cadence ×2.5 = 750 s.

This mapping is implemented by the reflector-feed shim contract — it exposes the adapter's lastprice(Symbol) surface, forwards to the live Reflector lastprice(Asset), and passes the XDR-identical PriceData through untouched, so the fail-closed core is unchanged. One command wires it end-to-end: source deploy.env && ./scripts/wire_reflector.sh.

The RWA-feed gap (the decisive finding)

No RWA feeds on testnet — keep the mock

The testnet CEX/DEX feed carries 16 crypto majors + EURC; the FX feed carries 23 fiat currencies plus XAU (gold). None of USDY / CETES / USTRY (or other Etherfuse/Ondo RWAs) have a Reflector feed on testnet — nor were any identifiable on mainnet. The FX feed's TRY is the Turkish Lira, not USTRY.

Consequence (as wired): the demo asset LEOD is mapped to Reflector's USDC feed — a live, stable ~$1 par-NAV proxy — so the live-oracle path runs end-to-end on real market data (a par bond NAV is ~$1, so USDC is a faithful stand-in). USDC (or USDT) is used precisely because it's stable: a volatile crypto feed would swing the NAV and crater collateral. The mainnet plan is to swap this proxy for a dedicated RWA price source (issuer NAV feed or a Reflector subscription feed) before any real asset is wrapped.

Drill

With a live feed configured, the deviation breaker is exercised by tightening max_dev_bps, observing the PriceDeviation halt, and re-arming via the prototype accept_override (which emits the loud override_accepted event). This proves fail-closed behavior against real feed movement.