Some checks failed
Verify Deployment / Verify Deployment (push) Has been cancelled
CI/CD Pipeline / Solidity Contracts (push) Has been cancelled
CI/CD Pipeline / Security Scanning (push) Has been cancelled
CI/CD Pipeline / Lint and Format (push) Has been cancelled
CI/CD Pipeline / Terraform Validation (push) Has been cancelled
CI/CD Pipeline / Kubernetes Validation (push) Has been cancelled
Validation / validate-genesis (push) Has been cancelled
Validation / validate-terraform (push) Has been cancelled
Validation / validate-kubernetes (push) Has been cancelled
Validation / validate-smart-contracts (push) Has been cancelled
Validation / validate-security (push) Has been cancelled
Validation / validate-documentation (push) Has been cancelled
410 lines
8.5 KiB
Markdown
410 lines
8.5 KiB
Markdown
# 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
|
|
|
|
1. **PriceFeedKeeper Contract** - On-chain keeper contract
|
|
2. **Keeper Service** - Off-chain service that calls the keeper
|
|
3. **OraclePriceFeed** - Price feed oracle integration
|
|
|
|
### Flow
|
|
|
|
```
|
|
Keeper Service (Off-chain)
|
|
│
|
|
▼
|
|
PriceFeedKeeper Contract
|
|
│
|
|
▼
|
|
OraclePriceFeed
|
|
│
|
|
▼
|
|
ReserveSystem
|
|
```
|
|
|
|
---
|
|
|
|
## Deployment
|
|
|
|
### Step 1: Deploy PriceFeedKeeper
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```solidity
|
|
// 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**:
|
|
```bash
|
|
# 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**:
|
|
```bash
|
|
# 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**:
|
|
1. Register keeper contract with Chainlink Keepers
|
|
2. Fund keeper with LINK tokens
|
|
3. Configure upkeep interval
|
|
|
|
**Configuration**:
|
|
```javascript
|
|
// 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**:
|
|
1. Register task with Gelato
|
|
2. Configure execution interval
|
|
3. Fund with native token
|
|
|
|
**Configuration**:
|
|
```javascript
|
|
// 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
|
|
|
|
```bash
|
|
forge script script/reserve/CheckUpkeep.s.sol:CheckUpkeep \
|
|
--rpc-url chain138
|
|
```
|
|
|
|
### Perform Upkeep
|
|
|
|
```bash
|
|
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):
|
|
|
|
```solidity
|
|
keeper.setUpdateInterval(60); // 60 seconds
|
|
```
|
|
|
|
### Maximum Updates Per Call
|
|
|
|
Limit the number of assets updated per call:
|
|
|
|
```solidity
|
|
keeper.setMaxUpdatesPerCall(20); // Update up to 20 assets per call
|
|
```
|
|
|
|
### Track/Untrack Assets
|
|
|
|
```solidity
|
|
// Track asset
|
|
keeper.trackAsset(assetAddress);
|
|
|
|
// Untrack asset
|
|
keeper.untrackAsset(assetAddress);
|
|
```
|
|
|
|
---
|
|
|
|
## Monitoring
|
|
|
|
### Check Keeper Status
|
|
|
|
```solidity
|
|
// 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:
|
|
|
|
```javascript
|
|
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`:
|
|
|
|
```ini
|
|
[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**:
|
|
```bash
|
|
sudo systemctl enable price-feed-keeper
|
|
sudo systemctl start price-feed-keeper
|
|
sudo systemctl status price-feed-keeper
|
|
```
|
|
|
|
### Docker Service
|
|
|
|
Create `docker-compose.yml`:
|
|
|
|
```yaml
|
|
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**:
|
|
```bash
|
|
docker-compose up -d
|
|
docker-compose logs -f keeper
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Keeper Not Updating
|
|
|
|
**Check**:
|
|
1. Keeper has `KEEPER_ROLE`
|
|
2. Assets are tracked
|
|
3. Update interval has passed
|
|
4. Keeper service is running
|
|
|
|
**Solution**:
|
|
```bash
|
|
# 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**:
|
|
1. Check keeper has sufficient balance
|
|
2. Verify assets are tracked
|
|
3. Check update interval hasn't passed
|
|
4. Verify oracle price feed is configured
|
|
|
|
### Transaction Failures
|
|
|
|
**Error**: `Transaction reverted`
|
|
|
|
**Solution**:
|
|
1. Check keeper role permissions
|
|
2. Verify oracle price feed address
|
|
3. Check asset aggregators are set
|
|
4. Verify price feeds are not stale
|
|
|
|
---
|
|
|
|
## Security Considerations
|
|
|
|
1. **Private Key Security**: Store keeper private key securely
|
|
2. **Access Control**: Use multi-sig for admin functions
|
|
3. **Rate Limiting**: Set appropriate update intervals
|
|
4. **Monitoring**: Monitor keeper transactions and failures
|
|
5. **Backup**: Run multiple keeper instances for redundancy
|
|
|
|
---
|
|
|
|
## Best Practices
|
|
|
|
1. **Multiple Keepers**: Run multiple keeper instances for redundancy
|
|
2. **Monitoring**: Set up alerts for keeper failures
|
|
3. **Gas Management**: Monitor gas prices and adjust intervals
|
|
4. **Error Handling**: Implement retry logic and error reporting
|
|
5. **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.
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
- [Price Feed Setup](./PRICE_FEED_SETUP.md)
|
|
- [Reserve System Integration](./INTEGRATION_COMPLETE.md)
|
|
- [Chainlink Keepers](https://docs.chain.link/chainlink-automation)
|
|
- [Gelato Network](https://docs.gelato.network)
|
|
|