8.5 KiB
Automated Price Feed Keeper Setup Guide
Date: 2025-01-27 Status: ✅ COMPLETE
Overview
This guide explains how to set up automated price feed updates using the PriceFeedKeeper contract. The keeper automatically updates price feeds at regular intervals, ensuring prices stay current.
Architecture
Components
- PriceFeedKeeper Contract - On-chain keeper contract
- Keeper Service - Off-chain service that calls the keeper
- OraclePriceFeed - Price feed oracle integration
Flow
Keeper Service (Off-chain)
│
▼
PriceFeedKeeper Contract
│
▼
OraclePriceFeed
│
▼
ReserveSystem
Deployment
Step 1: Deploy PriceFeedKeeper
# Set environment variables
export PRIVATE_KEY=<deployer_private_key>
export RPC_URL_138=<chain138_rpc_url>
export ORACLE_PRICE_FEED=<oracle_price_feed_address>
export RESERVE_ADMIN=<admin_address>
# Optional: Asset addresses to track
export XAU_ASSET=<xau_token_address>
export USDC_ASSET=<usdc_token_address>
export ETH_ASSET=<eth_token_address>
# Optional: Keeper address (defaults to deployer)
export KEEPER_ADDRESS=<keeper_address>
# Deploy keeper
forge script script/reserve/DeployKeeper.s.sol:DeployKeeper \
--rpc-url chain138 \
--broadcast \
--verify
Step 2: Track Assets
Assets must be tracked before the keeper can update them:
// Via contract call
keeper.trackAsset(xauAsset);
keeper.trackAsset(usdcAsset);
keeper.trackAsset(ethAsset);
Or use the deployment script which automatically tracks assets if provided.
Keeper Service Options
Option 1: Node.js Keeper Service (Recommended)
Requirements:
- Node.js 16+
- npm packages:
ethers,dotenv
Setup:
# Install dependencies
npm install ethers dotenv
# Set environment variables
export RPC_URL_138=<chain138_rpc_url>
export KEEPER_PRIVATE_KEY=<keeper_wallet_private_key>
export PRICE_FEED_KEEPER_ADDRESS=<keeper_contract_address>
export UPDATE_INTERVAL=30 # seconds
# Run keeper service
node scripts/reserve/keeper-service.js
Features:
- Automatic retry logic
- Error handling
- Statistics tracking
- Graceful shutdown
- Event parsing
Option 2: Bash Keeper Service
Setup:
# Set environment variables
export RPC_URL_138=<chain138_rpc_url>
export PRICE_FEED_KEEPER_ADDRESS=<keeper_contract_address>
export UPDATE_INTERVAL=30 # seconds
# Make script executable
chmod +x scripts/reserve/keeper-service.sh
# Run keeper service
./scripts/reserve/keeper-service.sh
Features:
- Simple bash implementation
- Uses Foundry scripts
- Basic error handling
Option 3: Chainlink Keepers
Setup:
- Register keeper contract with Chainlink Keepers
- Fund keeper with LINK tokens
- Configure upkeep interval
Configuration:
// Register upkeep
const keeperRegistry = await ethers.getContractAt("KeeperRegistry", registryAddress);
await keeperRegistry.registerUpkeep(
keeperAddress, // Keeper contract address
gasLimit, // Gas limit for upkeep
adminAddress, // Admin address
checkData, // Check data (empty for our keeper)
amount, // LINK amount to fund
source, // Source address
encryptedEmail // Encrypted email (optional)
);
Option 4: Gelato Network
Setup:
- Register task with Gelato
- Configure execution interval
- Fund with native token
Configuration:
// Register task
const gelato = await ethers.getContractAt("Gelato", gelatoAddress);
await gelato.createTask(
keeperAddress, // Task contract
"performUpkeep()", // Function selector
interval, // Execution interval
executor // Executor address
);
Manual Upkeep
Check if Upkeep is Needed
forge script script/reserve/CheckUpkeep.s.sol:CheckUpkeep \
--rpc-url chain138
Perform Upkeep
export KEEPER_PRIVATE_KEY=<keeper_private_key>
export PRICE_FEED_KEEPER_ADDRESS=<keeper_address>
forge script script/reserve/PerformUpkeep.s.sol:PerformUpkeep \
--rpc-url chain138 \
--broadcast
Configuration
Update Interval
Set the update interval (in seconds):
keeper.setUpdateInterval(60); // 60 seconds
Maximum Updates Per Call
Limit the number of assets updated per call:
keeper.setMaxUpdatesPerCall(20); // Update up to 20 assets per call
Track/Untrack Assets
// Track asset
keeper.trackAsset(assetAddress);
// Untrack asset
keeper.untrackAsset(assetAddress);
Monitoring
Check Keeper Status
// Get tracked assets
address[] memory assets = keeper.getTrackedAssets();
// Check if asset needs update
bool needsUpdate = keeper.needsUpdate(assetAddress);
// Get update interval
uint256 interval = keeper.updateInterval();
Monitor Events
Listen for PriceFeedsUpdated events:
keeper.on("PriceFeedsUpdated", (assets, timestamp, event) => {
console.log("Updated assets:", assets);
console.log("Timestamp:", timestamp);
});
Running as a Service
Systemd Service
Create /etc/systemd/system/price-feed-keeper.service:
[Unit]
Description=Price Feed Keeper Service
After=network.target
[Service]
Type=simple
User=keeper
WorkingDirectory=/path/to/smom-dbis-138
Environment="RPC_URL_138=https://rpc.d-bis.org"
Environment="KEEPER_PRIVATE_KEY=0x..."
Environment="PRICE_FEED_KEEPER_ADDRESS=0x..."
Environment="UPDATE_INTERVAL=30"
ExecStart=/usr/bin/node scripts/reserve/keeper-service.js
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl enable price-feed-keeper
sudo systemctl start price-feed-keeper
sudo systemctl status price-feed-keeper
Docker Service
Create docker-compose.yml:
version: '3.8'
services:
keeper:
image: node:18
working_dir: /app
volumes:
- .:/app
environment:
- RPC_URL_138=${RPC_URL_138}
- KEEPER_PRIVATE_KEY=${KEEPER_PRIVATE_KEY}
- PRICE_FEED_KEEPER_ADDRESS=${PRICE_FEED_KEEPER_ADDRESS}
- UPDATE_INTERVAL=30
command: node scripts/reserve/keeper-service.js
restart: unless-stopped
Run:
docker-compose up -d
docker-compose logs -f keeper
Troubleshooting
Keeper Not Updating
Check:
- Keeper has
KEEPER_ROLE - Assets are tracked
- Update interval has passed
- Keeper service is running
Solution:
# Check upkeep status
forge script script/reserve/CheckUpkeep.s.sol:CheckUpkeep --rpc-url chain138
# Manually perform upkeep
forge script script/reserve/PerformUpkeep.s.sol:PerformUpkeep --rpc-url chain138 --broadcast
Gas Estimation Errors
Error: Gas estimation failed
Solution:
- Check keeper has sufficient balance
- Verify assets are tracked
- Check update interval hasn't passed
- Verify oracle price feed is configured
Transaction Failures
Error: Transaction reverted
Solution:
- Check keeper role permissions
- Verify oracle price feed address
- Check asset aggregators are set
- Verify price feeds are not stale
Security Considerations
- Private Key Security: Store keeper private key securely
- Access Control: Use multi-sig for admin functions
- Rate Limiting: Set appropriate update intervals
- Monitoring: Monitor keeper transactions and failures
- Backup: Run multiple keeper instances for redundancy
Best Practices
- Multiple Keepers: Run multiple keeper instances for redundancy
- Monitoring: Set up alerts for keeper failures
- Gas Management: Monitor gas prices and adjust intervals
- Error Handling: Implement retry logic and error reporting
- Logging: Log all keeper activities for auditing
Cost Estimation
Gas Costs
- Check Upkeep: ~30,000 gas (view function, no cost)
- Perform Upkeep: ~100,000 - 300,000 gas per asset
- Update 10 Assets: ~1,000,000 - 3,000,000 gas
Frequency
- Update Interval: 30 seconds (recommended)
- Updates Per Day: 2,880
- Gas Per Day: ~2.88M - 8.64M gas (for 10 assets)
Cost (at 20 gwei)
- Per Update: 0.02 - 0.06 ETH
- Per Day: 57.6 - 172.8 ETH
- Per Month: 1,728 - 5,184 ETH
Note: Costs vary based on gas prices and number of assets.