add absorb script and upgrade script

This commit is contained in:
2026-01-06 15:57:36 +08:00
parent b1b3b07b21
commit eecae142a4
33 changed files with 3614 additions and 3070 deletions

420
scripts/handler.ts Normal file
View File

@@ -0,0 +1,420 @@
import { ethers, Contract, JsonRpcProvider } from "ethers";
import type { EventLog, Log } from "ethers";
// ==================== 类型定义 ====================
interface VaultConfig {
name: string;
address: string;
}
interface YTHolderData {
address: string;
balance: string;
}
interface LPHolderData {
address: string;
balance: string;
share: string;
}
interface LendingSupplierData {
address: string;
supply: string;
borrow: string;
net: string;
}
// ==================== 配置 ====================
const RPC_URL: string = "https://api.zan.top/node/v1/arb/sepolia/baf84c429d284bb5b676cb8c9ca21c07";
// 合约配置(包含部署区块号,可以大幅减少查询时间)
const YT_VAULTS: VaultConfig[] = [
{ name: "YT-A", address: "0x97204190B35D9895a7a47aa7BaC61ac08De3cF05" },
{ name: "YT-B", address: "0x181ef4011c35C4a2Fda08eBC5Cf509Ef58E553fF" },
{ name: "YT-C", address: "0xE9A5b9f3a2Eda4358f81d4E2eF4f3280A664e5B0" },
];
const YTLP_ADDRESS: string = "0x102e3F25Ef0ad9b0695C8F2daF8A1262437eEfc3";
const LENDING_ADDRESS: string = "0xCb4E7B1069F6C26A1c27523ce4c8dfD884552d1D";
// ==================== 部署区块配置 ====================
//
// 配置说明:
// 1. 查询准确的部署区块号,直接填写
interface DeploymentConfig {
ytVaults: number; // YT 代币部署区块
ytlp: number; // ytLP 部署区块
lending: number; // Lending 部署区块
}
const DEPLOYMENT_BLOCKS: DeploymentConfig = {
ytVaults: 227339300, // YT-A/B/C 部署区块号
ytlp: 227230270, // ytLP 部署区块号
lending: 227746053, // Lending 部署区块号
};
// ==================== ABIs ====================
const ERC20_ABI = [
"event Transfer(address indexed from, address indexed to, uint256 value)",
"function balanceOf(address account) view returns (uint256)",
"function totalSupply() view returns (uint256)",
] as const;
const LENDING_ABI = [
"event Supply(address indexed from, address indexed dst, uint256 amount)",
"function supplyBalanceOf(address account) view returns (uint256)",
"function borrowBalanceOf(address account) view returns (uint256)",
] as const;
// ==================== 工具函数 ====================
/**
* 分块查询事件,避免超出 RPC 限制
* @param contract 合约实例
* @param filter 事件过滤器
* @param fromBlock 起始区块
* @param toBlock 结束区块
* @param batchSize 每批次的区块数量(默认 9999低于 10000 限制)
*/
async function queryEventsInBatches(
contract: Contract,
filter: any,
fromBlock: number,
toBlock: number,
batchSize: number = 9999
): Promise<(EventLog | Log)[]> {
const allEvents: (EventLog | Log)[] = [];
let currentBlock = fromBlock;
console.log(` 查询区块范围: ${fromBlock} -> ${toBlock} (总共 ${toBlock - fromBlock + 1} 个区块)`);
while (currentBlock <= toBlock) {
const endBlock = Math.min(currentBlock + batchSize, toBlock);
console.log(` 正在查询区块 ${currentBlock} - ${endBlock}...`);
try {
const events = await contract.queryFilter(filter, currentBlock, endBlock);
allEvents.push(...events);
console.log(` ✓ 获取到 ${events.length} 个事件`);
} catch (error) {
console.error(` ✗ 查询区块 ${currentBlock} - ${endBlock} 失败:`, error);
throw error;
}
currentBlock = endBlock + 1;
// 添加小延迟,避免触发 RPC 速率限制
if (currentBlock <= toBlock) {
await new Promise(resolve => setTimeout(resolve, 100));
}
}
console.log(` 总计获取 ${allEvents.length} 个事件\n`);
return allEvents;
}
/**
* 获取当前最新区块号
*/
async function getLatestBlockNumber(provider: JsonRpcProvider, silent: boolean = false): Promise<number> {
const blockNumber = await provider.getBlockNumber();
if (!silent) {
console.log(`当前最新区块: ${blockNumber}\n`);
}
return blockNumber;
}
// ==================== 主函数 ====================
// 记录上次扫描的区块号
let lastScannedBlock: number = 0;
// 标记是否正在扫描,防止并发
let isScanning: boolean = false;
// 全局地址集合,用于追踪所有曾经出现过的地址
const allYTAddresses: Map<string, Set<string>> = new Map(); // vault address -> holder addresses
const allLPAddresses: Set<string> = new Set();
const allLendingAddresses: Set<string> = new Set();
async function getAllHolders(
provider: JsonRpcProvider,
fromBlock?: number,
toBlock?: number,
isInitialScan: boolean = false
): Promise<void> {
// 获取最新区块号
const latestBlock = toBlock || await getLatestBlockNumber(provider, fromBlock !== undefined);
// 计算起始区块
let ytVaultsStartBlock: number;
let ytlpStartBlock: number;
let lendingStartBlock: number;
if (fromBlock !== undefined) {
// 增量扫描模式
ytVaultsStartBlock = ytlpStartBlock = lendingStartBlock = fromBlock;
console.log(`\n🔄 增量扫描: 区块 ${fromBlock} -> ${latestBlock}\n`);
} else {
// 首次扫描:使用部署区块号
ytVaultsStartBlock = DEPLOYMENT_BLOCKS.ytVaults;
ytlpStartBlock = DEPLOYMENT_BLOCKS.ytlp;
lendingStartBlock = DEPLOYMENT_BLOCKS.lending;
if (isInitialScan) {
console.log(`✨ 首次扫描,从部署区块开始:`);
console.log(` YT Vaults 起始区块: ${ytVaultsStartBlock}`);
console.log(` ytLP 起始区块: ${ytlpStartBlock}`);
console.log(` Lending 起始区块: ${lendingStartBlock}\n`);
}
}
// 1. 获取 YT 代币持有者
console.log("1. YT 代币持有者:");
for (const vault of YT_VAULTS) {
console.log(` 正在查询 ${vault.name} (${vault.address})...`);
const contract: Contract = new ethers.Contract(vault.address, ERC20_ABI, provider);
const filter = contract.filters.Transfer();
const events: (EventLog | Log)[] = await queryEventsInBatches(
contract,
filter,
ytVaultsStartBlock,
latestBlock
);
// 初始化该 vault 的地址集合(如果不存在)
if (!allYTAddresses.has(vault.address)) {
allYTAddresses.set(vault.address, new Set<string>());
}
const vaultAddresses = allYTAddresses.get(vault.address)!;
// 记录新增地址数量
const previousCount = vaultAddresses.size;
// 添加新发现的地址到全局集合
for (const event of events) {
if ("args" in event && event.args.to !== ethers.ZeroAddress) {
vaultAddresses.add(event.args.to as string);
}
}
const newAddressCount = vaultAddresses.size - previousCount;
if (newAddressCount > 0) {
console.log(` 发现 ${newAddressCount} 个新地址,总共追踪 ${vaultAddresses.size} 个地址`);
}
// 查询所有曾经出现过的地址的当前余额
const holders: YTHolderData[] = [];
for (const address of vaultAddresses) {
const balance: bigint = await contract.balanceOf(address);
if (balance > 0n) {
holders.push({
address,
balance: ethers.formatEther(balance),
});
}
}
// 按余额降序排序
holders.sort((a, b) => parseFloat(b.balance) - parseFloat(a.balance));
console.log(` ${vault.name}: ${holders.length} 持有者`);
if (holders.length > 0) {
console.log(` 前 10 名持有者:`);
const top10 = holders.slice(0, 10);
top10.forEach((h: YTHolderData, index: number) =>
console.log(` ${index + 1}. ${h.address}: ${h.balance}`)
);
} else {
console.log(` 暂无持有者`);
}
}
// 2. 获取 LP 代币持有者
console.log("\n2. LP 代币持有者 (ytLP):");
console.log(` 正在查询 ytLP (${YTLP_ADDRESS})...`);
const lpContract: Contract = new ethers.Contract(YTLP_ADDRESS, ERC20_ABI, provider);
const lpFilter = lpContract.filters.Transfer();
const lpEvents: (EventLog | Log)[] = await queryEventsInBatches(
lpContract,
lpFilter,
ytlpStartBlock,
latestBlock
);
// 记录新增地址数量
const previousLPCount = allLPAddresses.size;
// 添加新发现的地址到全局集合
for (const event of lpEvents) {
if ("args" in event && event.args.to !== ethers.ZeroAddress) {
allLPAddresses.add(event.args.to as string);
}
}
const newLPAddressCount = allLPAddresses.size - previousLPCount;
if (newLPAddressCount > 0) {
console.log(` 发现 ${newLPAddressCount} 个新地址,总共追踪 ${allLPAddresses.size} 个地址`);
}
// 查询所有曾经出现过的地址的当前余额
const lpHolders: LPHolderData[] = [];
const totalSupply: bigint = await lpContract.totalSupply();
for (const address of allLPAddresses) {
const balance: bigint = await lpContract.balanceOf(address);
if (balance > 0n) {
const share: string = (Number(balance) / Number(totalSupply) * 100).toFixed(4);
lpHolders.push({
address,
balance: ethers.formatEther(balance),
share: share + "%",
});
}
}
// 按余额降序排序
lpHolders.sort((a, b) => parseFloat(b.balance) - parseFloat(a.balance));
console.log(` 总计: ${lpHolders.length} 持有者`);
if (lpHolders.length > 0) {
console.log(` 前 10 名持有者:`);
const top10 = lpHolders.slice(0, 10);
top10.forEach((h: LPHolderData, index: number) =>
console.log(` ${index + 1}. ${h.address}: ${h.balance} (${h.share})`)
);
} else {
console.log(` 暂无持有者`);
}
// 3. 获取 Lending 提供者
console.log("\n3. Lending 提供者:");
console.log(` 正在查询 Lending (${LENDING_ADDRESS})...`);
const lendingContract: Contract = new ethers.Contract(LENDING_ADDRESS, LENDING_ABI, provider);
const supplyFilter = lendingContract.filters.Supply();
const supplyEvents: (EventLog | Log)[] = await queryEventsInBatches(
lendingContract,
supplyFilter,
lendingStartBlock,
latestBlock
);
// 记录新增地址数量
const previousLendingCount = allLendingAddresses.size;
// 添加新发现的地址到全局集合
for (const event of supplyEvents) {
if ("args" in event) {
allLendingAddresses.add(event.args.dst as string);
}
}
const newLendingAddressCount = allLendingAddresses.size - previousLendingCount;
if (newLendingAddressCount > 0) {
console.log(` 发现 ${newLendingAddressCount} 个新地址,总共追踪 ${allLendingAddresses.size} 个地址`);
}
// 查询所有曾经出现过的地址的当前余额
const suppliers: LendingSupplierData[] = [];
for (const address of allLendingAddresses) {
const supplyBalance: bigint = await lendingContract.supplyBalanceOf(address);
const borrowBalance: bigint = await lendingContract.borrowBalanceOf(address);
if (supplyBalance > 0n || borrowBalance > 0n) {
suppliers.push({
address,
supply: ethers.formatUnits(supplyBalance, 6),
borrow: ethers.formatUnits(borrowBalance, 6),
net: ethers.formatUnits(supplyBalance - borrowBalance, 6),
});
}
}
// 按净供应额降序排序
suppliers.sort((a, b) => parseFloat(b.net) - parseFloat(a.net));
console.log(` 总计: ${suppliers.length} 参与者`);
if (suppliers.length > 0) {
console.log(` 前 10 名参与者:`);
const top10 = suppliers.slice(0, 10);
top10.forEach((s: LendingSupplierData, index: number) =>
console.log(
` ${index + 1}. ${s.address}: 供应=${s.supply} USDC, 借款=${s.borrow} USDC, 净额=${s.net} USDC`
)
);
} else {
console.log(` 暂无参与者`);
}
// 更新上次扫描的区块号
lastScannedBlock = latestBlock;
console.log(`\n📌 已记录扫描区块: ${lastScannedBlock}`);
}
// ==================== 执行 ====================
const POLL_INTERVAL_MS = 10000; // 10秒轮询间隔
async function main(): Promise<void> {
const provider: JsonRpcProvider = new ethers.JsonRpcProvider(RPC_URL);
console.log("=== ytLp 协议 Holder 数据监控 ===\n");
console.log(`轮询间隔: ${POLL_INTERVAL_MS / 1000}\n`);
try {
// 首次扫描:从部署区块到当前区块
console.log("📊 开始首次扫描...\n");
const startTime = Date.now();
await getAllHolders(provider, undefined, undefined, true);
const endTime = Date.now();
const duration = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n✓ 首次扫描完成,耗时 ${duration}`);
// 启动轮询
console.log(`\n⏰ 开始轮询,每 ${POLL_INTERVAL_MS / 1000} 秒检查一次新区块...\n`);
setInterval(async () => {
try {
// 如果正在扫描,跳过本次轮询
if (isScanning) {
console.log(`⏰ [${new Date().toLocaleString()}] 跳过本次轮询(上次扫描仍在进行中)`);
return;
}
const currentBlock = await provider.getBlockNumber();
// 如果有新区块,进行增量扫描
if (currentBlock > lastScannedBlock) {
isScanning = true; // 标记开始扫描
console.log(`\n${"=".repeat(60)}`);
console.log(`⏰ [${new Date().toLocaleString()}] 发现新区块`);
console.log(`${"=".repeat(60)}`);
const scanStart = Date.now();
await getAllHolders(provider, lastScannedBlock + 1, currentBlock, false);
const scanDuration = ((Date.now() - scanStart) / 1000).toFixed(2);
console.log(`\n✓ 增量扫描完成,耗时 ${scanDuration}`);
isScanning = false; // 标记扫描完成
} else {
console.log(`⏰ [${new Date().toLocaleString()}] 暂无新区块 (当前: ${currentBlock})`);
}
} catch (error) {
console.error(`\n✗ 轮询过程中发生错误:`, error);
isScanning = false; // 发生错误时也要重置标记
}
}, POLL_INTERVAL_MS);
} catch (error) {
console.error("\n✗ 发生错误:", error);
process.exit(1);
}
}
main();

View File

@@ -0,0 +1,102 @@
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);
});

View File

@@ -0,0 +1,170 @@
import hre from 'hardhat';
import { Signer } from 'ethers';
const LOOKBACK_BLOCKS = 50000; // 查询最近 50000 个区块
const LIQUIDATION_THRESHOLD = 10e6; // $10 (USDC 6 decimals)
/**
* 获取最近活跃的地址(通过多个事件)
*/
export async function getUniqueAddresses(
lendingContract: any
): Promise<string[]> {
const currentBlock = await hre.ethers.provider.getBlockNumber();
const fromBlock = Math.max(currentBlock - LOOKBACK_BLOCKS, 0);
console.log(`📊 Querying events from block ${fromBlock} to ${currentBlock}...`);
const uniqueAddresses = new Set<string>();
// 1. Withdraw 事件(借款/提现)
try {
const withdrawFilter = lendingContract.filters.Withdraw();
const withdrawEvents = await lendingContract.queryFilter(
withdrawFilter,
fromBlock,
currentBlock
);
for (const event of withdrawEvents) {
if (event.args?.src) uniqueAddresses.add(event.args.src);
if (event.args?.dst) uniqueAddresses.add(event.args.dst);
}
console.log(` - Withdraw events: ${withdrawEvents.length}`);
} catch (error) {
console.error(' ⚠️ Failed to query Withdraw events:', error);
}
// 2. Supply 事件(存款)
try {
const supplyFilter = lendingContract.filters.Supply();
const supplyEvents = await lendingContract.queryFilter(
supplyFilter,
fromBlock,
currentBlock
);
for (const event of supplyEvents) {
if (event.args?.from) uniqueAddresses.add(event.args.from);
if (event.args?.dst) uniqueAddresses.add(event.args.dst);
}
console.log(` - Supply events: ${supplyEvents.length}`);
} catch (error) {
console.error(' ⚠️ Failed to query Supply events:', error);
}
// 3. SupplyCollateral 事件(抵押品存入)
try {
const supplyCollateralFilter = lendingContract.filters.SupplyCollateral();
const supplyCollateralEvents = await lendingContract.queryFilter(
supplyCollateralFilter,
fromBlock,
currentBlock
);
for (const event of supplyCollateralEvents) {
if (event.args?.from) uniqueAddresses.add(event.args.from);
if (event.args?.dst) uniqueAddresses.add(event.args.dst);
}
console.log(` - SupplyCollateral events: ${supplyCollateralEvents.length}`);
} catch (error) {
console.error(' ⚠️ Failed to query SupplyCollateral events:', error);
}
// 4. WithdrawCollateral 事件(抵押品提取)
try {
const withdrawCollateralFilter = lendingContract.filters.WithdrawCollateral();
const withdrawCollateralEvents = await lendingContract.queryFilter(
withdrawCollateralFilter,
fromBlock,
currentBlock
);
for (const event of withdrawCollateralEvents) {
if (event.args?.src) uniqueAddresses.add(event.args.src);
if (event.args?.to) uniqueAddresses.add(event.args.to);
}
console.log(` - WithdrawCollateral events: ${withdrawCollateralEvents.length}`);
} catch (error) {
console.error(' ⚠️ Failed to query WithdrawCollateral events:', error);
}
console.log(`✅ Found ${uniqueAddresses.size} unique addresses from all events`);
return Array.from(uniqueAddresses);
}
/**
* 检查并清算可清算账户
* 参考comet/scripts/liquidation_bot/liquidateUnderwaterBorrowers.ts
*/
export async function liquidateUnderwaterBorrowers(
lendingContract: any,
priceFeedContract: any,
signer: Signer
): Promise<boolean> {
// 步骤 1: 获取最近活跃的地址
const uniqueAddresses = await getUniqueAddresses(lendingContract);
if (uniqueAddresses.length === 0) {
console.log(' No active addresses found');
return false;
}
console.log(`🔍 Checking ${uniqueAddresses.length} addresses for liquidation...`);
const liquidatableAccounts: string[] = [];
// 步骤 2: 检查每个地址是否可清算
for (const address of uniqueAddresses) {
try {
// 直接调用合约的 isLiquidatable(),无需自己计算健康因子
const isLiquidatable = await lendingContract.isLiquidatable(address);
if (isLiquidatable) {
// 应用清算阈值过滤防止清算小额账户gas 成本过高)
const borrowBalance = await lendingContract.borrowBalanceOf(address);
const baseToken = await lendingContract.baseToken();
const basePrice = await priceFeedContract.getPrice(baseToken);
// debtValue 计算borrowBalance (6 decimals) * basePrice (30 decimals) / 1e6
const debtValue = (BigInt(borrowBalance) * BigInt(basePrice)) / BigInt(10) ** BigInt(6);
const debtValueInBaseUnit = Number(debtValue / (BigInt(10) ** BigInt(30))); // 转换为 USDC 单位
// LIQUIDATION_THRESHOLD 是 6 decimals需要转换为 30 decimals 来和 debtValue 比较
// 10e6 * 1e24 = 10e30 (代表 $10)
if (debtValue >= BigInt(LIQUIDATION_THRESHOLD) * BigInt(10) ** BigInt(24)) {
console.log(`💰 Liquidatable: ${address}, Debt: $${debtValueInBaseUnit.toFixed(2)}`);
liquidatableAccounts.push(address);
} else {
console.log(`⏭️ Skip (below threshold): ${address}, Debt: $${debtValueInBaseUnit.toFixed(2)}`);
}
}
} catch (error) {
console.error(`Error checking ${address}:`, error);
}
}
// 步骤 3: 批量清算
if (liquidatableAccounts.length > 0) {
console.log(`\n🎯 Found ${liquidatableAccounts.length} liquidatable accounts`);
console.log('📤 Sending liquidation transaction...');
try {
const liquidatorAddress = await signer.getAddress();
const tx = await lendingContract.connect(signer).absorbMultiple(
liquidatorAddress,
liquidatableAccounts
);
console.log(`🔗 Transaction sent: ${tx.hash}`);
const receipt = await tx.wait();
console.log(`✅ Liquidation successful!`);
console.log(` Gas used: ${receipt.gasUsed.toString()}`);
console.log(` Block: ${receipt.blockNumber}`);
return true;
} catch (error) {
console.error('❌ Liquidation transaction failed:', error);
return false;
}
} else {
console.log('✅ No liquidatable accounts found');
return false;
}
}

View File

@@ -0,0 +1,109 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 Configurator 合约
* 使用 upgrades.upgradeProxy() 进行 UUPS 升级
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("🔄 升级 Configurator 合约");
console.log("==========================================");
console.log("升级账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-lending.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件,请先运行部署脚本");
}
const network = await ethers.provider.getNetwork();
const chainId = network.chainId.toString();
const allDeployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
const deployments = allDeployments[chainId];
if (!deployments) {
throw new Error(`未找到网络 ${chainId} 的部署信息`);
}
console.log("📋 当前部署的合约:");
console.log(" Configurator Proxy:", deployments.configuratorProxy);
console.log(" Configurator Impl: ", deployments.configuratorImpl);
console.log("");
// ========== 升级 Configurator ==========
console.log("🔄 Phase 1: 升级 Configurator 合约");
console.log(" 当前 Configurator Proxy:", deployments.configuratorProxy);
console.log(" 当前 Configurator Implementation:", deployments.configuratorImpl);
// 获取新的 Configurator 合约工厂
const ConfiguratorV2 = await ethers.getContractFactory("Configurator");
console.log("\n 正在验证新实现合约...");
const upgradedConfigurator = await upgrades.upgradeProxy(
deployments.configuratorProxy,
ConfiguratorV2,
{
kind: "uups",
// unsafeSkipStorageCheck: true // 跳过存储布局检查(请确保你了解风险)
}
);
await upgradedConfigurator.waitForDeployment();
console.log(" ✅ Configurator 已升级!");
// 获取新的实现合约地址
const upgradedConfiguratorAddress = await upgradedConfigurator.getAddress();
const newConfiguratorImplAddress = await upgrades.erc1967.getImplementationAddress(upgradedConfiguratorAddress);
console.log(" 新 Configurator Implementation:", newConfiguratorImplAddress);
// 验证升级
console.log("\n 验证升级结果:");
console.log(" Configurator Proxy (不变):", upgradedConfiguratorAddress);
console.log(" Owner:", await upgradedConfigurator.owner());
// 保存升级历史
if (!deployments.upgradeHistory) {
deployments.upgradeHistory = [];
}
deployments.upgradeHistory.push({
timestamp: new Date().toISOString(),
contract: "Configurator",
oldImplementation: deployments.configuratorImpl,
newImplementation: newConfiguratorImplAddress,
upgrader: deployer.address
});
// 保存新的实现地址
deployments.configuratorImpl = newConfiguratorImplAddress;
deployments.configuratorUpgradeTimestamp = new Date().toISOString();
allDeployments[chainId] = deployments;
fs.writeFileSync(deploymentsPath, JSON.stringify(allDeployments, null, 2));
console.log("\n✅ Configurator 升级完成!");
console.log("=====================================");
console.log("旧实现:", deployments.upgradeHistory[deployments.upgradeHistory.length - 1].oldImplementation);
console.log("新实现:", newConfiguratorImplAddress);
console.log("=====================================\n");
console.log("💾 升级信息已保存到:", deploymentsPath);
console.log("");
console.log("📌 重要提示:");
console.log(" 1. 代理地址保持不变,用户无需更改合约地址");
console.log(" 2. 所有状态数据已保留");
console.log(" 3. 建议运行验证脚本确认升级成功");
console.log(" 4. 建议在测试网充分测试后再升级主网\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,114 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 Lending 合约
* 使用 upgrades.upgradeProxy() 进行 UUPS 升级
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("🔄 升级 Lending 合约");
console.log("==========================================");
console.log("升级账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-lending.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件,请先运行部署脚本");
}
const network = await ethers.provider.getNetwork();
const chainId = network.chainId.toString();
const allDeployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
const deployments = allDeployments[chainId];
if (!deployments) {
throw new Error(`未找到网络 ${chainId} 的部署信息`);
}
if (!deployments.lendingProxy) {
throw new Error("未找到 Lending Proxy 地址,请先运行配置脚本");
}
console.log("📋 当前部署的合约:");
console.log(" Lending Proxy:", deployments.lendingProxy);
console.log(" Lending Impl: ", deployments.lendingImpl);
console.log("");
// ========== 升级 Lending ==========
console.log("🔄 Phase 1: 升级 Lending 合约");
console.log(" 当前 Lending Proxy:", deployments.lendingProxy);
console.log(" 当前 Lending Implementation:", deployments.lendingImpl);
// 获取新的 Lending 合约工厂
const LendingV2 = await ethers.getContractFactory("Lending");
console.log("\n 正在验证新实现合约...");
// upgrades.upgradeProxy 会自动验证存储布局兼容性
const upgradedLending = await upgrades.upgradeProxy(
deployments.lendingProxy,
LendingV2,
{
kind: "uups"
}
);
await upgradedLending.waitForDeployment();
console.log(" ✅ Lending 已升级!");
// 获取新的实现合约地址
const upgradedLendingAddress = await upgradedLending.getAddress();
const newLendingImplAddress = await upgrades.erc1967.getImplementationAddress(upgradedLendingAddress);
console.log(" 新 Lending Implementation:", newLendingImplAddress);
// 验证升级
console.log("\n 验证升级结果:");
console.log(" Lending Proxy (不变):", upgradedLendingAddress);
console.log(" Owner:", await upgradedLending.owner());
console.log(" Base Token:", await upgradedLending.baseToken());
// 保存升级历史
if (!deployments.upgradeHistory) {
deployments.upgradeHistory = [];
}
deployments.upgradeHistory.push({
timestamp: new Date().toISOString(),
contract: "Lending",
oldImplementation: deployments.lendingImpl,
newImplementation: newLendingImplAddress,
upgrader: deployer.address
});
// 保存新的实现地址
deployments.lendingImpl = newLendingImplAddress;
deployments.lendingUpgradeTimestamp = new Date().toISOString();
allDeployments[chainId] = deployments;
fs.writeFileSync(deploymentsPath, JSON.stringify(allDeployments, null, 2));
console.log("\n✅ Lending 升级完成!");
console.log("=====================================");
console.log("旧实现:", deployments.upgradeHistory[deployments.upgradeHistory.length - 1].oldImplementation);
console.log("新实现:", newLendingImplAddress);
console.log("=====================================\n");
console.log("💾 升级信息已保存到:", deploymentsPath);
console.log("");
console.log("📌 重要提示:");
console.log(" 1. 代理地址保持不变,用户无需更改合约地址");
console.log(" 2. 所有状态数据已保留");
console.log(" 3. 建议运行验证脚本确认升级成功");
console.log(" 4. 建议在测试网充分测试后再升级主网\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,117 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 LendingPriceFeed 合约
* 使用 upgrades.upgradeProxy() 进行 UUPS 升级
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("🔄 升级 LendingPriceFeed 合约");
console.log("==========================================");
console.log("升级账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-lending.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件,请先运行部署脚本");
}
const network = await ethers.provider.getNetwork();
const chainId = network.chainId.toString();
const allDeployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
const deployments = allDeployments[chainId];
if (!deployments) {
throw new Error(`未找到网络 ${chainId} 的部署信息`);
}
if (!deployments.lendingPriceFeed) {
throw new Error("未找到 LendingPriceFeed Proxy 地址,请先运行部署脚本");
}
console.log("📋 当前部署的合约:");
console.log(" LendingPriceFeed Proxy:", deployments.lendingPriceFeed);
if (deployments.lendingPriceFeedImpl) {
console.log(" LendingPriceFeed Impl: ", deployments.lendingPriceFeedImpl);
}
console.log("");
// ========== 升级 LendingPriceFeed ==========
console.log("🔄 Phase 1: 升级 LendingPriceFeed 合约");
console.log(" 当前 LendingPriceFeed Proxy:", deployments.lendingPriceFeed);
if (deployments.lendingPriceFeedImpl) {
console.log(" 当前 LendingPriceFeed Implementation:", deployments.lendingPriceFeedImpl);
}
// 获取新的 LendingPriceFeed 合约工厂
const LendingPriceFeedV2 = await ethers.getContractFactory("LendingPriceFeed");
console.log("\n 正在验证新实现合约...");
const upgradedPriceFeed = await upgrades.upgradeProxy(
deployments.lendingPriceFeed,
LendingPriceFeedV2,
{
kind: "uups"
}
);
await upgradedPriceFeed.waitForDeployment();
console.log(" ✅ LendingPriceFeed 已升级!");
// 获取新的实现合约地址
const upgradedPriceFeedAddress = await upgradedPriceFeed.getAddress();
const newPriceFeedImplAddress = await upgrades.erc1967.getImplementationAddress(upgradedPriceFeedAddress);
console.log(" 新 LendingPriceFeed Implementation:", newPriceFeedImplAddress);
// 验证升级
console.log("\n 验证升级结果:");
console.log(" LendingPriceFeed Proxy (不变):", upgradedPriceFeedAddress);
console.log(" Owner:", await upgradedPriceFeed.owner());
console.log(" USDC Address:", await upgradedPriceFeed.usdcAddress());
// 保存升级历史
if (!deployments.upgradeHistory) {
deployments.upgradeHistory = [];
}
deployments.upgradeHistory.push({
timestamp: new Date().toISOString(),
contract: "LendingPriceFeed",
oldImplementation: deployments.lendingPriceFeedImpl || "未记录",
newImplementation: newPriceFeedImplAddress,
upgrader: deployer.address
});
// 保存新的实现地址
deployments.lendingPriceFeedImpl = newPriceFeedImplAddress;
deployments.lastUpgradeTime = new Date().toISOString();
allDeployments[chainId] = deployments;
fs.writeFileSync(deploymentsPath, JSON.stringify(allDeployments, null, 2));
console.log("\n✅ LendingPriceFeed 升级完成!");
console.log("=====================================");
console.log("旧实现:", deployments.upgradeHistory[deployments.upgradeHistory.length - 1].oldImplementation);
console.log("新实现:", newPriceFeedImplAddress);
console.log("=====================================\n");
console.log("💾 升级信息已保存到:", deploymentsPath);
console.log("");
console.log("📌 重要提示:");
console.log(" 1. 代理地址保持不变,用户无需更改合约地址");
console.log(" 2. 所有状态数据已保留");
console.log(" 3. 建议运行验证脚本确认升级成功");
console.log(" 4. 建议在测试网充分测试后再升级主网\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,113 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 USDY 合约
* 使用 upgrades.upgradeProxy() 进行 UUPS 升级
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("🔄 升级 USDY 合约");
console.log("==========================================");
console.log("升级账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-ytlp.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件,请先运行部署脚本");
}
const deployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
if (!deployments.contracts?.USDY?.proxy) {
throw new Error("未找到 USDY 部署信息");
}
console.log("📋 当前部署的合约:");
console.log(" USDY Proxy: ", deployments.contracts.USDY.proxy);
console.log(" USDY Implementation: ", deployments.contracts.USDY.implementation);
console.log("");
// ========== 升级 USDY ==========
console.log("🔄 Phase 1: 升级 USDY 代理合约");
// 获取新的 USDY 合约工厂
const USDYV2 = await ethers.getContractFactory("USDY");
console.log(" 正在验证新实现合约...");
const upgradedUSDY = await upgrades.upgradeProxy(
deployments.contracts.USDY.proxy,
USDYV2,
{
kind: "uups"
}
);
await upgradedUSDY.waitForDeployment();
console.log(" ✅ USDY 已升级!");
// 获取新的实现合约地址
const upgradedUSDYAddress = await upgradedUSDY.getAddress();
const newUSDYImplAddress = await upgrades.erc1967.getImplementationAddress(upgradedUSDYAddress);
console.log(" 新 USDY Implementation:", newUSDYImplAddress);
console.log("");
// ========== 验证升级结果 ==========
console.log("🔄 Phase 2: 验证升级结果");
console.log(" USDY Proxy (不变):", upgradedUSDYAddress);
console.log(" Name:", await upgradedUSDY.name());
console.log(" Symbol:", await upgradedUSDY.symbol());
console.log(" Total Supply:", ethers.formatUnits(await upgradedUSDY.totalSupply(), 6));
console.log("");
// ========== 保存更新的部署信息 ==========
if (!deployments.upgradeHistory) {
deployments.upgradeHistory = [];
}
deployments.upgradeHistory.push({
timestamp: new Date().toISOString(),
contract: "USDY",
oldImplementation: deployments.contracts.USDY.implementation,
newImplementation: newUSDYImplAddress,
upgrader: deployer.address
});
deployments.contracts.USDY.implementation = newUSDYImplAddress;
deployments.lastUpdate = new Date().toISOString();
fs.writeFileSync(deploymentsPath, JSON.stringify(deployments, null, 2));
console.log("💾 升级信息已保存到:", deploymentsPath);
// ========== 升级总结 ==========
console.log("\n🎉 升级总结:");
console.log("=====================================");
console.log("旧 USDY Implementation:");
console.log(" ", deployments.upgradeHistory[deployments.upgradeHistory.length - 1].oldImplementation);
console.log("");
console.log("新 USDY Implementation:");
console.log(" ", newUSDYImplAddress);
console.log("");
console.log("USDY Proxy (不变):");
console.log(" ", deployments.contracts.USDY.proxy);
console.log("=====================================\n");
console.log("✅ 升级完成!");
console.log("");
console.log("📌 重要提示:");
console.log(" 1. USDY 代理地址保持不变");
console.log(" 2. 所有状态数据已保留");
console.log(" 3. 建议运行验证脚本确认升级成功");
console.log(" 4. 主网升级前务必充分测试\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,125 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 YTAssetFactory 合约
*
* 升级步骤:
* 1. 部署新的 YTAssetFactory 实现合约
* 2. 使用 upgrades.upgradeProxy() 进行 UUPS 升级
* 3. 验证新功能
*
* 注意:
* - 这是 UUPS 代理升级,代理地址保持不变
* - 所有状态数据已保留
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("🔄 升级 YTAssetFactory 系统");
console.log("==========================================");
console.log("升级账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-vault-system.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件 deployments-vault-system.json请先运行部署脚本");
}
const deployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
if (!deployments.contracts?.YTAssetFactory?.proxy) {
throw new Error("未找到 YTAssetFactory 部署信息");
}
console.log("📋 当前部署的合约:");
console.log(" YTAssetFactory Proxy: ", deployments.contracts.YTAssetFactory.proxy);
console.log(" YTAssetFactory Implementation: ", deployments.contracts.YTAssetFactory.implementation);
console.log("");
// ========== Phase 1: 升级 YTAssetFactory ==========
console.log("🔄 Phase 1: 升级 YTAssetFactory 代理合约");
console.log(" 当前 YTAssetFactory Proxy:", deployments.contracts.YTAssetFactory.proxy);
console.log(" 当前 YTAssetFactory Implementation:", deployments.contracts.YTAssetFactory.implementation);
// 获取新的 YTAssetFactory 合约工厂
const YTAssetFactoryV2 = await ethers.getContractFactory("YTAssetFactory");
console.log("\n 正在验证新实现合约...");
const upgradedFactory = await upgrades.upgradeProxy(
deployments.contracts.YTAssetFactory.proxy,
YTAssetFactoryV2,
{
kind: "uups"
}
);
await upgradedFactory.waitForDeployment();
console.log(" ✅ YTAssetFactory 已升级!");
// 获取新的实现合约地址
const upgradedFactoryAddress = await upgradedFactory.getAddress();
const newFactoryImplAddress = await upgrades.erc1967.getImplementationAddress(upgradedFactoryAddress);
console.log(" 新 YTAssetFactory Implementation:", newFactoryImplAddress);
console.log("");
// ========== Phase 2: 验证升级结果 ==========
console.log("🔄 Phase 2: 验证升级结果");
console.log(" YTAssetFactory Proxy (不变):", upgradedFactoryAddress);
console.log(" Owner:", await upgradedFactory.owner());
console.log(" Vault Implementation:", await upgradedFactory.vaultImplementation());
console.log(" USDC Address:", await upgradedFactory.usdcAddress());
console.log("");
// ========== 保存更新的部署信息 ==========
// 保存旧的实现地址作为历史记录
if (!deployments.upgradeHistory) {
deployments.upgradeHistory = [];
}
deployments.upgradeHistory.push({
timestamp: new Date().toISOString(),
contract: "YTAssetFactory",
oldImplementation: deployments.contracts.YTAssetFactory.implementation,
newImplementation: newFactoryImplAddress,
upgrader: deployer.address
});
// 更新当前实现地址
deployments.contracts.YTAssetFactory.implementation = newFactoryImplAddress;
deployments.lastUpdate = new Date().toISOString();
fs.writeFileSync(deploymentsPath, JSON.stringify(deployments, null, 2));
console.log("💾 升级信息已保存到:", deploymentsPath);
// ========== 升级总结 ==========
console.log("\n🎉 升级总结:");
console.log("=====================================");
console.log("旧 YTAssetFactory Implementation:");
console.log(" ", deployments.upgradeHistory[deployments.upgradeHistory.length - 1].oldImplementation);
console.log("");
console.log("新 YTAssetFactory Implementation:");
console.log(" ", newFactoryImplAddress);
console.log("");
console.log("Factory Proxy (不变):");
console.log(" ", deployments.contracts.YTAssetFactory.proxy);
console.log("=====================================\n");
console.log("✅ 升级完成!");
console.log("");
console.log("📌 重要提示:");
console.log(" 1. YTAssetFactory 代理地址保持不变");
console.log(" 2. 所有状态数据已保留");
console.log(" 3. 建议运行验证脚本确认升级成功");
console.log(" 4. 主网升级前务必充分测试\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,107 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 YTLPToken 合约
* 使用 upgrades.upgradeProxy() 进行 UUPS 升级
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("🔄 升级 YTLPToken 合约");
console.log("==========================================");
console.log("升级账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-ytlp.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件,请先运行部署脚本");
}
const deployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
if (!deployments.contracts?.YTLPToken?.proxy) {
throw new Error("未找到 YTLPToken 部署信息");
}
console.log("📋 当前部署的合约:");
console.log(" YTLPToken Proxy: ", deployments.contracts.YTLPToken.proxy);
console.log(" YTLPToken Implementation: ", deployments.contracts.YTLPToken.implementation);
console.log("");
// ========== 升级 YTLPToken ==========
console.log("🔄 Phase 1: 升级 YTLPToken 代理合约");
// 获取新的 YTLPToken 合约工厂
const YTLPTokenV2 = await ethers.getContractFactory("YTLPToken");
console.log(" 正在验证新实现合约...");
const upgradedYTLPToken = await upgrades.upgradeProxy(
deployments.contracts.YTLPToken.proxy,
YTLPTokenV2,
{
kind: "uups"
}
);
await upgradedYTLPToken.waitForDeployment();
console.log(" ✅ YTLPToken 已升级!");
// 获取新的实现合约地址
const upgradedYTLPTokenAddress = await upgradedYTLPToken.getAddress();
const newYTLPTokenImplAddress = await upgrades.erc1967.getImplementationAddress(upgradedYTLPTokenAddress);
console.log(" 新 YTLPToken Implementation:", newYTLPTokenImplAddress);
console.log("");
// ========== 验证升级结果 ==========
console.log("🔄 Phase 2: 验证升级结果");
console.log(" YTLPToken Proxy (不变):", upgradedYTLPTokenAddress);
console.log(" Name:", await upgradedYTLPToken.name());
console.log(" Symbol:", await upgradedYTLPToken.symbol());
console.log(" Total Supply:", ethers.formatEther(await upgradedYTLPToken.totalSupply()));
console.log("");
// ========== 保存更新的部署信息 ==========
if (!deployments.upgradeHistory) {
deployments.upgradeHistory = [];
}
deployments.upgradeHistory.push({
timestamp: new Date().toISOString(),
contract: "YTLPToken",
oldImplementation: deployments.contracts.YTLPToken.implementation,
newImplementation: newYTLPTokenImplAddress,
upgrader: deployer.address
});
deployments.contracts.YTLPToken.implementation = newYTLPTokenImplAddress;
deployments.lastUpdate = new Date().toISOString();
fs.writeFileSync(deploymentsPath, JSON.stringify(deployments, null, 2));
console.log("💾 升级信息已保存到:", deploymentsPath);
// ========== 升级总结 ==========
console.log("\n🎉 升级总结:");
console.log("=====================================");
console.log("旧 YTLPToken Implementation:");
console.log(" ", deployments.upgradeHistory[deployments.upgradeHistory.length - 1].oldImplementation);
console.log("");
console.log("新 YTLPToken Implementation:");
console.log(" ", newYTLPTokenImplAddress);
console.log("");
console.log("YTLPToken Proxy (不变):");
console.log(" ", deployments.contracts.YTLPToken.proxy);
console.log("=====================================\n");
console.log("✅ 升级完成!\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,105 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 YTPoolManager 合约
* 使用 upgrades.upgradeProxy() 进行 UUPS 升级
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("🔄 升级 YTPoolManager 合约");
console.log("==========================================");
console.log("升级账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-ytlp.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件,请先运行部署脚本");
}
const deployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
if (!deployments.contracts?.YTPoolManager?.proxy) {
throw new Error("未找到 YTPoolManager 部署信息");
}
console.log("📋 当前部署的合约:");
console.log(" YTPoolManager Proxy: ", deployments.contracts.YTPoolManager.proxy);
console.log(" YTPoolManager Implementation: ", deployments.contracts.YTPoolManager.implementation);
console.log("");
// ========== 升级 YTPoolManager ==========
console.log("🔄 Phase 1: 升级 YTPoolManager 代理合约");
// 获取新的 YTPoolManager 合约工厂
const YTPoolManagerV2 = await ethers.getContractFactory("YTPoolManager");
console.log(" 正在验证新实现合约...");
const upgradedYTPoolManager = await upgrades.upgradeProxy(
deployments.contracts.YTPoolManager.proxy,
YTPoolManagerV2,
{
kind: "uups"
}
);
await upgradedYTPoolManager.waitForDeployment();
console.log(" ✅ YTPoolManager 已升级!");
// 获取新的实现合约地址
const upgradedYTPoolManagerAddress = await upgradedYTPoolManager.getAddress();
const newYTPoolManagerImplAddress = await upgrades.erc1967.getImplementationAddress(upgradedYTPoolManagerAddress);
console.log(" 新 YTPoolManager Implementation:", newYTPoolManagerImplAddress);
console.log("");
// ========== 验证升级结果 ==========
console.log("🔄 Phase 2: 验证升级结果");
console.log(" YTPoolManager Proxy (不变):", upgradedYTPoolManagerAddress);
console.log(" Owner:", await upgradedYTPoolManager.owner());
console.log("");
// ========== 保存更新的部署信息 ==========
if (!deployments.upgradeHistory) {
deployments.upgradeHistory = [];
}
deployments.upgradeHistory.push({
timestamp: new Date().toISOString(),
contract: "YTPoolManager",
oldImplementation: deployments.contracts.YTPoolManager.implementation,
newImplementation: newYTPoolManagerImplAddress,
upgrader: deployer.address
});
deployments.contracts.YTPoolManager.implementation = newYTPoolManagerImplAddress;
deployments.lastUpdate = new Date().toISOString();
fs.writeFileSync(deploymentsPath, JSON.stringify(deployments, null, 2));
console.log("💾 升级信息已保存到:", deploymentsPath);
// ========== 升级总结 ==========
console.log("\n🎉 升级总结:");
console.log("=====================================");
console.log("旧 YTPoolManager Implementation:");
console.log(" ", deployments.upgradeHistory[deployments.upgradeHistory.length - 1].oldImplementation);
console.log("");
console.log("新 YTPoolManager Implementation:");
console.log(" ", newYTPoolManagerImplAddress);
console.log("");
console.log("YTPoolManager Proxy (不变):");
console.log(" ", deployments.contracts.YTPoolManager.proxy);
console.log("=====================================\n");
console.log("✅ 升级完成!\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,105 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 YTPriceFeed 合约
* 使用 upgrades.upgradeProxy() 进行 UUPS 升级
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("🔄 升级 YTPriceFeed 合约");
console.log("==========================================");
console.log("升级账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-ytlp.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件,请先运行部署脚本");
}
const deployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
if (!deployments.contracts?.YTPriceFeed?.proxy) {
throw new Error("未找到 YTPriceFeed 部署信息");
}
console.log("📋 当前部署的合约:");
console.log(" YTPriceFeed Proxy: ", deployments.contracts.YTPriceFeed.proxy);
console.log(" YTPriceFeed Implementation: ", deployments.contracts.YTPriceFeed.implementation);
console.log("");
// ========== 升级 YTPriceFeed ==========
console.log("🔄 Phase 1: 升级 YTPriceFeed 代理合约");
// 获取新的 YTPriceFeed 合约工厂
const YTPriceFeedV2 = await ethers.getContractFactory("YTPriceFeed");
console.log(" 正在验证新实现合约...");
const upgradedYTPriceFeed = await upgrades.upgradeProxy(
deployments.contracts.YTPriceFeed.proxy,
YTPriceFeedV2,
{
kind: "uups"
}
);
await upgradedYTPriceFeed.waitForDeployment();
console.log(" ✅ YTPriceFeed 已升级!");
// 获取新的实现合约地址
const upgradedYTPriceFeedAddress = await upgradedYTPriceFeed.getAddress();
const newYTPriceFeedImplAddress = await upgrades.erc1967.getImplementationAddress(upgradedYTPriceFeedAddress);
console.log(" 新 YTPriceFeed Implementation:", newYTPriceFeedImplAddress);
console.log("");
// ========== 验证升级结果 ==========
console.log("🔄 Phase 2: 验证升级结果");
console.log(" YTPriceFeed Proxy (不变):", upgradedYTPriceFeedAddress);
console.log(" Owner:", await upgradedYTPriceFeed.owner());
console.log("");
// ========== 保存更新的部署信息 ==========
if (!deployments.upgradeHistory) {
deployments.upgradeHistory = [];
}
deployments.upgradeHistory.push({
timestamp: new Date().toISOString(),
contract: "YTPriceFeed",
oldImplementation: deployments.contracts.YTPriceFeed.implementation,
newImplementation: newYTPriceFeedImplAddress,
upgrader: deployer.address
});
deployments.contracts.YTPriceFeed.implementation = newYTPriceFeedImplAddress;
deployments.lastUpdate = new Date().toISOString();
fs.writeFileSync(deploymentsPath, JSON.stringify(deployments, null, 2));
console.log("💾 升级信息已保存到:", deploymentsPath);
// ========== 升级总结 ==========
console.log("\n🎉 升级总结:");
console.log("=====================================");
console.log("旧 YTPriceFeed Implementation:");
console.log(" ", deployments.upgradeHistory[deployments.upgradeHistory.length - 1].oldImplementation);
console.log("");
console.log("新 YTPriceFeed Implementation:");
console.log(" ", newYTPriceFeedImplAddress);
console.log("");
console.log("YTPriceFeed Proxy (不变):");
console.log(" ", deployments.contracts.YTPriceFeed.proxy);
console.log("=====================================\n");
console.log("✅ 升级完成!\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,105 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 YTRewardRouter 合约
* 使用 upgrades.upgradeProxy() 进行 UUPS 升级
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("🔄 升级 YTRewardRouter 合约");
console.log("==========================================");
console.log("升级账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-ytlp.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件,请先运行部署脚本");
}
const deployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
if (!deployments.contracts?.YTRewardRouter?.proxy) {
throw new Error("未找到 YTRewardRouter 部署信息");
}
console.log("📋 当前部署的合约:");
console.log(" YTRewardRouter Proxy: ", deployments.contracts.YTRewardRouter.proxy);
console.log(" YTRewardRouter Implementation: ", deployments.contracts.YTRewardRouter.implementation);
console.log("");
// ========== 升级 YTRewardRouter ==========
console.log("🔄 Phase 1: 升级 YTRewardRouter 代理合约");
// 获取新的 YTRewardRouter 合约工厂
const YTRewardRouterV2 = await ethers.getContractFactory("YTRewardRouter");
console.log(" 正在验证新实现合约...");
const upgradedYTRewardRouter = await upgrades.upgradeProxy(
deployments.contracts.YTRewardRouter.proxy,
YTRewardRouterV2,
{
kind: "uups"
}
);
await upgradedYTRewardRouter.waitForDeployment();
console.log(" ✅ YTRewardRouter 已升级!");
// 获取新的实现合约地址
const upgradedYTRewardRouterAddress = await upgradedYTRewardRouter.getAddress();
const newYTRewardRouterImplAddress = await upgrades.erc1967.getImplementationAddress(upgradedYTRewardRouterAddress);
console.log(" 新 YTRewardRouter Implementation:", newYTRewardRouterImplAddress);
console.log("");
// ========== 验证升级结果 ==========
console.log("🔄 Phase 2: 验证升级结果");
console.log(" YTRewardRouter Proxy (不变):", upgradedYTRewardRouterAddress);
console.log(" Owner:", await upgradedYTRewardRouter.owner());
console.log("");
// ========== 保存更新的部署信息 ==========
if (!deployments.upgradeHistory) {
deployments.upgradeHistory = [];
}
deployments.upgradeHistory.push({
timestamp: new Date().toISOString(),
contract: "YTRewardRouter",
oldImplementation: deployments.contracts.YTRewardRouter.implementation,
newImplementation: newYTRewardRouterImplAddress,
upgrader: deployer.address
});
deployments.contracts.YTRewardRouter.implementation = newYTRewardRouterImplAddress;
deployments.lastUpdate = new Date().toISOString();
fs.writeFileSync(deploymentsPath, JSON.stringify(deployments, null, 2));
console.log("💾 升级信息已保存到:", deploymentsPath);
// ========== 升级总结 ==========
console.log("\n🎉 升级总结:");
console.log("=====================================");
console.log("旧 YTRewardRouter Implementation:");
console.log(" ", deployments.upgradeHistory[deployments.upgradeHistory.length - 1].oldImplementation);
console.log("");
console.log("新 YTRewardRouter Implementation:");
console.log(" ", newYTRewardRouterImplAddress);
console.log("");
console.log("YTRewardRouter Proxy (不变):");
console.log(" ", deployments.contracts.YTRewardRouter.proxy);
console.log("=====================================\n");
console.log("✅ 升级完成!\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,105 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 YTVault 合约
* 使用 upgrades.upgradeProxy() 进行 UUPS 升级
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("🔄 升级 YTVault 合约");
console.log("==========================================");
console.log("升级账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-ytlp.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件,请先运行部署脚本");
}
const deployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
if (!deployments.contracts?.YTVault?.proxy) {
throw new Error("未找到 YTVault 部署信息");
}
console.log("📋 当前部署的合约:");
console.log(" YTVault Proxy: ", deployments.contracts.YTVault.proxy);
console.log(" YTVault Implementation: ", deployments.contracts.YTVault.implementation);
console.log("");
// ========== 升级 YTVault ==========
console.log("🔄 Phase 1: 升级 YTVault 代理合约");
// 获取新的 YTVault 合约工厂
const YTVaultV2 = await ethers.getContractFactory("YTVault");
console.log(" 正在验证新实现合约...");
const upgradedYTVault = await upgrades.upgradeProxy(
deployments.contracts.YTVault.proxy,
YTVaultV2,
{
kind: "uups"
}
);
await upgradedYTVault.waitForDeployment();
console.log(" ✅ YTVault 已升级!");
// 获取新的实现合约地址
const upgradedYTVaultAddress = await upgradedYTVault.getAddress();
const newYTVaultImplAddress = await upgrades.erc1967.getImplementationAddress(upgradedYTVaultAddress);
console.log(" 新 YTVault Implementation:", newYTVaultImplAddress);
console.log("");
// ========== 验证升级结果 ==========
console.log("🔄 Phase 2: 验证升级结果");
console.log(" YTVault Proxy (不变):", upgradedYTVaultAddress);
console.log(" Owner:", await upgradedYTVault.owner());
console.log("");
// ========== 保存更新的部署信息 ==========
if (!deployments.upgradeHistory) {
deployments.upgradeHistory = [];
}
deployments.upgradeHistory.push({
timestamp: new Date().toISOString(),
contract: "YTVault",
oldImplementation: deployments.contracts.YTVault.implementation,
newImplementation: newYTVaultImplAddress,
upgrader: deployer.address
});
deployments.contracts.YTVault.implementation = newYTVaultImplAddress;
deployments.lastUpdate = new Date().toISOString();
fs.writeFileSync(deploymentsPath, JSON.stringify(deployments, null, 2));
console.log("💾 升级信息已保存到:", deploymentsPath);
// ========== 升级总结 ==========
console.log("\n🎉 升级总结:");
console.log("=====================================");
console.log("旧 YTVault Implementation:");
console.log(" ", deployments.upgradeHistory[deployments.upgradeHistory.length - 1].oldImplementation);
console.log("");
console.log("新 YTVault Implementation:");
console.log(" ", newYTVaultImplAddress);
console.log("");
console.log("YTVault Proxy (不变):");
console.log(" ", deployments.contracts.YTVault.proxy);
console.log("=====================================\n");
console.log("✅ 升级完成!\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -1,182 +0,0 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 验证 YTAssetVault 升级结果
*
* 功能:
* 1. 检查 Factory 的实现地址是否已更新
* 2. 验证现有 Vault 的实现地址
* 3. 测试新功能是否可用
*/
async function main() {
console.log("\n==========================================");
console.log("🔍 验证 YTAssetVault 升级结果");
console.log("==========================================\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-vault-system.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件");
}
const deployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
const factory = await ethers.getContractAt(
"YTAssetFactory",
deployments.contracts.YTAssetFactory.proxy
);
// ========== 验证 Factory ==========
console.log("📋 验证 Factory 配置");
console.log("=====================================");
const currentImplInFactory = await factory.vaultImplementation();
const expectedImpl = deployments.contracts.YTAssetVault.implementation;
console.log("Factory Proxy: ", deployments.contracts.YTAssetFactory.proxy);
console.log("当前 vaultImplementation:", currentImplInFactory);
console.log("配置文件中的实现: ", expectedImpl);
if (currentImplInFactory.toLowerCase() === expectedImpl.toLowerCase()) {
console.log("✅ Factory 配置正确!\n");
} else {
console.log("❌ Factory 配置不匹配!\n");
}
// ========== 验证已部署的 Vaults ==========
const vaults = deployments.vaults || [];
if (vaults.length === 0) {
console.log(" 没有已部署的 Vault\n");
return;
}
console.log("📋 验证已部署的 Vaults");
console.log("=====================================");
console.log(`发现 ${vaults.length} 个 Vault\n`);
const results: any[] = [];
for (let i = 0; i < vaults.length; i++) {
const vaultInfo = vaults[i];
console.log(`[${i + 1}/${vaults.length}] 检查 ${vaultInfo.symbol} (${vaultInfo.address})`);
try {
// 获取实现地址
const implAddress = await upgrades.erc1967.getImplementationAddress(vaultInfo.address);
const isUpgraded = implAddress.toLowerCase() === expectedImpl.toLowerCase();
console.log(` 实现地址: ${implAddress}`);
console.log(` 状态: ${isUpgraded ? '✅ 已升级' : '⏸️ 未升级'}`);
// 如果已升级,测试新功能
if (isUpgraded) {
const vault = await ethers.getContractAt("YTAssetVault", vaultInfo.address);
try {
// 测试新增的状态变量
const pendingCount = await vault.pendingRequestsCount();
const requestIdCounter = await vault.requestIdCounter();
const processedUpToIndex = await vault.processedUpToIndex();
console.log(` 新功能验证:`);
console.log(` - pendingRequestsCount: ${pendingCount}`);
console.log(` - requestIdCounter: ${requestIdCounter}`);
console.log(` - processedUpToIndex: ${processedUpToIndex}`);
// 测试新增的查询函数
const queueProgress = await vault.getQueueProgress();
console.log(` - 队列进度: ${queueProgress[0]}/${queueProgress[1]} (待处理: ${queueProgress[2]})`);
console.log(` ✅ 新功能工作正常`);
results.push({
index: i,
symbol: vaultInfo.symbol,
address: vaultInfo.address,
upgraded: true,
functional: true
});
} catch (error: any) {
console.log(` ⚠️ 新功能测试失败: ${error.message}`);
results.push({
index: i,
symbol: vaultInfo.symbol,
address: vaultInfo.address,
upgraded: true,
functional: false,
error: error.message
});
}
} else {
results.push({
index: i,
symbol: vaultInfo.symbol,
address: vaultInfo.address,
upgraded: false,
functional: false
});
}
} catch (error: any) {
console.log(` ❌ 检查失败: ${error.message}`);
results.push({
index: i,
symbol: vaultInfo.symbol,
address: vaultInfo.address,
upgraded: false,
functional: false,
error: error.message
});
}
console.log("");
}
// ========== 验证总结 ==========
console.log("📊 验证总结");
console.log("=====================================");
const upgraded = results.filter(r => r.upgraded);
const functional = results.filter(r => r.functional);
const needsUpgrade = results.filter(r => !r.upgraded);
console.log(`总 Vaults 数量: ${results.length}`);
console.log(`已升级: ${upgraded.length}`);
console.log(`功能正常: ${functional.length}`);
console.log(`待升级: ${needsUpgrade.length} ${needsUpgrade.length > 0 ? '⏸️' : ''}`);
console.log("");
if (needsUpgrade.length > 0) {
console.log("⏸️ 待升级的 Vaults:");
needsUpgrade.forEach(v => {
console.log(` [${v.index}] ${v.symbol}: ${v.address}`);
});
console.log("");
console.log("💡 升级命令:");
console.log(` factory.upgradeVault("vaultAddress", "${expectedImpl}")`);
console.log("");
}
// ========== 升级历史 ==========
if (deployments.upgradeHistory && deployments.upgradeHistory.length > 0) {
console.log("📜 升级历史");
console.log("=====================================");
deployments.upgradeHistory.forEach((h: any, idx: number) => {
console.log(`[${idx + 1}] ${h.timestamp}`);
console.log(` 升级者: ${h.upgrader}`);
console.log(` 旧实现: ${h.oldImplementation}`);
console.log(` 新实现: ${h.newImplementation}`);
});
console.log("");
}
console.log("✅ 验证完成!\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});