#!/usr/bin/env node /** * Gelato Network Setup Script * Registers PriceFeedKeeper with Gelato Network * * Usage: * node scripts/reserve/gelato-keeper-setup.js * * Environment Variables: * RPC_URL_138 - ChainID 138 RPC endpoint * PRIVATE_KEY - Deployer private key * GELATO_OPS - Gelato Ops contract address * PRICE_FEED_KEEPER_ADDRESS - PriceFeedKeeper contract address * EXECUTION_INTERVAL - Execution interval in seconds (default: 30) * FUNDING_AMOUNT - Native token amount to fund (default: 0.1 ETH) */ const { ethers } = require('ethers'); require('dotenv').config(); const CONFIG = { rpcUrl: process.env.RPC_URL_138 || 'http://localhost:8545', privateKey: process.env.PRIVATE_KEY, gelatoOps: process.env.GELATO_OPS || '0x527a819db1eb0e34426297b03bae11F2f8B3A19E', // Default Gelato Ops keeperAddress: process.env.PRICE_FEED_KEEPER_ADDRESS, executionInterval: parseInt(process.env.EXECUTION_INTERVAL || '30'), fundingAmount: ethers.parseEther(process.env.FUNDING_AMOUNT || '0.1'), }; // Gelato Ops ABI (simplified) const GELATO_OPS_ABI = [ "function createTask(address execAddress, bytes4 execSelector, address resolverAddress, bytes calldata resolverData) external returns (bytes32)", "function getTaskId(address execAddress, bytes4 execSelector, address resolverAddress, bytes calldata resolverData) external view returns (bytes32)", "function cancelTask(bytes32 taskId) external", "function depositFunds(address taskCreator, address token, uint256 amount) external payable", "function getTaskId(address execAddress, bytes4 execSelector, address resolverAddress, bytes calldata resolverData) external view returns (bytes32)", "event TaskCreated(bytes32 indexed taskId, address indexed execAddress, bytes4 execSelector, address indexed resolverAddress, bytes resolverData)", ]; // GelatoKeeperCompatible ABI const GELATO_KEEPER_ABI = [ "function executeTask() external", "function canExec() external view returns (bool canExec, bytes memory execData)", ]; async function main() { console.log('=== Gelato Network Setup ===\n'); // Validate configuration if (!CONFIG.privateKey) throw new Error('PRIVATE_KEY is required'); if (!CONFIG.keeperAddress) throw new Error('PRICE_FEED_KEEPER_ADDRESS is required'); const provider = new ethers.JsonRpcProvider(CONFIG.rpcUrl); const wallet = new ethers.Wallet(CONFIG.privateKey, provider); console.log('Network:', CONFIG.rpcUrl); console.log('Deployer:', wallet.address); console.log('Gelato Ops:', CONFIG.gelatoOps); console.log('Keeper Address:', CONFIG.keeperAddress); console.log('Execution Interval:', CONFIG.executionInterval, 'seconds'); console.log('Funding Amount:', ethers.formatEther(CONFIG.fundingAmount), 'ETH'); console.log(''); // Check balance const balance = await provider.getBalance(wallet.address); console.log('Balance:', ethers.formatEther(balance), 'ETH'); if (balance < CONFIG.fundingAmount) { throw new Error(`Insufficient balance. Need ${ethers.formatEther(CONFIG.fundingAmount)} ETH`); } // Deploy GelatoKeeperCompatible if not already deployed console.log('Checking GelatoKeeperCompatible contract...'); // For now, assume it needs to be deployed via Foundry script // In production, deploy it first and set GELATO_KEEPER_COMPATIBLE_ADDRESS const gelatoKeeperAddress = process.env.GELATO_KEEPER_COMPATIBLE_ADDRESS; if (!gelatoKeeperAddress) { console.log('⚠ GELATO_KEEPER_COMPATIBLE_ADDRESS not set'); console.log('Please deploy GelatoKeeperCompatible contract first using:'); console.log('forge script script/reserve/DeployGelatoKeeper.s.sol:DeployGelatoKeeper --rpc-url chain138 --broadcast'); process.exit(1); } console.log('GelatoKeeperCompatible:', gelatoKeeperAddress); // Create task console.log('\nCreating Gelato task...'); const gelatoOps = new ethers.Contract(CONFIG.gelatoOps, GELATO_OPS_ABI, wallet); const execAddress = gelatoKeeperAddress; const execSelector = '0x3c4b2e02'; // executeTask() selector const resolverAddress = gelatoKeeperAddress; const resolverData = ethers.AbiCoder.defaultAbiCoder().encode(['bytes4'], ['0x3c4b2e02']); // canExec() selector const createTaskTx = await gelatoOps.createTask( execAddress, execSelector, resolverAddress, resolverData, { value: CONFIG.fundingAmount } ); console.log('Transaction sent:', createTaskTx.hash); const receipt = await createTaskTx.wait(); // Parse TaskCreated event const event = receipt.logs.find(log => { try { const parsed = gelatoOps.interface.parseLog(log); return parsed.name === 'TaskCreated'; } catch { return false; } }); if (event) { const parsed = gelatoOps.interface.parseLog(event); const taskId = parsed.args.taskId; console.log('✓ Task created!'); console.log('Task ID:', taskId); console.log(''); console.log('=== Setup Complete ==='); console.log('Task ID:', taskId); console.log('Monitor at: https://app.gelato.network/task/' + taskId); } else { console.log('⚠ Could not parse TaskCreated event'); console.log('Check transaction receipt for task ID'); } } main().catch(error => { console.error('Error:', error.message); process.exit(1); });