Oracle Module
The Oracle module provides decentralized price feeds for DeFi operations.
Overview
┌─────────────────────────────────────────────────────────────┐
│ Oracle Architecture │
│ │
│ External Sources Validator Network │
│ ┌──────────┐ ┌──────────────────┐ │
│ │Chainlink │───────────▶│ │ │
│ │ Pyth │───────────▶│ Price Voting │ │
│ │ Band │───────────▶│ (Validators) │ │
│ │ Custom │───────────▶│ │ │
│ └──────────┘ └────────┬─────────┘ │
│ │ │
│ ┌─────────▼─────────┐ │
│ │ Median Aggregation│ │
│ │ + TWAP │ │
│ └─────────┬─────────┘ │
│ │ │
│ ┌─────────▼─────────┐ │
│ │ On-Chain Price │ │
│ │ (Consensus) │ │
│ └───────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Price Feed Mechanism
Vote Extensions (ABCI 2.0)
Validators include price votes in block proposals:
type PriceVote struct {
Validator string
Prices []Price
Timestamp time.Time
Signature []byte
}
type Price struct {
Symbol string // e.g., "BTC"
Price sdk.Dec // e.g., 42000.50
Source string // e.g., "chainlink"
}
Aggregation
- Collect votes from 2/3+ validators
- Remove outliers (>3σ deviation)
- Calculate weighted median
- Apply TWAP smoothing
Supported Assets
| Symbol | Sources | Update Frequency |
|---|---|---|
| BTC | Chainlink, Pyth, Binance | Every block |
| ETH | Chainlink, Pyth, Coinbase | Every block |
| SOL | Pyth, FTX | Every block |
| RP1 | Internal DEX | Every block |
| USDC | Fixed (1.00) | N/A |
Query Prices
Current Price
rp1d query oracle price BTC
Output:
{
"symbol": "BTC",
"price": "42150.500000000000000000",
"timestamp": "2024-01-15T10:30:00Z",
"sources": 12
}
All Prices
rp1d query oracle prices
Historical TWAP
rp1d query oracle twap BTC --period 1h
TypeScript SDK
import { OracleModule } from '@rp1/sdk';
const oracle = new OracleModule(client);
// Get current price
const btcPrice = await oracle.getPrice('BTC');
console.log(`BTC: $${btcPrice.price}`);
// Get all prices
const prices = await oracle.getAllPrices();
prices.forEach(p => console.log(`${p.symbol}: $${p.price}`));
// Get TWAP
const twap = await oracle.getTWAP('ETH', '1h');
console.log(`ETH 1h TWAP: $${twap}`);
// Subscribe to price updates
oracle.subscribePrices(['BTC', 'ETH'], (price) => {
console.log(`${price.symbol} updated: $${price.price}`);
});
Oracle Daemon
Validators run the oracle daemon to submit prices:
Configuration
# oracle-config.yaml
sources:
- name: chainlink
endpoint: https://api.chainlink.com/v1
assets: [BTC, ETH]
weight: 0.4
- name: pyth
endpoint: https://pyth.network/api
assets: [BTC, ETH, SOL]
weight: 0.4
- name: binance
endpoint: wss://stream.binance.com
assets: [BTC, ETH, SOL]
weight: 0.2
settings:
update_interval: 500ms
max_deviation: 0.01 # 1% max deviation
timeout: 5s
Running the Daemon
rp1d oracle-daemon start --config oracle-config.yaml
Price Deviation Alerts
# Alert if price deviates >5% from TWAP
rp1d query oracle deviation BTC --threshold 0.05
Message Types
MsgSubmitPrice (Validator Only)
message MsgSubmitPrice {
string validator = 1;
repeated PriceData prices = 2;
bytes signature = 3;
}
message PriceData {
string symbol = 1;
string price = 2;
string source = 3;
google.protobuf.Timestamp timestamp = 4;
}
Parameters
| Parameter | Default | Description |
|---|---|---|
vote_threshold | 66% | Min validators for consensus |
max_deviation | 3% | Max price deviation allowed |
slash_window | 100 blocks | Window for missed votes |
slash_fraction | 0.01% | Slash for missing votes |
twap_period | 30 min | Default TWAP period |
Events
EventTypePriceUpdated = "oracle_price_updated"
EventTypePriceDeviation = "oracle_price_deviation"
EventTypeMissedVote = "oracle_missed_vote"
Using Oracle in Smart Contracts
Solidity (EVM)
import "@rp1/contracts/interfaces/IOracle.sol";
contract MyDeFi {
IOracle public oracle;
function getCollateralValue(
address token,
uint256 amount
) public view returns (uint256) {
uint256 price = oracle.getPrice(token);
return amount * price / 1e18;
}
}
CosmWasm
use rp1_oracle::query_price;
pub fn execute_swap(
deps: DepsMut,
info: MessageInfo,
token_in: String,
token_out: String,
) -> Result<Response, ContractError> {
let price_in = query_price(deps.as_ref(), &token_in)?;
let price_out = query_price(deps.as_ref(), &token_out)?;
// ... swap logic
}
Security
- Multi-source aggregation: No single source can manipulate price
- Outlier rejection: Statistical filtering removes anomalies
- TWAP smoothing: Resists flash loan attacks
- Slashing: Validators penalized for bad data