Stellar Unified Price Oracle Aggregator
A decentralized price oracle aggregator built on Soroban (Stellar smart contracts). Collects price data from multiple permissioned oracle sources, aggregates via median , and exposes historical price data for consumer contracts.
Multi-source aggregation β register multiple oracle sources per asset, aggregate via median
Admin governance β admin controls sources, assets, decimals, description, history limits
Median price β robust single-statistic aggregation resistant to outliers and manipulation
Per-source prices β inspect individual source submissions for transparency
Historical prices β ledger-based price history with configurable retention
Contract upgradability β WASM-based upgrade mechanism
SEP-40 compliant β full implementation of the Stellar Oracle Consumer Interface standard
Contract events β all state changes emit on-chain events for indexers and monitoring
27 public endpoints β full admin, source, asset, submission, query, history, and SEP-40 interface
Function
Description
initialize(admin, min_sources, max_history, decimals, description)
Initialize the contract
set_admin(new_admin)
Transfer admin rights
get_admin_address()
Get current admin
set_min_sources_required(n)
Set minimum sources for aggregation
get_min_sources_required()
Get minimum sources required
set_max_history_length(n)
Set max historical records per asset
get_max_history_length()
Get max history length
set_decimals(n)
Set price decimals
get_decimals()
Get decimals
set_description(s)
Set contract description
get_description()
Get description
upgrade(new_wasm_hash)
Upgrade contract WASM
Function
Description
add_source(address, name)
Register an oracle source
remove_source(address)
Remove an oracle source
is_source(address) -> bool
Check if address is a registered source
get_oracle_sources() -> OracleSources
Get all registered sources
Function
Description
register_asset(asset)
Register a new asset
unregister_asset(asset)
Unregister an asset
is_asset_registered(asset) -> bool
Check if asset is registered
Function
Description
submit_price(source, asset, price, timestamp)
Submit a price (source only)
Function
Description
get_price(asset) -> AggregatePrice
Get latest aggregated price for an asset
get_source_price(asset, source) -> PriceEntry
Get latest price from a specific source
get_all_prices(asset) -> Vec<PriceEntry>
Get latest prices from all sources
get_latest_ledger() -> u32
Get the latest ledger with price data
Function
Description
get_historical_price(asset, ledger) -> PriceHistoryEntry
Get historical price at a specific ledger (interpolated if enabled)
get_historical_prices(asset, start, end) -> Vec<PriceHistoryEntry>
Get historical prices in a ledger range
has_historical_price(asset, ledger) -> bool
Check if historical price exists
set_interpolation_enabled(bool)
Enable/disable linear interpolation for history gaps (admin)
get_interpolation_enabled() -> bool
Check if interpolation is enabled
SEP-40 Oracle Consumer Interface
Function
Description
base() β Asset
Returns the base asset (USD)
assets() β Vec<Asset>
Returns all registered assets as Asset::Stellar
decimals() β u32
Returns price decimals
resolution() β u32
Returns staleness window in seconds (0 = no expiry)
price(asset, timestamp) β Option<PriceData>
Get price at or before a given timestamp
prices(asset, records) β Option<Vec<PriceData>>
Get latest N historical price records
lastprice(asset) β Option<PriceData>
Get latest aggregated price
Event
Trigger
Topics
Data
ContractInitializedEvent
initialize()
admin
min_sources, max_history, decimals, description
SourceAddedEvent
add_source()
source, admin
name
SourceRemovedEvent
remove_source()
source, admin
β
AssetRegisteredEvent
register_asset()
asset, admin
β
AssetUnregisteredEvent
unregister_asset()
asset, admin
β
PriceSubmittedEvent
submit_price()
asset, source
price, timestamp
PriceUpdatedEvent
aggregate price changes
asset
new_price, old_price, timestamp
AdminChangedEvent
set_admin()
old_admin, new_admin
β
ContractUpgradedEvent
upgrade()
new_wasm_hash
β
scripts/oracle-cli.sh is a shell script plugin that wraps stellar contract invoke with
oracle-specific ergonomics.
stellar CLI installed and configured
ORACLE_CONTRACT_ID environment variable set to your deployed contract address
Command
Description
oracle-cli init
Initialize a newly deployed contract
oracle-cli submit-price
Submit a price from a registered source
oracle-cli get-price
Get the latest aggregated price for an asset
oracle-cli add-source
Register a new oracle source (admin)
oracle-cli register-asset
Register a new asset (admin)
oracle-cli health-check
Display contract configuration and live status
export ORACLE_CONTRACT_ID=CAAAA...
export ORACLE_NETWORK=testnet # default: testnet
# Initialize
./scripts/oracle-cli.sh init \
--admin GAAA... --admin-key my-admin \
--description " My Oracle" --decimals 18
# Add a source
./scripts/oracle-cli.sh add-source \
--address GBBB... --name " Chainlink" --admin-key my-admin
# Register an asset
./scripts/oracle-cli.sh register-asset \
--asset GCCC... --admin-key my-admin
# Submit a price (price = 50 000 Γ 10^18)
./scripts/oracle-cli.sh submit-price \
--source GBBB... --asset GCCC... \
--price 50000000000000000000 \
--source-key my-source-identity
# Query latest price
./scripts/oracle-cli.sh get-price --asset GCCC...
# Health check
./scripts/oracle-cli.sh health-check
Rust (stable toolchain, see rust-toolchain.toml)
Soroban CLI (optional, for deployment)
All 79 tests pass with zero warnings.
Deploys the contract to Stellar testnet and runs a full lifecycle test:
See docs/e2e-testnet.md for prerequisites, configuration, and expected output.
soroban contract deploy \
--wasm target/wasm32v1-none/release/price_oracle.wasm \
--source < identity> \
--network testnet
contracts/price-oracle/
βββ Cargo.toml
βββ .cargo/config.toml
βββ src/
βββ lib.rs # Contract entrypoint and endpoint implementations
βββ types.rs # Data types, storage keys, error codes
βββ storage.rs # Storage helpers and median computation
βββ events.rs # Contract event definitions
βββ test.rs # Test suite (65 tests)
Layer
Technology
Contract
Rust, Soroban SDK v26
Target
wasm32v1-none (WebAssembly)
Aggregation
On-chain median (Rust)
Testing
#[cfg(test)] with soroban-sdk/testutils
Code
Name
Description
0
NotAuthorized
Caller is not the admin or required signer
1
AlreadyInitialized
Contract already initialized
2
AssetNotRegistered
Asset not found
3
AssetAlreadyRegistered
Asset already registered
4
SourceAlreadyExists
Source already registered
5
SourceNotFound
Source not found
6
InsufficientSources
Not enough sources for aggregation
7
InvalidPrice
Price is zero or negative
8
NoData
No price data available (or gap with interpolation disabled)
9
InvalidTimestamp
Submitted timestamp too far in the future
10
InvalidConfiguration
Configuration parameter out of valid range
11
DescriptionTooLong
Description exceeds 256 characters
12
ContractPaused
Contract is paused; operations blocked
13
TimelockNotReady
Timelock delay has not elapsed
14
OperationNotFound
No pending timelock operation with that ID
15
PriceBelowMinimum
Price is below the asset's configured minimum
See docs/error-codes.md for the full registry with causes and resolutions.
Document
Description
Architecture
System design, data flow, module structure
Deployment Record
Contract addresses, initialization parameters, admin addresses, deployment checklist
Security Audit Checklist
Pre-audit review items: access control, input validation, arithmetic safety, storage safety, upgrade mechanism, event integrity, known patterns
Monitoring Dashboard
Grafana dashboard setup and metrics reference
MIT
See docs/SLA.md for price freshness guarantees, uptime commitments, deviation thresholds, incident response times, and compensation terms.