Lux Standard

Oracles

Unified price feeds for all Lux DeFi protocols

Oracles

THE standard Oracle system for all Lux DeFi protocols - Perps, Lending, AMM, Flash Loans.

Architecture

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                              ORACLE ARCHITECTURE                                         │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                          │
│   PRICE SOURCES (IOracleSource)                                                         │
│   ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐                 │
│   │Chainlink │  │   Pyth   │  │  TWAP    │  │   DEX    │  │OracleHub │                 │
│   │ Adapter  │  │ Adapter  │  │ Source   │  │Precompile│  │(written) │                 │
│   └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘                 │
│        │             │             │             │             │                        │
│        └─────────────┴─────────────┴─────────────┴─────────────┘                        │
│                                    │                                                     │
│                         ┌──────────▼──────────┐                                         │
│                         │  Oracle.sol         │  ← THE interface for DeFi apps          │
│                         │  (aggregates all)   │                                         │
│                         └──────────┬──────────┘                                         │
│                                    │                                                     │
│            ┌───────────────────────┼───────────────────────┐                            │
│            │                       │                       │                            │
│   ┌────────▼────────┐   ┌─────────▼────────┐   ┌─────────▼────────┐                    │
│   │     Perps       │   │     Markets      │   │    Flash Loans   │                    │
│   │  VaultPriceFeed │   │ (Morpho-style)   │   │   (Atomic ops)   │                    │
│   └─────────────────┘   └──────────────────┘   └──────────────────┘                    │
│                                                                                          │
└─────────────────────────────────────────────────────────────────────────────────────────┘

DEX Gateway (~/work/lux/dex) writes prices → OracleHub → read by Oracle.sol

Core Contracts

ContractPathPurpose
Oraclecontracts/oracle/Oracle.solTHE main oracle for all DeFi apps
OracleHubcontracts/oracle/OracleHub.solOn-chain price hub (written by DEX)
ChainlinkAdaptercontracts/oracle/adapters/ChainlinkAdapter.solChainlink price feeds
PythAdaptercontracts/oracle/adapters/PythAdapter.solPyth Network feeds
TWAPSourcecontracts/oracle/sources/TWAPSource.solAMM TWAP prices
DEXSourcecontracts/oracle/sources/DEXSource.solDEX precompile (0x0400)

Interfaces

InterfacePathPurpose
IOraclecontracts/oracle/IOracle.solMain oracle interface
IOracleSourcecontracts/oracle/interfaces/IOracleSource.solIndividual price source
IOracleWritercontracts/oracle/interfaces/IOracleWriter.solPrice writing (DEX)
IOracleStrategycontracts/oracle/interfaces/IOracleStrategy.solAggregation strategies

Quick Start

import "@luxfi/contracts/oracle/IOracle.sol";

contract MyDeFiApp {
    IOracle public oracle;

    constructor(address _oracle) {
        oracle = IOracle(_oracle);
    }

    // Simple price query
    function getAssetPrice(address asset) public view returns (uint256) {
        (uint256 price, ) = oracle.getPrice(asset);
        return price; // 18 decimals, USD
    }

    // For perps: use maximize param
    function getPerpsPrice(address asset, bool isLong) public view returns (uint256) {
        return oracle.getPriceForPerps(asset, isLong);
    }

    // Batch query for gas efficiency
    function getMultiplePrices(address[] calldata assets) public view returns (uint256[] memory) {
        (uint256[] memory prices, ) = oracle.getPrices(assets);
        return prices;
    }

    // Check oracle health before critical ops
    function isOracleHealthy() public view returns (bool) {
        (bool healthy, uint256 sources) = oracle.health();
        return healthy && sources >= 2;
    }
}

IOracle Interface

interface IOracle {
    // Core price functions
    function getPrice(address asset) external view returns (uint256 price, uint256 timestamp);
    function getPriceIfFresh(address asset, uint256 maxAge) external view returns (uint256 price);
    function price(address asset) external view returns (uint256 price);
    function isSupported(address asset) external view returns (bool);

    // Batch operations (gas efficient)
    function getPrices(address[] calldata assets) external view returns (uint256[] memory, uint256[] memory);

    // Perps-specific
    function getPriceForPerps(address asset, bool maximize) external view returns (uint256 price);
    function isPriceConsistent(address asset, uint256 maxDeviationBps) external view returns (bool);

    // Health monitoring
    function health() external view returns (bool healthy, uint256 activeSourceCount);
    function isCircuitBreakerTripped(address asset) external view returns (bool);
}

Price Sources

import "@luxfi/contracts/integrations/oracles/ChainlinkAdapter.sol";

// Deploy
ChainlinkAdapter chainlink = new ChainlinkAdapter(
    3600  // max 1 hour staleness
);

// Configure feeds
chainlink.setFeed(WETH, 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419); // ETH/USD
chainlink.setFeed(WBTC, 0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c); // BTC/USD

// Get price
(uint256 price, uint256 timestamp) = chainlink.getPrice(WETH);

2. Pyth (Pull Oracle)

import "@luxfi/contracts/integrations/oracles/RedStoneAdapter.sol";

// Pyth price IDs
bytes32 constant ETH_USD = 0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace;
bytes32 constant BTC_USD = 0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43;

// Deploy
PythAdapter pyth = new PythAdapter(
    0x4305FB66699C3B2702D4d05CF36551390A4c69C6, // Pyth contract
    60  // max 60s staleness
);

// Configure feeds
pyth.setFeed(WETH, ETH_USD);
pyth.setFeed(WBTC, BTC_USD);

// Update prices (required before reading)
pyth.updatePrices{value: updateFee}(pythUpdateData);

// Get price
(uint256 price, uint256 timestamp) = pyth.getPrice(WETH);

3. TWAP (AMM-based)

import "@luxfi/contracts/oracle/sources/TWAPSource.sol";

// Deploy
TWAPSource twap = new TWAPSource(
    USDC,  // quote token
    6      // USDC decimals
);

// Configure pairs
twap.setPair(WETH, WETH_USDC_PAIR);
twap.setPair(WBTC, WBTC_USDC_PAIR);

// Get TWAP (30 min default)
(uint256 price, uint256 timestamp) = twap.getPrice(WETH);

4. DEX Precompile (Native)

import "@luxfi/contracts/oracle/sources/DEXSource.sol";

// Deploy
DEXSource dex = new DEXSource(LUSD); // quote token

// Configure pools
dex.setPool(
    WETH,           // asset
    3000,           // fee tier (0.3%)
    60,             // tick spacing
    address(0)      // no hooks
);

// Get spot price from DEX precompile (0x0400)
(uint256 price, uint256 timestamp) = dex.getPrice(WETH);

5. OracleHub (DEX-Written Prices)

The DEX gateway (~/work/lux/dex) writes prices to OracleHub:

import "@luxfi/contracts/oracle/OracleHub.sol";

// DEX gateway writes prices
oracleHub.writePrice(WETH, 4000e18, block.timestamp);

// Or with validator signatures (trustless)
oracleHub.writeQuorumPrice(signedUpdates, 3); // 3-of-5 quorum

// DeFi apps read via Oracle.sol
(uint256 price, ) = oracle.getPrice(WETH);

Aggregation Strategies

import "@luxfi/contracts/oracle/interfaces/IOracleStrategy.sol";

// Available strategies
MedianStrategy median = new MedianStrategy();  // Default, manipulation-resistant
MeanStrategy mean = new MeanStrategy();        // Simple average
MinStrategy min = new MinStrategy();           // Conservative (liquidations)
MaxStrategy max = new MaxStrategy();           // Aggressive (borrowing limits)

// Set strategy on Oracle
oracle.setStrategy(IOracleStrategy(address(median)));

Perps Integration

For perpetual futures, use getPriceForPerps with spread:

contract PerpsVault {
    IOracle public oracle;

    function openPosition(
        address asset,
        uint256 size,
        bool isLong
    ) external {
        // Use maximize=true for longs (worse entry price)
        // Use maximize=false for shorts
        uint256 entryPrice = oracle.getPriceForPerps(asset, isLong);

        // Check price consistency before large trades
        require(oracle.isPriceConsistent(asset, 100), "Price deviation >1%");

        // Open position at entry price...
    }

    function liquidate(address user, address asset) external {
        // Check circuit breaker before liquidation
        require(!oracle.isCircuitBreakerTripped(asset), "Circuit breaker active");

        // Get liquidation price
        (uint256 price, ) = oracle.getPrice(asset);

        // Execute liquidation...
    }
}

Lending Integration

For Morpho-style lending markets:

contract LendingMarket {
    IOracle public oracle;

    function getCollateralValue(
        address asset,
        uint256 amount
    ) public view returns (uint256 valueUsd) {
        (uint256 price, uint256 timestamp) = oracle.getPrice(asset);

        // Validate freshness for critical operations
        require(block.timestamp - timestamp < 1 hours, "Stale price");

        valueUsd = (amount * price) / 1e18;
    }

    function isLiquidatable(address user) public view returns (bool) {
        // Batch query for gas efficiency
        address[] memory assets = getUserAssets(user);
        (uint256[] memory prices, ) = oracle.getPrices(assets);

        // Calculate health factor...
    }
}

Flash Loan Safety

Oracle provides atomic price guarantees within transactions:

contract FlashLoanArbitrage {
    IOracle public oracle;

    function executeArbitrage(
        address asset,
        uint256 amount
    ) external {
        // Get price at start (view function = atomic)
        (uint256 startPrice, ) = oracle.getPrice(asset);

        // Execute flash loan and swaps...

        // Same price guaranteed within tx
        (uint256 endPrice, ) = oracle.getPrice(asset);
        assert(startPrice == endPrice); // Always true within same block
    }
}

DEX Integration

The DEX gateway (~/work/lux/dex) provides:

SourceWeightUpdate IntervalDescription
X-Chain2.050msNative DEX orderbook (highest trust)
C-Chain AMM1.8100msLiquid tokens (LETH, LBTC, etc.)
Zoo Chain1.7100msZOO token pairs
A-Chain1.5100-200msValidator attestations
Pyth1.2Real-timeWebSocket streaming
Chainlink1.0~1sReference only

The DEX aggregates all sources and writes to OracleHub via:

  • writePrice() - Keeper-based updates
  • writeSignedPrice() - Single validator signature
  • writeQuorumPrice() - Multi-validator consensus

Circuit Breakers

Automatic protection against price manipulation:

// Oracle configuration
oracle.setCircuitBreakerConfig(
    1000,     // 10% max price change
    5 minutes // cooldown period
);

// Check before critical operations
if (oracle.isCircuitBreakerTripped(asset)) {
    revert("Circuit breaker active, try later");
}

// Manual reset by guardian
oracle.resetCircuitBreaker(asset);

Health Monitoring

// Check overall health
(bool healthy, uint256 sourceCount) = oracle.health();
require(healthy && sourceCount >= 2, "Oracle unhealthy");

// Check individual source health
(bool srcHealthy, uint256 lastHb) = chainlinkAdapter.health();

Gas Optimization

// BAD: Multiple individual calls
uint256 ethPrice = oracle.price(WETH);
uint256 btcPrice = oracle.price(WBTC);
uint256 luxPrice = oracle.price(LUX);

// GOOD: Single batch call
address[] memory assets = new address[](3);
assets[0] = WETH;
assets[1] = WBTC;
assets[2] = LUX;

(uint256[] memory prices, ) = oracle.getPrices(assets);

Deployment

// 1. Deploy strategies
MedianStrategy medianStrategy = new MedianStrategy();

// 2. Deploy main Oracle
Oracle oracle = new Oracle(address(medianStrategy));

// 3. Deploy and add sources
ChainlinkAdapter chainlink = new ChainlinkAdapter(3600);
PythAdapter pyth = new PythAdapter(PYTH_CONTRACT, 60);
TWAPSource twap = new TWAPSource(USDC, 6);
DEXSource dex = new DEXSource(LUSD);
OracleHub hub = new OracleHub();

oracle.addSource(IOracleSource(address(chainlink)));
oracle.addSource(IOracleSource(address(pyth)));
oracle.addSource(IOracleSource(address(twap)));
oracle.addSource(IOracleSource(address(dex)));
oracle.addSource(IOracleSource(address(hub)));

// 4. Configure
oracle.setConfig(
    1 hours,  // maxAge
    500,      // maxDeviationBps (5%)
    2         // minSources
);

// 5. Grant DEX gateway writer access to OracleHub
hub.addWriter(DEX_GATEWAY);

Security Considerations

RiskMitigation
Stale pricesFreshness checks with maxAge
Flash loan manipulationTWAP over 30+ minutes
Single source failureMulti-source aggregation (minSources=2)
Price manipulationMedian aggregation + deviation checks
Oracle downtimeMultiple sources + fallback logic
Large price swingsCircuit breakers (10% max change)
  • Perpetuals - Uses getPriceForPerps with spread
  • Lending - Uses oracles for collateral valuation
  • AMM - TWAP source integration
  • DEX Precompile - Native on-chain pricing at 0x0400

On this page