This commit is contained in:
2025-12-18 13:07:35 +08:00
commit 76b7f838db
271 changed files with 88812 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
import { ethers, upgrades } from "hardhat";
/**
* 部署WUSD代币
*/
async function main() {
console.log("开始部署WUSD代币...\n");
const [deployer] = await ethers.getSigners();
console.log("部署账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ===== 部署WUSD (可升级) =====
console.log("===== 部署WUSD (可升级) =====");
const WUSD = await ethers.getContractFactory("WUSD");
console.log("部署WUSD代理...");
const wusd = await upgrades.deployProxy(
WUSD,
["Wrapped USD", "WUSD"],
{
initializer: "initialize",
kind: "uups",
}
);
await wusd.waitForDeployment();
const wusdAddress = await wusd.getAddress();
console.log("✅ WUSD代理部署到:", wusdAddress);
const wusdImplAddress = await upgrades.erc1967.getImplementationAddress(wusdAddress);
console.log("✅ WUSD实现地址:", wusdImplAddress);
// 验证部署
const name = await wusd.name();
const symbol = await wusd.symbol();
const decimals = await wusd.decimals();
console.log("\n代币信息:");
console.log(" 名称:", name);
console.log(" 符号:", symbol);
console.log(" 精度:", decimals.toString());
// ===== 显示部署摘要 =====
console.log("\n===== 部署摘要 =====");
console.log("WUSD代理:", wusdAddress);
console.log("WUSD实现:", wusdImplAddress);
// 保存到JSON文件
const deploymentInfo = {
network: (await ethers.provider.getNetwork()).name,
chainId: (await ethers.provider.getNetwork()).chainId.toString(),
deployer: deployer.address,
timestamp: new Date().toISOString(),
contracts: {
WUSD: {
proxy: wusdAddress,
implementation: wusdImplAddress,
name: name,
symbol: symbol,
decimals: Number(decimals)
}
}
};
const fs = require("fs");
fs.writeFileSync(
"./deployments-wusd.json",
JSON.stringify(deploymentInfo, null, 2)
);
console.log("\n✅ 部署信息已保存到 deployments-wusd.json");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,184 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
/**
* 部署YTLp系统的所有合约不包含配置
*/
async function main() {
console.log("开始部署YT协议可升级合约...\n");
const [deployer] = await ethers.getSigners();
console.log("部署账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ==================== 1. 部署代币合约 ====================
console.log("===== 1. 部署代币合约 =====");
// 部署USDY (可升级)
console.log("部署USDY...");
const USDY = await ethers.getContractFactory("USDY");
const usdy = await upgrades.deployProxy(USDY, [], {
kind: "uups",
initializer: "initialize"
});
await usdy.waitForDeployment();
const usdyAddress = await usdy.getAddress();
console.log("✅ USDY deployed to:", usdyAddress);
// 部署YTLPToken (可升级)
console.log("部署YTLPToken...");
const YTLPToken = await ethers.getContractFactory("YTLPToken");
const ytLP = await upgrades.deployProxy(YTLPToken, [], {
kind: "uups",
initializer: "initialize"
});
await ytLP.waitForDeployment();
const ytLPAddress = await ytLP.getAddress();
console.log("✅ YTLPToken deployed to:", ytLPAddress);
// ==================== 2. 部署核心合约 ====================
console.log("\n===== 2. 部署核心合约 =====");
if (!fs.existsSync("./deployments-wusd.json")) {
throw new Error("未找到 deployments-wusd.json请先运行 deployWUSD.ts");
}
const wusdDeployment = JSON.parse(fs.readFileSync("./deployments-wusd.json", "utf8"));
const wusdAddress = wusdDeployment.contracts.WUSD.proxy;
// 部署YTPriceFeed (可升级)
console.log("部署YTPriceFeed...");
const YTPriceFeed = await ethers.getContractFactory("YTPriceFeed");
const priceFeed = await upgrades.deployProxy(YTPriceFeed, [wusdAddress], {
kind: "uups",
initializer: "initialize"
});
await priceFeed.waitForDeployment();
const priceFeedAddress = await priceFeed.getAddress();
console.log("✅ YTPriceFeed deployed to:", priceFeedAddress);
// 部署YTVault (可升级)
console.log("部署YTVault...");
const YTVault = await ethers.getContractFactory("YTVault");
const vault = await upgrades.deployProxy(
YTVault,
[usdyAddress, priceFeedAddress],
{
kind: "uups",
initializer: "initialize"
}
);
await vault.waitForDeployment();
const vaultAddress = await vault.getAddress();
console.log("✅ YTVault deployed to:", vaultAddress);
// 部署YTPoolManager (可升级)
console.log("部署YTPoolManager...");
const YTPoolManager = await ethers.getContractFactory("YTPoolManager");
const cooldownDuration = 15 * 60; // 15分钟
const poolManager = await upgrades.deployProxy(
YTPoolManager,
[vaultAddress, usdyAddress, ytLPAddress, cooldownDuration],
{
kind: "uups",
initializer: "initialize"
}
);
await poolManager.waitForDeployment();
const poolManagerAddress = await poolManager.getAddress();
console.log("✅ YTPoolManager deployed to:", poolManagerAddress);
// 部署YTRewardRouter (可升级)
console.log("部署YTRewardRouter...");
const YTRewardRouter = await ethers.getContractFactory("YTRewardRouter");
const router = await upgrades.deployProxy(
YTRewardRouter,
[usdyAddress, ytLPAddress, poolManagerAddress, vaultAddress],
{
kind: "uups",
initializer: "initialize"
}
);
await router.waitForDeployment();
const routerAddress = await router.getAddress();
console.log("✅ YTRewardRouter deployed to:", routerAddress);
// ==================== 3. 输出部署信息 ====================
console.log("\n===== 部署完成!=====");
console.log("\n📋 合约地址:");
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
console.log("USDY: ", usdyAddress);
console.log("YTLPToken: ", ytLPAddress);
console.log("YTPriceFeed: ", priceFeedAddress);
console.log("YTVault: ", vaultAddress);
console.log("YTPoolManager: ", poolManagerAddress);
console.log("YTRewardRouter: ", routerAddress);
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
// 获取实现合约地址
console.log("\n📋 实现合约地址 (用于验证和升级):");
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
const usdyImpl = await upgrades.erc1967.getImplementationAddress(usdyAddress);
const ytLPImpl = await upgrades.erc1967.getImplementationAddress(ytLPAddress);
const priceFeedImpl = await upgrades.erc1967.getImplementationAddress(priceFeedAddress);
const vaultImpl = await upgrades.erc1967.getImplementationAddress(vaultAddress);
const poolManagerImpl = await upgrades.erc1967.getImplementationAddress(poolManagerAddress);
const routerImpl = await upgrades.erc1967.getImplementationAddress(routerAddress);
console.log("USDY Implementation: ", usdyImpl);
console.log("YTLPToken Implementation: ", ytLPImpl);
console.log("YTPriceFeed Implementation: ", priceFeedImpl);
console.log("YTVault Implementation: ", vaultImpl);
console.log("YTPoolManager Implementation: ", poolManagerImpl);
console.log("YTRewardRouter Implementation: ", routerImpl);
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
// 保存到JSON文件
const deploymentInfo = {
network: (await ethers.provider.getNetwork()).name,
chainId: (await ethers.provider.getNetwork()).chainId.toString(),
deployer: deployer.address,
timestamp: new Date().toISOString(),
contracts: {
USDY: {
proxy: usdyAddress,
implementation: usdyImpl
},
YTLPToken: {
proxy: ytLPAddress,
implementation: ytLPImpl
},
YTPriceFeed: {
proxy: priceFeedAddress,
implementation: priceFeedImpl
},
YTVault: {
proxy: vaultAddress,
implementation: vaultImpl
},
YTPoolManager: {
proxy: poolManagerAddress,
implementation: poolManagerImpl
},
YTRewardRouter: {
proxy: routerAddress,
implementation: routerImpl
}
}
};
fs.writeFileSync(
"./deployments-ytlp.json",
JSON.stringify(deploymentInfo, null, 2)
);
console.log("\n✅ 部署信息已保存到 deployments-ytlp.json");
console.log("\n⚠ 注意: 合约已部署但未配置,请运行 configureYTLp.ts 进行配置");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,99 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
/**
* 部署YTAssetFactory和YTAssetVault系统
*/
async function main() {
console.log("开始部署YT Asset Vault系统...\n");
const [deployer] = await ethers.getSigners();
console.log("部署账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// WUSD地址需要提前部署或使用已知地址
// const WUSD_ADDRESS = "0x7Cd017ca5ddb86861FA983a34b5F495C6F898c41";
if (!fs.existsSync("./deployments-wusd.json")) {
throw new Error("未找到 deployments-wusd.json请先运行 deployWUSD.ts");
}
const wusdDeployment = JSON.parse(fs.readFileSync("./deployments-wusd.json", "utf8"));
const WUSD_ADDRESS = wusdDeployment.contracts.WUSD.proxy;
// ===== 1. 部署YTAssetVault实现合约 =====
console.log("===== 1. 部署YTAssetVault实现合约 =====");
const YTAssetVault = await ethers.getContractFactory("YTAssetVault");
console.log("部署YTAssetVault实现...");
const vaultImpl = await YTAssetVault.deploy();
await vaultImpl.waitForDeployment();
const vaultImplAddress = await vaultImpl.getAddress();
console.log("✅ YTAssetVault实现部署到:", vaultImplAddress);
// ===== 2. 部署YTAssetFactory可升级 =====
console.log("\n===== 2. 部署YTAssetFactory可升级 =====");
const YTAssetFactory = await ethers.getContractFactory("YTAssetFactory");
// 默认硬顶: 1000万
const defaultHardCap = ethers.parseEther("10000000");
console.log("部署YTAssetFactory代理...");
const vaultFactory = await upgrades.deployProxy(
YTAssetFactory,
[vaultImplAddress, defaultHardCap],
{
initializer: "initialize",
kind: "uups",
}
);
await vaultFactory.waitForDeployment();
const vaultFactoryAddress = await vaultFactory.getAddress();
console.log("✅ YTAssetFactory部署到:", vaultFactoryAddress);
const vaultFactoryImplAddress = await upgrades.erc1967.getImplementationAddress(vaultFactoryAddress);
console.log("✅ YTAssetFactory实现:", vaultFactoryImplAddress);
// ===== 3. 显示部署摘要 =====
console.log("\n===== 部署摘要 =====");
console.log("WUSD地址: ", WUSD_ADDRESS);
console.log("YTAssetVault实现: ", vaultImplAddress);
console.log("YTAssetFactory代理: ", vaultFactoryAddress);
console.log("YTAssetFactory实现: ", vaultFactoryImplAddress);
console.log("默认硬顶: ", ethers.formatEther(defaultHardCap), "tokens");
// 保存到JSON文件
const deploymentInfo = {
network: (await ethers.provider.getNetwork()).name,
chainId: (await ethers.provider.getNetwork()).chainId.toString(),
deployer: deployer.address,
timestamp: new Date().toISOString(),
wusdAddress: WUSD_ADDRESS,
defaultHardCap: defaultHardCap.toString(),
contracts: {
YTAssetVault: {
implementation: vaultImplAddress
},
YTAssetFactory: {
proxy: vaultFactoryAddress,
implementation: vaultFactoryImplAddress
}
},
vaults: [] // 创建的vault将被添加到这里
};
fs.writeFileSync(
"./deployments-vault-system.json",
JSON.stringify(deploymentInfo, null, 2)
);
console.log("\n✅ 部署信息已保存到 deployments-vault-system.json");
console.log("\n💡 下一步:");
console.log("1. 使用 createVault.ts 创建YTAssetVault代币");
console.log("2. 在YTLp系统中将创建的vault添加到白名单");
console.log("3. 为vault设置价格和其他参数");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,159 @@
import { ethers } from "hardhat";
import * as fs from "fs";
/**
* 通过YTAssetFactory创建YTAssetVault
*/
async function main() {
console.log("开始创建YTAssetVault...\n");
const [deployer] = await ethers.getSigners();
console.log("操作账户:", deployer.address);
// ==================== 1. 读取Factory地址 ====================
console.log("\n===== 1. 读取Factory地址 =====");
if (!fs.existsSync("./deployments-vault-system.json")) {
throw new Error("未找到 deployments-vault-system.json请先运行 deployAsset.ts");
}
const vaultDeployment = JSON.parse(fs.readFileSync("./deployments-vault-system.json", "utf8"));
const factoryAddress = vaultDeployment.contracts.YTAssetFactory.proxy;
const wusdAddress = vaultDeployment.wusdAddress;
console.log("YTAssetFactory:", factoryAddress);
console.log("WUSD地址:", wusdAddress);
const factory = await ethers.getContractAt("YTAssetFactory", factoryAddress);
// 注意YTAssetVault的价格精度是1e30
const PRICE_PRECISION = ethers.parseUnits("1", 30); // 1e30
// 可以在这里修改要创建的vault参数
const vaultParams = [
{
name: "YT Token A",
symbol: "YT-A",
manager: deployer.address,
hardCap: ethers.parseEther("10000000"), // 1000万
redemptionTime: Math.floor(Date.now() / 1000) + 365 * 24 * 60 * 60, // 1年后
initialWusdPrice: PRICE_PRECISION, // $1.00 (精度1e30)
initialYtPrice: PRICE_PRECISION // $1.00 (精度1e30)
},
{
name: "YT Token B",
symbol: "YT-B",
manager: deployer.address,
hardCap: ethers.parseEther("10000000"),
redemptionTime: Math.floor(Date.now() / 1000) + 365 * 24 * 60 * 60,
initialWusdPrice: PRICE_PRECISION, // $1.00 (精度1e30)
initialYtPrice: PRICE_PRECISION // $1.00 (精度1e30)
},
{
name: "YT Token C",
symbol: "YT-C",
manager: deployer.address,
hardCap: ethers.parseEther("10000000"),
redemptionTime: Math.floor(Date.now() / 1000) + 365 * 24 * 60 * 60,
initialWusdPrice: PRICE_PRECISION, // $1.00 (精度1e30)
initialYtPrice: PRICE_PRECISION // $1.00 (精度1e30)
}
];
// ==================== 2. 创建Vaults ====================
console.log("\n===== 2. 创建Vaults =====");
const createdVaults: any[] = [];
for (const params of vaultParams) {
console.log(`\n创建 ${params.name} (${params.symbol})...`);
// 价格已经是1e30精度直接使用
const wusdPrice = params.initialWusdPrice;
const ytPrice = params.initialYtPrice;
const tx = await factory.createVault(
params.name,
params.symbol,
params.manager,
params.hardCap,
wusdAddress,
params.redemptionTime,
wusdPrice,
ytPrice
);
const receipt = await tx.wait();
// 从事件中获取vault地址
const event = receipt?.logs.find((log: any) => {
try {
const parsed = factory.interface.parseLog({
topics: log.topics as string[],
data: log.data
});
return parsed?.name === "VaultCreated";
} catch {
return false;
}
});
if (event) {
const parsed = factory.interface.parseLog({
topics: event.topics as string[],
data: event.data
});
const vaultAddress = parsed?.args[0];
const index = parsed?.args[5];
console.log(" ✅ Vault地址:", vaultAddress);
console.log(" ✅ Vault索引:", index.toString());
createdVaults.push({
name: params.name,
symbol: params.symbol,
address: vaultAddress,
index: index.toString(),
manager: params.manager,
hardCap: params.hardCap.toString(),
redemptionTime: params.redemptionTime,
wusdPrice: wusdPrice.toString(),
ytPrice: ytPrice.toString()
});
}
}
// ==================== 3. 输出摘要 ====================
console.log("\n===== 创建完成!=====");
console.log("\n📋 创建的Vaults:");
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
createdVaults.forEach((vault, i) => {
console.log(`${i + 1}. ${vault.name} (${vault.symbol})`);
console.log(` 地址: ${vault.address}`);
console.log(` 索引: ${vault.index}`);
});
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
// 更新部署文件添加创建的vaults
vaultDeployment.vaults = createdVaults;
vaultDeployment.lastUpdate = new Date().toISOString();
fs.writeFileSync(
"./deployments-vault-system.json",
JSON.stringify(vaultDeployment, null, 2)
);
console.log("\n✅ Vault信息已保存到 deployments-vault-system.json");
console.log("\n💡 下一步:");
console.log("1. 在YTLp系统中将这些vault添加到白名单");
console.log("2. 为YTPriceFeed设置价格来源使用第一个vault");
console.log("3. 为每个vault设置初始价格");
console.log("4. 开始使用!");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,189 @@
import { ethers } from "hardhat";
import * as fs from "fs";
/**
* 配置YTLp系统的权限和参数
* 需要先运行 deployYTLp.ts 和 deployAsset.ts
*/
async function main() {
console.log("开始配置YT协议...\n");
const [deployer] = await ethers.getSigners();
console.log("配置账户:", deployer.address);
console.log("账户余额:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "ETH\n");
// ==================== 1. 读取部署地址 ====================
console.log("===== 1. 读取部署地址 =====");
// 读取YTLp系统部署信息
const ytlpDeployment = JSON.parse(fs.readFileSync("./deployments-ytlp.json", "utf8"));
const usdyAddress = ytlpDeployment.contracts.USDY.proxy;
const ytLPAddress = ytlpDeployment.contracts.YTLPToken.proxy;
const priceFeedAddress = ytlpDeployment.contracts.YTPriceFeed.proxy;
const vaultAddress = ytlpDeployment.contracts.YTVault.proxy;
const poolManagerAddress = ytlpDeployment.contracts.YTPoolManager.proxy;
const routerAddress = ytlpDeployment.contracts.YTRewardRouter.proxy;
console.log("USDY: ", usdyAddress);
console.log("YTLPToken: ", ytLPAddress);
console.log("YTPriceFeed: ", priceFeedAddress);
console.log("YTVault: ", vaultAddress);
console.log("YTPoolManager: ", poolManagerAddress);
console.log("YTRewardRouter: ", routerAddress);
// 读取YTAssetFactory部署信息可选
let factoryAddress: string | undefined;
let firstVaultAddress: string | undefined;
if (fs.existsSync("./deployments-vault-system.json")) {
const vaultDeployment = JSON.parse(fs.readFileSync("./deployments-vault-system.json", "utf8"));
factoryAddress = vaultDeployment.contracts.YTAssetFactory.proxy;
console.log("YTAssetFactory: ", factoryAddress);
// 如果有创建的vault读取第一个作为wusdPriceSource
if (vaultDeployment.vaults && vaultDeployment.vaults.length > 0) {
firstVaultAddress = vaultDeployment.vaults[0].address;
console.log("第一个Vault: ", firstVaultAddress);
}
}
// 获取合约实例
const usdy = await ethers.getContractAt("USDY", usdyAddress);
const ytLP = await ethers.getContractAt("YTLPToken", ytLPAddress);
const priceFeed = await ethers.getContractAt("YTPriceFeed", priceFeedAddress);
const vault = await ethers.getContractAt("YTVault", vaultAddress);
const poolManager = await ethers.getContractAt("YTPoolManager", poolManagerAddress);
// ==================== 2. 配置权限 ====================
console.log("\n===== 2. 配置权限 =====");
// 配置USDY权限
console.log("配置USDY vault权限...");
await usdy.addVault(vaultAddress);
console.log(" ✅ 添加YTVault");
await usdy.addVault(poolManagerAddress);
console.log(" ✅ 添加YTPoolManager");
// 配置YTLPToken权限
console.log("配置YTLPToken minter权限...");
await ytLP.setMinter(poolManagerAddress, true);
console.log(" ✅ 设置YTPoolManager为minter");
// 配置Vault权限
console.log("配置YTVault权限...");
await vault.setPoolManager(poolManagerAddress);
console.log(" ✅ 设置PoolManager");
await vault.setSwapper(routerAddress, true);
console.log(" ✅ 添加Router为swapper");
// 配置PoolManager权限
console.log("配置YTPoolManager handler权限...");
await poolManager.setHandler(routerAddress, true);
console.log(" ✅ 添加Router为handler");
// ==================== 3. 配置YTPriceFeed ====================
console.log("\n===== 3. 配置YTPriceFeed =====");
// 设置WUSD价格来源如果有YTAssetVault
if (firstVaultAddress) {
console.log("设置WUSD价格来源...");
await priceFeed.setWusdPriceSource(firstVaultAddress);
console.log(" ✅ WUSD价格来源:", firstVaultAddress);
} else {
console.log(" ⚠️ 未找到YTAssetVault跳过WUSD价格来源设置");
console.log(" 💡 提示: 请在创建YTAssetVault后手动调用 priceFeed.setWusdPriceSource()");
}
// 设置keeper权限默认设置deployer为keeper
console.log("设置Keeper权限...");
await priceFeed.setKeeper(deployer.address, true);
console.log(" ✅ 添加Keeper:", deployer.address);
// 设置价格保护参数
console.log("设置价格保护参数...");
const maxPriceChangeBps = 500; // 5%
await priceFeed.setMaxPriceChangeBps(maxPriceChangeBps);
console.log(" ✅ 最大价格变动:", maxPriceChangeBps / 100, "%");
// ==================== 4. 配置YTVault参数 ====================
console.log("\n===== 4. 配置YTVault参数 =====");
// 设置动态费率(初始关闭)
console.log("设置动态费率...");
await vault.setDynamicFees(true);
console.log(" ✅ 动态费率: 开启");
// 设置最大滑点
console.log("设置最大滑点...");
const maxSwapSlippageBps = 1000; // 10%
await vault.setMaxSwapSlippageBps(maxSwapSlippageBps);
console.log(" ✅ 最大滑点:", maxSwapSlippageBps / 100, "%");
// ==================== 5. 配置YTPoolManager参数 ====================
console.log("\n===== 5. 配置YTPoolManager参数 =====");
// ==================== 6. 输出配置摘要 ====================
console.log("\n===== 配置完成!=====");
console.log("\n📋 权限配置:");
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
console.log("✅ USDY vaults: YTVault, YTPoolManager");
console.log("✅ YTLPToken minter: YTPoolManager");
console.log("✅ YTVault poolManager: YTPoolManager");
console.log("✅ YTVault swapper: YTRewardRouter");
console.log("✅ YTPoolManager handler: YTRewardRouter");
console.log("✅ YTPriceFeed keeper:", deployer.address);
if (firstVaultAddress) {
console.log("✅ YTPriceFeed wusdPriceSource:", firstVaultAddress);
}
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
console.log("\n📋 参数配置:");
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
console.log("✅ 动态费率: 开启");
console.log("✅ 最大滑点:", maxSwapSlippageBps / 100, "%");
console.log("✅ 最大价格变动:", maxPriceChangeBps / 100, "%");
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
// 保存配置信息
const configInfo = {
network: (await ethers.provider.getNetwork()).name,
chainId: (await ethers.provider.getNetwork()).chainId.toString(),
configurer: deployer.address,
timestamp: new Date().toISOString(),
configuration: {
permissions: {
usdyVaults: [vaultAddress, poolManagerAddress],
ytlpMinters: [poolManagerAddress],
vaultPoolManager: poolManagerAddress,
vaultSwappers: [routerAddress],
poolManagerHandlers: [routerAddress],
priceFeedKeepers: [deployer.address],
priceFeedWusdSource: firstVaultAddress || "未设置"
},
parameters: {
dynamicFees: true,
maxSwapSlippageBps,
maxPriceChangeBps
}
}
};
fs.writeFileSync(
"./deployments-ytlp-config.json",
JSON.stringify(configInfo, null, 2)
);
console.log("\n✅ 配置信息已保存到 deployments-ytlp-config.json");
console.log("\n💡 下一步:");
console.log("1. 通过YTAssetFactory创建YTAssetVault代币");
console.log("2. 将YTAssetVault添加到YTVault的白名单");
console.log("3. 为YTAssetVault设置价格");
console.log("4. 开始使用协议!");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,169 @@
import { ethers } from "hardhat";
import * as fs from "fs";
/**
* 将YTAssetVault添加到YTVault白名单并设置价格
*/
async function main() {
console.log("开始添加Vault到白名单...\n");
const [deployer] = await ethers.getSigners();
console.log("操作账户:", deployer.address);
// ==================== 1. 读取部署地址 ====================
console.log("\n===== 1. 读取部署地址 =====");
// 读取YTLp系统部署信息
const ytlpDeployment = JSON.parse(fs.readFileSync("./deployments-ytlp.json", "utf8"));
const priceFeedAddress = ytlpDeployment.contracts.YTPriceFeed.proxy;
const vaultAddress = ytlpDeployment.contracts.YTVault.proxy;
console.log("YTPriceFeed:", priceFeedAddress);
console.log("YTVault: ", vaultAddress);
// 读取YTAssetFactory部署信息
const vaultSystemDeployment = JSON.parse(fs.readFileSync("./deployments-vault-system.json", "utf8"));
const vaults = vaultSystemDeployment.vaults;
if (!vaults || vaults.length === 0) {
throw new Error("未找到YTAssetVault请先运行 createVault.ts");
}
console.log("\n找到", vaults.length, "个YTAssetVault:");
vaults.forEach((v: any, i: number) => {
console.log(` ${i + 1}. ${v.name} (${v.symbol}): ${v.address}`);
});
// 获取合约实例
const priceFeed = await ethers.getContractAt("YTPriceFeed", priceFeedAddress);
const vault = await ethers.getContractAt("YTVault", vaultAddress);
// ==================== 2. 添加到白名单 ====================
console.log("\n===== 2. 添加到白名单 =====");
// 配置参数(可根据需要调整)
// 注意:总权重 = 4000 + 3000 + 2000 = 9000
const whitelistParams = [
{
weight: 4000, // 4000/9000 = 44.44%
maxUsdyAmount: ethers.parseEther("45000000"), // 4500万
isStable: false
},
{
weight: 3000, // 3000/9000 = 33.33%
maxUsdyAmount: ethers.parseEther("35000000"), // 3500万
isStable: false
},
{
weight: 2000, // 2000/9000 = 22.22%
maxUsdyAmount: ethers.parseEther("25000000"), // 2500万
isStable: false
}
];
for (let i = 0; i < vaults.length && i < whitelistParams.length; i++) {
const v = vaults[i];
const params = whitelistParams[i];
console.log(`\n添加 ${v.name} (${v.symbol}) 到白名单...`);
const tx = await vault.setWhitelistedToken(
v.address,
18, // decimals
params.weight,
params.maxUsdyAmount,
params.isStable
);
await tx.wait();
console.log(" ✅ 权重:", params.weight);
console.log(" ✅ 最大USDY:", ethers.formatEther(params.maxUsdyAmount));
console.log(" ✅ 是否稳定币:", params.isStable);
}
// ==================== 3. 设置价格 ====================
console.log("\n===== 3. 设置价格 =====");
for (const v of vaults) {
console.log(`\n设置 ${v.name} (${v.symbol}) 价格...`);
// 使用vault中保存的初始价格已经是1e30精度直接使用
const price = v.ytPrice;
const tx = await priceFeed.forceUpdatePrice(
v.address,
price
);
await tx.wait();
console.log(" ✅ 价格已设置:", ethers.formatUnits(price, 30), "(精度1e30)");
}
// ==================== 4. 设置WUSD价格来源 ====================
console.log("\n===== 4. 设置WUSD价格来源 =====");
// 使用第一个vault作为WUSD价格来源
const firstVault = vaults[0];
console.log("设置WUSD价格来源为:", firstVault.name, firstVault.address);
const tx = await priceFeed.setWusdPriceSource(firstVault.address);
await tx.wait();
console.log(" ✅ WUSD价格来源已设置");
// ==================== 5. 验证配置 ====================
console.log("\n===== 5. 验证配置 =====");
for (const v of vaults) {
const isWhitelisted = await vault.whitelistedTokens(v.address);
const weight = await vault.tokenWeights(v.address);
const price = await priceFeed.getPrice(v.address, true);
console.log(`\n${v.name} (${v.symbol}):`);
console.log(" 白名单:", isWhitelisted ? "✅" : "❌");
console.log(" 权重:", weight.toString());
console.log(" 价格:", ethers.formatUnits(price, 30));
}
const totalWeight = await vault.totalTokenWeights();
console.log("\n总权重:", totalWeight.toString());
const wusdPriceSource = await priceFeed.wusdPriceSource();
console.log("WUSD价格来源:", wusdPriceSource);
// ==================== 6. 输出摘要 ====================
console.log("\n===== 配置完成!=====");
console.log("\n✅ 已添加", vaults.length, "个vault到白名单");
console.log("✅ 已为所有vault设置初始价格");
console.log("✅ 已设置WUSD价格来源");
console.log("\n💡 系统已就绪,可以开始使用!");
// 保存配置信息
const configInfo = {
timestamp: new Date().toISOString(),
operator: deployer.address,
whitelistedVaults: vaults.map((v: any, i: number) => ({
name: v.name,
symbol: v.symbol,
address: v.address,
weight: whitelistParams[i]?.weight || 0,
maxUsdyAmount: whitelistParams[i]?.maxUsdyAmount.toString() || "0",
price: v.ytPrice
})),
totalWeight: totalWeight.toString(),
wusdPriceSource: wusdPriceSource
};
fs.writeFileSync(
"./deployments-whitelist-config.json",
JSON.stringify(configInfo, null, 2)
);
console.log("\n✅ 白名单配置信息已保存到 deployments-whitelist-config.json");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,118 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 部署 Lending 借贷池系统
* 包含LendingFactory, Configurator, Lending 实现和代理
*/
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 deployments: any = {};
// ========== 第一阶段:部署工厂合约 ==========
console.log("📦 Phase 1: 部署 LendingFactory...");
const LendingFactory = await ethers.getContractFactory("LendingFactory");
const lendingFactory = await LendingFactory.deploy();
await lendingFactory.waitForDeployment();
const lendingFactoryAddress = await lendingFactory.getAddress();
console.log("✅ LendingFactory 已部署:", lendingFactoryAddress);
deployments.lendingFactory = lendingFactoryAddress;
// ========== 第二阶段:部署 Configurator ==========
console.log("\n📦 Phase 2: 部署 Configurator (UUPS 代理)...");
const Configurator = await ethers.getContractFactory("Configurator");
// 使用 upgrades 插件部署 UUPS 代理
const configurator = await upgrades.deployProxy(
Configurator,
[],
{
kind: "uups",
initializer: "initialize"
}
);
await configurator.waitForDeployment();
const configuratorProxyAddress = await configurator.getAddress();
console.log("✅ Configurator Proxy:", configuratorProxyAddress);
deployments.configuratorProxy = configuratorProxyAddress;
// 获取实现合约地址
const configuratorImplAddress = await upgrades.erc1967.getImplementationAddress(configuratorProxyAddress);
console.log("✅ Configurator Implementation:", configuratorImplAddress);
deployments.configuratorImpl = configuratorImplAddress;
console.log("✅ Configurator Owner:", await configurator.owner());
// ========== 第三阶段:部署 Lending 实现合约 ==========
console.log("\n📦 Phase 3: 通过工厂部署 Lending 实现合约...");
const deployTx = await lendingFactory.deploy();
const deployReceipt = await deployTx.wait();
// 使用 logs 和 interface.parseLog 解析事件
let lendingImplAddress;
for (const log of deployReceipt.logs) {
try {
const parsedLog = lendingFactory.interface.parseLog({
topics: [...log.topics],
data: log.data
});
if (parsedLog && parsedLog.name === 'LendingDeployed') {
lendingImplAddress = parsedLog.args.lending;
break;
}
} catch (e) {
// 忽略无法解析的日志
continue;
}
}
console.log("✅ Lending Implementation:", lendingImplAddress);
deployments.lendingImpl = lendingImplAddress;
// ========== 第四阶段:准备部署 Lending 代理 ==========
console.log("\n📦 Phase 4: 准备部署 Lending 代理(需要先配置参数)");
console.log("⚠️ 请运行配置脚本 08-configureLending.ts 来完成配置和代理部署");
// ========== 保存部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-lending.json");
const existingDeployments = fs.existsSync(deploymentsPath)
? JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"))
: {};
const network = await ethers.provider.getNetwork();
const chainId = network.chainId.toString();
existingDeployments[chainId] = {
...existingDeployments[chainId],
...deployments,
timestamp: new Date().toISOString(),
deployer: deployer.address
};
fs.writeFileSync(deploymentsPath, JSON.stringify(existingDeployments, null, 2));
console.log("\n💾 部署信息已保存到:", deploymentsPath);
// ========== 部署总结 ==========
console.log("\n🎉 部署总结:");
console.log("=====================================");
console.log("LendingFactory: ", deployments.lendingFactory);
console.log("Configurator (Proxy): ", deployments.configuratorProxy);
console.log("Configurator (Impl): ", deployments.configuratorImpl);
console.log("Lending (Impl): ", deployments.lendingImpl);
console.log("=====================================\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,197 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 配置 Lending 借贷池参数并部署代理
* 包含:设置工厂、配置市场参数、添加抵押资产、部署 Lending 代理
*/
async function main() {
const [deployer] = await ethers.getSigners();
console.log("\n==========================================");
console.log("⚙️ 配置 Lending 借贷池");
console.log("==========================================");
console.log("配置账户:", deployer.address, "\n");
// ========== 读取部署信息 ==========
const deploymentsPath = path.join(__dirname, "../../deployments-lending.json");
if (!fs.existsSync(deploymentsPath)) {
throw new Error("未找到部署信息文件,请先运行 07-deployLending.ts");
}
const network = await ethers.provider.getNetwork();
const chainId = network.chainId.toString();
const deployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"))[chainId];
if (!deployments) {
throw new Error(`未找到网络 ${chainId} 的部署信息`);
}
console.log("📋 使用已部署的合约:");
console.log(" LendingFactory:", deployments.lendingFactory);
console.log(" Configurator:", deployments.configuratorProxy);
console.log(" Lending Impl:", deployments.lendingImpl, "\n");
const configurator = await ethers.getContractAt("Configurator", deployments.configuratorProxy);
const lendingFactory = await ethers.getContractAt("LendingFactory", deployments.lendingFactory);
// ========== 第一阶段:配置外部代币和价格源 ==========
console.log("⚙️ Phase 1: 配置外部代币和价格源");
// 这里使用示例地址,实际部署时需要替换为真实地址
// 如果你已有 WUSD 等合约,请从部署文件中读取
const USDC = {
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // Mainnet USDC (示例)
decimals: 6
};
const WETH = {
address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // Mainnet WETH (示例)
decimals: 18
};
// 价格预言机地址(需要部署或使用 Chainlink
const usdcPriceFeed = "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6"; // Chainlink USDC/USD (示例)
const ethPriceFeed = "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"; // Chainlink ETH/USD (示例)
console.log(" 基础资产 (USDC):", USDC.address);
console.log(" 抵押资产 (WETH):", WETH.address);
console.log(" USDC 价格源:", usdcPriceFeed);
console.log(" ETH 价格源:", ethPriceFeed, "\n");
// ========== 第二阶段:准备配置参数 ==========
console.log("⚙️ Phase 2: 准备市场配置参数");
// 使用占位符地址作为 Lending 代理地址
const LENDING_PROXY_PLACEHOLDER = ethers.ZeroAddress;
const configuration = {
baseToken: USDC.address,
baseTokenPriceFeed: usdcPriceFeed,
// 利率模型参数年化利率18位精度
// 注意:这些年化利率会在 initialize 时自动转换为每秒利率
// 转换公式perSecondRate = perYearRate / 31,536,000
supplyKink: ethers.parseUnits("0.8", 18), // 80% 利用率拐点
supplyPerYearInterestRateSlopeLow: ethers.parseUnits("0.03", 18), // 3% APY
supplyPerYearInterestRateSlopeHigh: ethers.parseUnits("0.4", 18), // 40% APY
supplyPerYearInterestRateBase: ethers.parseUnits("0", 18), // 0% 基础
borrowKink: ethers.parseUnits("0.8", 18), // 80% 利用率拐点
borrowPerYearInterestRateSlopeLow: ethers.parseUnits("0.05", 18), // 5% APY
borrowPerYearInterestRateSlopeHigh: ethers.parseUnits("1.5", 18), // 150% APY
borrowPerYearInterestRateBase: ethers.parseUnits("0.015", 18), // 1.5% 基础
storeFrontPriceFactor: ethers.parseUnits("0.5", 18), // 50% 清算折扣
trackingIndexScale: ethers.parseUnits("1", 15), // 10^15 比例
baseBorrowMin: ethers.parseUnits("100", USDC.decimals), // 最小借 100 USDC
targetReserves: ethers.parseUnits("5000000", USDC.decimals), // 目标储备 500 万
assetConfigs: [
{
asset: WETH.address,
priceFeed: ethPriceFeed,
decimals: WETH.decimals,
borrowCollateralFactor: ethers.parseUnits("0.80", 18), // 80% LTV
liquidateCollateralFactor: ethers.parseUnits("0.85", 18), // 85% 清算线
liquidationFactor: ethers.parseUnits("0.95", 18), // 95% (配合 storeFrontPriceFactor 产生折扣)
supplyCap: ethers.parseUnits("100000", WETH.decimals) // 最多 10 万 ETH
}
]
};
console.log("✅ 配置参数已准备\n");
// ========== 第三阶段:设置工厂和配置 ==========
console.log("⚙️ Phase 3: 设置工厂和配置参数");
console.log(" 设置工厂合约...");
const setFactoryTx = await configurator.setFactory(LENDING_PROXY_PLACEHOLDER, deployments.lendingFactory);
await setFactoryTx.wait();
console.log(" ✅ 工厂已设置");
console.log(" 设置市场配置...");
const setConfigTx = await configurator.setConfiguration(LENDING_PROXY_PLACEHOLDER, configuration);
await setConfigTx.wait();
console.log(" ✅ 配置已设置\n");
// ========== 第四阶段:部署 Lending 代理 ==========
console.log("⚙️ Phase 4: 部署 Lending 代理");
console.log(" 获取配置信息...");
const config = await configurator.getConfiguration(LENDING_PROXY_PLACEHOLDER);
console.log(" 部署 Lending 代理...");
const Lending = await ethers.getContractFactory("Lending");
// 使用 upgrades 插件部署 UUPS 代理
const lending = await upgrades.deployProxy(
Lending,
[config],
{
kind: "uups",
initializer: "initialize"
}
);
await lending.waitForDeployment();
const lendingProxyAddress = await lending.getAddress();
console.log(" ✅ Lending Proxy 已部署:", lendingProxyAddress);
// 获取实现合约地址(验证)
const lendingImplAddress = await upgrades.erc1967.getImplementationAddress(lendingProxyAddress);
console.log(" ✅ Lending Implementation (验证):", lendingImplAddress, "\n");
// ========== 第五阶段:验证部署 ==========
console.log("✨ Phase 5: 验证部署");
console.log(" Lending Owner:", await lending.owner());
console.log(" Lending Paused:", await lending.paused());
console.log(" Base Token:", await lending.baseToken());
console.log(" Total Supply:", ethers.formatUnits(await lending.totalSupply(), USDC.decimals));
console.log(" Total Borrow:", ethers.formatUnits(await lending.totalBorrow(), USDC.decimals));
const supplyRate = await lending.getSupplyRate();
const borrowRate = await lending.getBorrowRate();
// 注意:返回的是每秒利率,需要乘以一年的秒数得到 APY
const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
console.log(" Supply Rate (per second):", ethers.formatUnits(supplyRate, 18));
console.log(" Supply APY:", ethers.formatUnits(BigInt(supplyRate) * BigInt(SECONDS_PER_YEAR), 18));
console.log(" Borrow Rate (per second):", ethers.formatUnits(borrowRate, 18));
console.log(" Borrow APY:", ethers.formatUnits(BigInt(borrowRate) * BigInt(SECONDS_PER_YEAR), 18), "\n");
// ========== 保存部署信息 ==========
deployments.lendingProxy = lendingProxyAddress;
deployments.configTimestamp = new Date().toISOString();
const allDeployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
allDeployments[chainId] = deployments;
fs.writeFileSync(deploymentsPath, JSON.stringify(allDeployments, null, 2));
console.log("💾 配置信息已保存到:", deploymentsPath);
// ========== 配置总结 ==========
console.log("\n🎉 配置总结:");
console.log("=====================================");
console.log("Lending Proxy: ", lendingProxyAddress);
console.log("Base Token: ", USDC.address);
console.log("Collateral Assets: ", configuration.assetConfigs.length);
console.log("Supply Kink: ", "80%");
console.log("Borrow Kink: ", "80%");
console.log("Min Borrow: ", "100 USDC");
console.log("=====================================\n");
console.log("✅ Lending 借贷池已完全配置完成!");
console.log("📝 后续步骤:");
console.log(" 1. 用户可以调用 supply() 存入 USDC");
console.log(" 2. 用户可以调用 supplyCollateral() 存入 WETH");
console.log(" 3. 用户可以调用 borrow() 借出 USDC");
console.log(" 4. 清算人可以调用 absorb() 清算不良贷款");
console.log(" 5. 清算人可以调用 buyCollateral() 购买清算抵押品\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,156 @@
import { ethers, upgrades } from "hardhat";
import * as fs from "fs";
import * as path from "path";
/**
* 升级 Lending 或 Configurator 合约
* 使用 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 deployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"))[chainId];
if (!deployments) {
throw new Error(`未找到网络 ${chainId} 的部署信息`);
}
console.log("📋 当前部署的合约:");
console.log(" Configurator Proxy:", deployments.configuratorProxy);
console.log(" Configurator Impl:", deployments.configuratorImpl);
console.log(" Lending Proxy:", deployments.lendingProxy);
console.log(" Lending Impl:", deployments.lendingImpl, "\n");
// ========== 选择要升级的合约 ==========
// 修改这里来选择升级 Lending 或 Configurator
const UPGRADE_LENDING = true; // true = 升级 Lending, false = 升级 Configurator
if (UPGRADE_LENDING) {
// ========== 升级 Lending ==========
console.log("🔄 Phase 1: 升级 Lending 合约");
if (!deployments.lendingProxy) {
throw new Error("未找到 Lending Proxy 地址,请先运行配置脚本");
}
console.log(" 当前 Lending Proxy:", deployments.lendingProxy);
console.log(" 当前 Lending Implementation:", deployments.lendingImpl);
// 获取新的 Lending 合约工厂
// 注意:如果你有 LendingV2请替换为 "LendingV2"
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());
// 保存新的实现地址
deployments.lendingImpl = newLendingImplAddress;
deployments.lendingUpgradeTimestamp = new Date().toISOString();
} else {
// ========== 升级 Configurator ==========
console.log("🔄 Phase 1: 升级 Configurator 合约");
console.log(" 当前 Configurator Proxy:", deployments.configuratorProxy);
console.log(" 当前 Configurator Implementation:", deployments.configuratorImpl);
// 获取新的 Configurator 合约工厂
// 注意:如果你有 ConfiguratorV2请替换为 "ConfiguratorV2"
const ConfiguratorV2 = await ethers.getContractFactory("Configurator");
console.log("\n 正在验证新实现合约...");
const upgradedConfigurator = await upgrades.upgradeProxy(
deployments.configuratorProxy,
ConfiguratorV2,
{
kind: "uups"
}
);
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());
// 保存新的实现地址
deployments.configuratorImpl = newConfiguratorImplAddress;
deployments.configuratorUpgradeTimestamp = new Date().toISOString();
}
// ========== 保存部署信息 ==========
const allDeployments = JSON.parse(fs.readFileSync(deploymentsPath, "utf-8"));
allDeployments[chainId] = deployments;
fs.writeFileSync(deploymentsPath, JSON.stringify(allDeployments, null, 2));
console.log("\n💾 升级信息已保存到:", deploymentsPath);
// ========== 升级总结 ==========
console.log("\n🎉 升级总结:");
console.log("=====================================");
if (UPGRADE_LENDING) {
console.log("升级合约: Lending");
console.log("Lending Proxy: ", deployments.lendingProxy);
console.log("新 Lending Implementation:", deployments.lendingImpl);
} else {
console.log("升级合约: Configurator");
console.log("Configurator Proxy: ", deployments.configuratorProxy);
console.log("新 Configurator Impl: ", deployments.configuratorImpl);
}
console.log("=====================================\n");
console.log("✅ 升级完成!");
console.log("⚠️ 重要提示:");
console.log(" 1. 代理地址保持不变,用户无需更改合约地址");
console.log(" 2. 所有状态数据已保留");
console.log(" 3. 建议在测试网充分测试后再升级主网\n");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});