# 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)

