103 lines
3.2 KiB
TypeScript
103 lines
3.2 KiB
TypeScript
|
|
import hre from 'hardhat';
|
|||
|
|
import { liquidateUnderwaterBorrowers } from './liquidateUnderwaterBorrowers';
|
|||
|
|
import * as fs from 'fs';
|
|||
|
|
import * as path from 'path';
|
|||
|
|
const LOOP_DELAY = 5000; // 5 秒轮询间隔
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 清算机器人主循环
|
|||
|
|
*/
|
|||
|
|
async function main() {
|
|||
|
|
const network = hre.network.name;
|
|||
|
|
const chainId = hre.network.config.chainId;
|
|||
|
|
|
|||
|
|
console.log('\n==========================================');
|
|||
|
|
console.log('🤖 YT Lending Liquidation Bot Started');
|
|||
|
|
console.log('==========================================');
|
|||
|
|
console.log('Network:', network);
|
|||
|
|
console.log('Chain ID:', chainId);
|
|||
|
|
console.log('Loop Delay:', LOOP_DELAY, 'ms\n');
|
|||
|
|
|
|||
|
|
// 读取部署信息
|
|||
|
|
const deploymentsPath = path.join(__dirname, '../../deployments-lending.json');
|
|||
|
|
if (!fs.existsSync(deploymentsPath)) {
|
|||
|
|
throw new Error('deployments-lending.json not found');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const deployments = JSON.parse(fs.readFileSync(deploymentsPath, 'utf-8'));
|
|||
|
|
const deployment = deployments[chainId?.toString() || '421614'];
|
|||
|
|
|
|||
|
|
if (!deployment) {
|
|||
|
|
throw new Error(`No deployment found for chainId: ${chainId}`);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('📋 Contract Addresses:');
|
|||
|
|
console.log(' Lending Proxy:', deployment.lendingProxy);
|
|||
|
|
console.log(' Price Feed:', deployment.lendingPriceFeedProxy);
|
|||
|
|
console.log(' Base Token (USDC):', deployment.usdcAddress);
|
|||
|
|
console.log('');
|
|||
|
|
|
|||
|
|
// 获取签名者
|
|||
|
|
const [signer] = await hre.ethers.getSigners();
|
|||
|
|
console.log('👤 Liquidator Address:', await signer.getAddress());
|
|||
|
|
console.log('💰 Liquidator Balance:', hre.ethers.formatEther(await hre.ethers.provider.getBalance(signer)), 'ETH\n');
|
|||
|
|
|
|||
|
|
// 初始化合约
|
|||
|
|
const lendingContract = await hre.ethers.getContractAt(
|
|||
|
|
'Lending',
|
|||
|
|
deployment.lendingProxy,
|
|||
|
|
signer
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
const priceFeedContract = await hre.ethers.getContractAt(
|
|||
|
|
'LendingPriceFeed',
|
|||
|
|
deployment.lendingPriceFeedProxy,
|
|||
|
|
signer
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
console.log('✅ Contracts initialized\n');
|
|||
|
|
console.log('==========================================');
|
|||
|
|
console.log('🔄 Starting main loop...\n');
|
|||
|
|
|
|||
|
|
let lastBlockNumber: number | undefined;
|
|||
|
|
|
|||
|
|
// Compound V3 风格:while(true) 轮询
|
|||
|
|
while (true) {
|
|||
|
|
try {
|
|||
|
|
const currentBlockNumber = await hre.ethers.provider.getBlockNumber();
|
|||
|
|
|
|||
|
|
console.log(`[${new Date().toISOString()}] Block: ${currentBlockNumber}`);
|
|||
|
|
|
|||
|
|
// 检查是否有新区块(每个区块只处理一次)
|
|||
|
|
if (currentBlockNumber !== lastBlockNumber) {
|
|||
|
|
lastBlockNumber = currentBlockNumber;
|
|||
|
|
|
|||
|
|
// 执行清算逻辑
|
|||
|
|
await liquidateUnderwaterBorrowers(
|
|||
|
|
lendingContract,
|
|||
|
|
priceFeedContract,
|
|||
|
|
signer
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
console.log(''); // 空行分隔
|
|||
|
|
} else {
|
|||
|
|
console.log(`Block already checked; waiting ${LOOP_DELAY}ms...\n`);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 等待下一次轮询
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, LOOP_DELAY));
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('❌ Error in main loop:', error);
|
|||
|
|
console.log(`Retrying in ${LOOP_DELAY}ms...\n`);
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, LOOP_DELAY));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
main()
|
|||
|
|
.then(() => process.exit(0))
|
|||
|
|
.catch((error) => {
|
|||
|
|
console.error('❌ Fatal error:', error);
|
|||
|
|
process.exit(1);
|
|||
|
|
});
|