// 合约验证和部署区块查询工具 // Contract verification and deployment block query tool const { ethers } = require("ethers"); // 配置 const RPC_URL = "https://sepolia-rollup.arbitrum.io/rpc"; // 你数据库中的合约地址 const CONTRACTS = { "YT-A": "0x7f9eEA491eE53045594ee4669327f0355aCd0e58", "YT-B": "0x20B94C5E5b7361552E0548161a58696aA6FeDBd4", "YT-C": "0x0EF308D70cf35460E26a3Eb42F3442Ff28cbE07C", "ytLP": "0x102e3F25Ef0ad9b0695C8F2daF8A1262437eEfc3", "Lending": "0xCb4E7B1069F6C26A1c27523ce4c8dfD884552d1D" }; // ERC20 ABI (只包含必要的函数) const ERC20_ABI = [ "function name() view returns (string)", "function symbol() view returns (string)", "function totalSupply() view returns (uint256)", "function balanceOf(address) view returns (uint256)" ]; async function verifyContract(provider, name, address) { console.log(`\n━━━ ${name} ━━━`); console.log(`地址: ${address}`); try { // 检查合约代码 const code = await provider.getCode(address); if (code === "0x") { console.log("❌ 错误: 该地址没有合约代码(可能是错误的地址)"); return null; } console.log("✅ 合约代码存在"); // 尝试读取 ERC20 信息(仅适用于 YT 和 ytLP) if (name.startsWith("YT-") || name === "ytLP") { try { const contract = new ethers.Contract(address, ERC20_ABI, provider); const [tokenName, symbol, totalSupply] = await Promise.all([ contract.name(), contract.symbol(), contract.totalSupply() ]); console.log(` 名称: ${tokenName}`); console.log(` 符号: ${symbol}`); console.log(` 总供应量: ${ethers.formatEther(totalSupply)} (${totalSupply.toString()})`); } catch (error) { console.log("⚠️ 无法读取 ERC20 信息(可能不是标准 ERC20)"); } } // 尝试获取创建交易(需要手动在 Arbiscan 查询) console.log(`\n🔍 在 Arbiscan 上查询部署信息:`); console.log(` https://sepolia.arbiscan.io/address/${address}`); return { address, hasCode: true }; } catch (error) { console.log(`❌ 错误: ${error.message}`); return null; } } async function suggestDeploymentBlock(provider) { console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); console.log("📍 部署区块建议"); console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); const currentBlock = await provider.getBlockNumber(); console.log(`当前最新区块: ${currentBlock}`); console.log(`\n如果你不知道确切的部署区块号,可以使用以下策略:\n`); console.log(`方案 1 (推荐): 在 Arbiscan 上查询准确的部署区块`); console.log(` - 访问上面的链接,查看 "Contract Creation" 交易`); console.log(` - 使用准确的部署区块可以确保不遗漏任何数据\n`); console.log(`方案 2 (临时): 使用较近的区块号进行测试`); console.log(` - 从较新的区块开始扫描(例如: ${currentBlock - 100000})`); console.log(` - 可以快速测试功能,但可能遗漏早期持有者数据\n`); console.log(`方案 3 (保守): 使用较早的区块号`); console.log(` - 从一个足够早的区块开始(例如: 227000000)`); console.log(` - 可能扫描大量无关区块,但能确保完整性`); } async function main() { console.log("=== 合约验证工具 ===\n"); console.log(`RPC: ${RPC_URL}\n`); const provider = new ethers.JsonRpcProvider(RPC_URL); // 验证连接 try { const network = await provider.getNetwork(); console.log(`✅ 已连接到网络: ${network.name} (Chain ID: ${network.chainId})\n`); } catch (error) { console.log(`❌ 无法连接到 RPC: ${error.message}`); process.exit(1); } // 验证每个合约 const results = {}; for (const [name, address] of Object.entries(CONTRACTS)) { const result = await verifyContract(provider, name, address); results[name] = result; } // 显示摘要 console.log("\n\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); console.log("📊 验证摘要"); console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); const validContracts = Object.entries(results).filter(([_, r]) => r?.hasCode); const invalidContracts = Object.entries(results).filter(([_, r]) => !r?.hasCode); console.log(`✅ 有效合约: ${validContracts.length}/${Object.keys(CONTRACTS).length}`); validContracts.forEach(([name]) => console.log(` • ${name}`)); if (invalidContracts.length > 0) { console.log(`\n❌ 无效合约: ${invalidContracts.length}`); invalidContracts.forEach(([name]) => console.log(` • ${name}`)); } // 部署区块建议 await suggestDeploymentBlock(provider); console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); console.log("📝 下一步"); console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); console.log("1. 在 Arbiscan 上查询每个合约的部署区块号"); console.log("2. 更新 .env 文件中的部署区块号:"); console.log(" YT_VAULTS_DEPLOY_BLOCK=<实际区块号>"); console.log(" YTLP_DEPLOY_BLOCK=<实际区块号>"); console.log(" LENDING_DEPLOY_BLOCK=<实际区块号>"); console.log("3. 运行 Scanner:"); console.log(" ./run-scanner.sh"); console.log(""); } main().catch(console.error);