feat: 添加多链支持和 Lending 借贷系统
- 新增 ARB Sepolia + BNB Testnet 多链支持 - 添加 LendingPanel 借贷系统组件 - 添加 LendingAdminPanel 管理面板 - 添加 USDCPanel USDC 操作组件 - 添加 HoldersPanel 持有人信息组件 - 添加 AutoTestPanel 自动化测试组件 - 重构 LP 组件为模块化结构 (LP/) - 添加多个调试和测试脚本 - 修复 USDC 精度动态配置 - 优化合约配置支持多链切换 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
237
frontend/scripts/check-lending-setup.js
Normal file
237
frontend/scripts/check-lending-setup.js
Normal file
@@ -0,0 +1,237 @@
|
||||
import { createPublicClient, http, parseAbi } from 'viem';
|
||||
import { arbitrumSepolia } from 'viem/chains';
|
||||
|
||||
const LENDING_PROXY = '0xCb4E7B1069F6C26A1c27523ce4c8dfD884552d1D';
|
||||
const CONFIGURATOR_ADDRESS = '0x488409CE9A3Fcd8EbD373dCb7e025cF8AB96fcdc';
|
||||
|
||||
const LENDING_ABI = parseAbi([
|
||||
'function owner() view returns (address)',
|
||||
'function configurator() view returns (address)',
|
||||
'function getConfigurator() view returns (address)',
|
||||
'function setConfigurator(address) external',
|
||||
'function paused() view returns (bool)',
|
||||
'function getTotalSupply() view returns (uint256)',
|
||||
'function getTotalBorrow() view returns (uint256)',
|
||||
'function getUtilization() view returns (uint256)',
|
||||
'function getBorrowRate() view returns (uint256)',
|
||||
'function getSupplyRate(uint256) view returns (uint256)',
|
||||
'function initialize(address,address,address) external'
|
||||
]);
|
||||
|
||||
const CONFIGURATOR_ABI = [
|
||||
{
|
||||
"inputs": [
|
||||
{ "internalType": "address", "name": "lendingProxy", "type": "address" }
|
||||
],
|
||||
"name": "getConfiguration",
|
||||
"outputs": [
|
||||
{
|
||||
"components": [
|
||||
{ "internalType": "address", "name": "baseToken", "type": "address" },
|
||||
{ "internalType": "address", "name": "lendingPriceSource", "type": "address" },
|
||||
{ "internalType": "uint64", "name": "supplyKink", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "supplyPerYearInterestRateSlopeLow", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "supplyPerYearInterestRateSlopeHigh", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "supplyPerYearInterestRateBase", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "borrowKink", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "borrowPerYearInterestRateSlopeLow", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "borrowPerYearInterestRateSlopeHigh", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "borrowPerYearInterestRateBase", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "storeFrontPriceFactor", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "trackingIndexScale", "type": "uint64" },
|
||||
{ "internalType": "uint104", "name": "baseBorrowMin", "type": "uint104" },
|
||||
{ "internalType": "uint104", "name": "targetReserves", "type": "uint104" },
|
||||
{
|
||||
"components": [
|
||||
{ "internalType": "address", "name": "asset", "type": "address" },
|
||||
{ "internalType": "uint8", "name": "decimals", "type": "uint8" },
|
||||
{ "internalType": "uint64", "name": "borrowCollateralFactor", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "liquidateCollateralFactor", "type": "uint64" },
|
||||
{ "internalType": "uint64", "name": "liquidationFactor", "type": "uint64" },
|
||||
{ "internalType": "uint128", "name": "supplyCap", "type": "uint128" }
|
||||
],
|
||||
"internalType": "struct LendingConfiguration.AssetConfig[]",
|
||||
"name": "assetConfigs",
|
||||
"type": "tuple[]"
|
||||
}
|
||||
],
|
||||
"internalType": "struct LendingConfiguration.Configuration",
|
||||
"name": "",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
];
|
||||
|
||||
const publicClient = createPublicClient({
|
||||
chain: arbitrumSepolia,
|
||||
transport: http('https://sepolia-rollup.arbitrum.io/rpc')
|
||||
});
|
||||
|
||||
async function checkLending() {
|
||||
console.log('🔍 检查 Lending 合约设置\n');
|
||||
|
||||
try {
|
||||
// 检查 owner
|
||||
const owner = await publicClient.readContract({
|
||||
address: LENDING_PROXY,
|
||||
abi: LENDING_ABI,
|
||||
functionName: 'owner'
|
||||
});
|
||||
console.log('1️⃣ Lending Owner:', owner);
|
||||
} catch (error) {
|
||||
console.log('1️⃣ ❌ 读取 owner 失败');
|
||||
}
|
||||
|
||||
// 尝试读取configurator地址
|
||||
const getters = ['configurator', 'getConfigurator'];
|
||||
let foundConfigurator = null;
|
||||
|
||||
for (const getter of getters) {
|
||||
try {
|
||||
console.log(`\n2️⃣ 尝试调用 ${getter}()...`);
|
||||
const configuratorAddr = await publicClient.readContract({
|
||||
address: LENDING_PROXY,
|
||||
abi: LENDING_ABI,
|
||||
functionName: getter
|
||||
});
|
||||
console.log(` ✅ ${getter}() = ${configuratorAddr}`);
|
||||
console.log(` 期望地址: ${CONFIGURATOR_ADDRESS}`);
|
||||
console.log(` 匹配: ${configuratorAddr.toLowerCase() === CONFIGURATOR_ADDRESS.toLowerCase() ? '✅' : '❌'}`);
|
||||
|
||||
foundConfigurator = configuratorAddr;
|
||||
|
||||
if (configuratorAddr.toLowerCase() !== CONFIGURATOR_ADDRESS.toLowerCase()) {
|
||||
console.log('\n⚠️ 警告: Configurator 地址不匹配!');
|
||||
console.log('💡 Lending 合约指向了不同的 Configurator');
|
||||
console.log(` Lending 中的: ${configuratorAddr}`);
|
||||
console.log(` 前端使用的: ${CONFIGURATOR_ADDRESS}`);
|
||||
}
|
||||
|
||||
break;
|
||||
} catch (error) {
|
||||
console.log(` ❌ ${getter}() 不存在或调用失败`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundConfigurator) {
|
||||
console.log('\n⚠️ 未找到 Configurator 地址!');
|
||||
console.log('💡 Lending 合约可能需要先通过 setConfigurator() 设置 Configurator 地址\n');
|
||||
}
|
||||
|
||||
// 检查是否暂停
|
||||
try {
|
||||
const isPaused = await publicClient.readContract({
|
||||
address: LENDING_PROXY,
|
||||
abi: LENDING_ABI,
|
||||
functionName: 'paused'
|
||||
});
|
||||
console.log('\n3️⃣ 系统暂停状态:', isPaused ? '已暂停' : '运行中');
|
||||
} catch (error) {
|
||||
console.log('\n3️⃣ ❌ 读取暂停状态失败');
|
||||
}
|
||||
|
||||
// 检查流动性
|
||||
try {
|
||||
const liquidity = await publicClient.readContract({
|
||||
address: LENDING_PROXY,
|
||||
abi: LENDING_ABI,
|
||||
functionName: 'getTotalSupply'
|
||||
});
|
||||
console.log('4️⃣ 总供应量:', (Number(liquidity) / 1e6).toFixed(2), 'USDC');
|
||||
} catch (error) {
|
||||
console.log('4️⃣ ❌ 读取总供应量失败');
|
||||
}
|
||||
|
||||
// 检查系统数据查询函数
|
||||
console.log('\n📊 系统数据查询:');
|
||||
|
||||
try {
|
||||
const totalBorrow = await publicClient.readContract({
|
||||
address: LENDING_PROXY,
|
||||
abi: LENDING_ABI,
|
||||
functionName: 'getTotalBorrow'
|
||||
});
|
||||
console.log(' 总借款:', (Number(totalBorrow) / 1e6).toFixed(2), 'USDC');
|
||||
} catch (error) {
|
||||
console.log(' ❌ getTotalBorrow() 调用失败');
|
||||
}
|
||||
|
||||
try {
|
||||
const utilization = await publicClient.readContract({
|
||||
address: LENDING_PROXY,
|
||||
abi: LENDING_ABI,
|
||||
functionName: 'getUtilization'
|
||||
});
|
||||
console.log(' 资金利用率:', (Number(utilization) / 1e18 * 100).toFixed(2), '%');
|
||||
} catch (error) {
|
||||
console.log(' ❌ getUtilization() 调用失败');
|
||||
}
|
||||
|
||||
try {
|
||||
const borrowRate = await publicClient.readContract({
|
||||
address: LENDING_PROXY,
|
||||
abi: LENDING_ABI,
|
||||
functionName: 'getBorrowRate'
|
||||
});
|
||||
const borrowAPR = (Number(borrowRate) / 1e18 * 100).toFixed(2);
|
||||
console.log(' 借款年利率:', borrowAPR, '%');
|
||||
} catch (error) {
|
||||
console.log(' ❌ getBorrowRate() 调用失败');
|
||||
}
|
||||
|
||||
try {
|
||||
const utilization = await publicClient.readContract({
|
||||
address: LENDING_PROXY,
|
||||
abi: LENDING_ABI,
|
||||
functionName: 'getUtilization'
|
||||
});
|
||||
const supplyRate = await publicClient.readContract({
|
||||
address: LENDING_PROXY,
|
||||
abi: LENDING_ABI,
|
||||
functionName: 'getSupplyRate',
|
||||
args: [utilization]
|
||||
});
|
||||
const supplyAPR = (Number(supplyRate) / 1e18 * 100).toFixed(2);
|
||||
console.log(' 存款年利率:', supplyAPR, '%');
|
||||
} catch (error) {
|
||||
console.log(' ❌ getSupplyRate() 调用失败');
|
||||
}
|
||||
|
||||
// 检查 Configurator 配置
|
||||
console.log('\n⚙️ Configurator 配置:');
|
||||
|
||||
try {
|
||||
const config = await publicClient.readContract({
|
||||
address: CONFIGURATOR_ADDRESS,
|
||||
abi: CONFIGURATOR_ABI,
|
||||
functionName: 'getConfiguration',
|
||||
args: [LENDING_PROXY]
|
||||
});
|
||||
|
||||
console.log(' 基础资产:', config.baseToken);
|
||||
console.log(' 价格源:', config.lendingPriceSource);
|
||||
console.log(' 抵押品资产数量:', config.assetConfigs.length);
|
||||
|
||||
config.assetConfigs.forEach((asset, index) => {
|
||||
console.log(`\n 抵押品 ${index + 1}:`);
|
||||
console.log(` 地址: ${asset.asset}`);
|
||||
console.log(` 精度: ${asset.decimals}`);
|
||||
console.log(` 借款抵押率: ${(Number(asset.borrowCollateralFactor) / 1e18 * 100).toFixed(2)}%`);
|
||||
console.log(` 清算抵押率: ${(Number(asset.liquidateCollateralFactor) / 1e18 * 100).toFixed(2)}%`);
|
||||
console.log(` 清算奖励: ${(Number(asset.liquidationFactor) / 1e18 * 100).toFixed(2)}%`);
|
||||
console.log(` 供应上限: ${(Number(asset.supplyCap) / (10 ** asset.decimals)).toFixed(2)}`);
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(' ❌ 读取 Configurator 配置失败:', error.message);
|
||||
}
|
||||
|
||||
console.log('\n💡 总结:');
|
||||
console.log(' - 检查 Lending 合约是否正确设置了 Configurator 地址');
|
||||
console.log(' - 检查 Configurator 合约是否正确设置了 Lending 地址');
|
||||
console.log(' - 这两个合约需要相互关联才能正常工作');
|
||||
}
|
||||
|
||||
checkLending();
|
||||
Reference in New Issue
Block a user