- Introduced Aggregator.sol for Chainlink-compatible oracle functionality, including round-based updates and access control. - Added OracleWithCCIP.sol to extend Aggregator with CCIP cross-chain messaging capabilities. - Created .gitmodules to include OpenZeppelin contracts as a submodule. - Developed a comprehensive deployment guide in NEXT_STEPS_COMPLETE_GUIDE.md for Phase 2 and smart contract deployment. - Implemented Vite configuration for the orchestration portal, supporting both Vue and React frameworks. - Added server-side logic for the Multi-Cloud Orchestration Portal, including API endpoints for environment management and monitoring. - Created scripts for resource import and usage validation across non-US regions. - Added tests for CCIP error handling and integration to ensure robust functionality. - Included various new files and directories for the orchestration portal and deployment scripts.
7.3 KiB
Price Feed Setup Guide
Date: 2025-01-27 Status: ✅ COMPLETE
Overview
This guide explains how to set up price feeds for the Reserve System, including both mock feeds for testing and real Chainlink aggregators for production.
Architecture
Components
- OraclePriceFeed - Integrates Reserve System with Chainlink-compatible aggregators
- MockPriceFeed - Mock price feed for testing and development
- ReserveSystem - Core reserve system that receives price updates
Flow
Chainlink Aggregator / MockPriceFeed
│
▼
OraclePriceFeed
│
▼
ReserveSystem
Setup Options
Option 1: Mock Price Feeds (Testing/Development)
Use mock price feeds for testing and development environments.
Advantages:
- No external dependencies
- Full control over prices
- Easy to test edge cases
- No API costs
Usage:
export USE_MOCK_FEEDS=true
export XAU_ASSET=<xau_token_address>
export USDC_ASSET=<usdc_token_address>
export ETH_ASSET=<eth_token_address>
forge script script/reserve/SetupPriceFeeds.s.sol:SetupPriceFeeds \
--rpc-url chain138 \
--broadcast
Option 2: Real Chainlink Aggregators (Production)
Use real Chainlink aggregators for production environments.
Advantages:
- Real-time market prices
- High reliability
- Industry standard
- Multiple data sources
Usage:
export USE_MOCK_FEEDS=false
export XAU_ASSET=<xau_token_address>
export XAU_AGGREGATOR=<chainlink_xau_usd_aggregator>
export USDC_ASSET=<usdc_token_address>
export USDC_AGGREGATOR=<chainlink_usdc_usd_aggregator>
export ETH_ASSET=<eth_token_address>
export ETH_AGGREGATOR=<chainlink_eth_usd_aggregator>
forge script script/reserve/SetupPriceFeeds.s.sol:SetupPriceFeeds \
--rpc-url chain138 \
--broadcast
Step-by-Step Setup
Step 1: Deploy OraclePriceFeed (if not already deployed)
The SetupPriceFeeds.s.sol script will automatically deploy OraclePriceFeed if not provided via environment variable.
Step 2: Configure Aggregators
For Mock Feeds:
# Set environment variables
export RESERVE_SYSTEM=<reserve_system_address>
export RESERVE_ADMIN=<admin_address>
export USE_MOCK_FEEDS=true
# Asset addresses (use test token addresses)
export XAU_ASSET=0x1111111111111111111111111111111111111111
export USDC_ASSET=0x2222222222222222222222222222222222222222
export ETH_ASSET=0x3333333333333333333333333333333333333333
# Run setup script
forge script script/reserve/SetupPriceFeeds.s.sol:SetupPriceFeeds \
--rpc-url chain138 \
--broadcast
For Real Aggregators:
# Set environment variables
export RESERVE_SYSTEM=<reserve_system_address>
export RESERVE_ADMIN=<admin_address>
export USE_MOCK_FEEDS=false
# Asset addresses
export XAU_ASSET=<xau_token_address>
export USDC_ASSET=<usdc_token_address>
export ETH_ASSET=<eth_token_address>
# Chainlink aggregator addresses (example for Ethereum mainnet)
export XAU_AGGREGATOR=0x214eD9Da11D2fbe465a6fc601a91E62EbEc1a0D6 # XAU/USD
export USDC_AGGREGATOR=0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6 # USDC/USD
export ETH_AGGREGATOR=0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419 # ETH/USD
# Run setup script
forge script script/reserve/SetupPriceFeeds.s.sol:SetupPriceFeeds \
--rpc-url chain138 \
--broadcast
Step 3: Update Price Feeds
Price feeds can be updated manually or via automated keeper:
// Manual update
oraclePriceFeed.updatePriceFeed(assetAddress);
// Update multiple assets
address[] memory assets = [xauAsset, usdcAsset, ethAsset];
oraclePriceFeed.updateMultiplePriceFeeds(assets);
Step 4: Verify Price Feeds
// Check if update is needed
bool needsUpdate = oraclePriceFeed.needsUpdate(assetAddress);
// Get current price
(uint256 price, uint256 timestamp) = reserveSystem.getPrice(assetAddress);
Price Feed Configuration
Supported Assets
Common assets to configure:
-
Gold (XAU)
- Token: XAU token address
- Aggregator: Chainlink XAU/USD
- Decimals: 8 (Chainlink) → 18 (Reserve System)
- Multiplier: 1e10
-
USDC
- Token: USDC token address
- Aggregator: Chainlink USDC/USD
- Decimals: 8 (Chainlink) → 18 (Reserve System)
- Multiplier: 1e10
-
ETH
- Token: ETH/WETH token address
- Aggregator: Chainlink ETH/USD
- Decimals: 8 (Chainlink) → 18 (Reserve System)
- Multiplier: 1e10
Price Multipliers
Price multipliers convert from aggregator decimals (typically 8) to Reserve System decimals (18):
- 8 decimals → 18 decimals: Multiplier = 1e10
- 18 decimals → 18 decimals: Multiplier = 1e0 (1)
Update Interval
Default update interval: 30 seconds
Can be configured:
oraclePriceFeed.setUpdateInterval(60); // 60 seconds
Mock Price Feed Usage
Deploy Mock Price Feed
// Deploy with initial price
MockPriceFeed mockFeed = new MockPriceFeed(2000 * 1e8, 8); // $2000, 8 decimals
Update Mock Price
// Update price
mockFeed.updatePrice(2100 * 1e8); // $2100
// Update with custom timestamp
mockFeed.updatePriceWithTimestamp(2100 * 1e8, block.timestamp - 10);
Get Price Data
// Get latest answer
int256 price = mockFeed.latestAnswer();
// Get latest round data
(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
mockFeed.latestRoundData();
Automated Price Updates
Keeper Integration
Set up a keeper to automatically update price feeds:
// Example keeper script
const OraclePriceFeed = await ethers.getContractAt("OraclePriceFeed", oraclePriceFeedAddress);
const assets = [xauAsset, usdcAsset, ethAsset];
// Check if updates are needed
for (const asset of assets) {
const needsUpdate = await OraclePriceFeed.needsUpdate(asset);
if (needsUpdate) {
await OraclePriceFeed.updatePriceFeed(asset);
}
}
Cron Job Example
#!/bin/bash
# Update price feeds every 30 seconds
while true; do
forge script script/reserve/UpdatePriceFeeds.s.sol:UpdatePriceFeeds \
--rpc-url chain138 \
--broadcast
sleep 30
done
Troubleshooting
Price Feed Not Available
Error: ReserveSystem: price feed not available
Solution:
- Verify aggregator is set:
oraclePriceFeed.aggregators(asset) - Update price feed:
oraclePriceFeed.updatePriceFeed(asset) - Check aggregator is returning valid data
Stale Price
Error: ReserveSystem: stale source price
Solution:
- Update price feed more frequently
- Increase update interval if needed
- Check aggregator is updating regularly
Invalid Price
Error: OraclePriceFeed: invalid price
Solution:
- Verify aggregator is returning positive values
- Check aggregator is not paused
- Verify aggregator address is correct
Security Considerations
- Access Control: Only authorized addresses can update price feeds
- Price Validation: Prices are validated before updating Reserve System
- Staleness Check: Prices older than threshold are rejected
- Multi-Sig: Consider using multi-sig for critical price feed updates