The Lux Price Oracle aggregates prices from multiple on-chain and off-chain sources into a single canonical price per asset pair. Sources include AMM V3 TWAP (LP-041), K-chain oracle feeds (LP-038), and StableSwap virtual prices (LP-042). The aggregator uses a weighted median with freshness scoring to produce manipulation-resistant prices for use by lending protocols, perpetuals, and other DeFi primitives.
Each price feed aggregates from registered sources:
Source {
sourceType uint8 // 0=AMM_TWAP, 1=KCHAIN, 2=STABLESWAP, 3=CUSTOM
sourceAddr address // contract address or feed ID
weight uint256 // aggregation weight
maxStaleness uint256 // max seconds before source is considered stale
}
For each price update:
1. Query all registered sources for the current price
2. Discard stale sources (older than maxStaleness)
3. Discard outliers (>3 standard deviations from the unweighted median)
4. Compute weighted median of remaining sources
5. Emit PriceUpdated(feedId, price, timestamp, sourceCount)
AMM V3 TWAP: reads the cumulative tick accumulator from V3 pools. Default window: 30 minutes. Resistant to single-block manipulation.
K-chain feed: reads the latest aggregated price from the Oracle VM (LP-038). Sub-second freshness.
StableSwap virtual price: for LP token pricing, reads get_virtual_price() from StableSwap pools (LP-042). Monotonically increasing.
Custom: any contract implementing IOracle.getPrice() returns (uint256 price, uint256 timestamp).
interface IPriceOracle {
function getPrice(bytes32 feedId) external view returns (uint256 price, uint256 timestamp);
function getPriceTWAP(bytes32 feedId, uint256 window) external view returns (uint256 price);
}
If the primary source is stale, the oracle falls through a priority chain:
1. K-chain feed (highest priority, freshest)
2. AMM V3 30-minute TWAP
3. AMM V3 2-hour TWAP (wider window, more resistant)
4. Last known price with staleness flag
Consumers can check timestamp to determine freshness.
If the price changes >20% in a single update, the oracle pauses for 5 minutes and re-queries. This prevents flash crash propagation to dependent protocols.
1. Multi-source resilience: compromising a single source is insufficient to manipulate the aggregated price (requires >50% of weighted sources).
2. TWAP window: 30-minute TWAP requires sustained manipulation over 30 minutes of on-chain trading, making attacks expensive.
3. Circular dependency: oracle prices must not depend on protocols that themselves depend on the oracle (e.g., oracle using lending pool prices that use the same oracle for liquidations).
github.com/luxfi/standard/contracts/oracle/ |PriceAggregator.sol |Copyright (C) 2024-2026, Lux Partners Limited. All rights reserved.
Licensed under the MIT License.