375 lines
9.5 KiB
Markdown
375 lines
9.5 KiB
Markdown
|
|
# YT Lending 借贷池系统流程说明
|
|||
|
|
|
|||
|
|
## 系统概述
|
|||
|
|
|
|||
|
|
YT Lending 是基于 Compound V3 架构的简化借贷池系统,采用 OpenZeppelin UUPS 升级模式和 Ownable 权限管理。
|
|||
|
|
|
|||
|
|
### 核心特性
|
|||
|
|
|
|||
|
|
- ✅ **UUPS 可升级**:使用 OpenZeppelin 的 UUPS 代理模式
|
|||
|
|
- ✅ **简化权限**:使用 Owner 权限管理,替代复杂的 Governor 治理
|
|||
|
|
- ✅ **单一基础资产**:支持一种基础资产(如 USDC)的借贷
|
|||
|
|
- ✅ **多种抵押品**:支持多种抵押资产(如 ETH、WBTC)
|
|||
|
|
- ✅ **动态利率**:双拐点利率模型
|
|||
|
|
- ✅ **清算机制**:支持不良贷款清算和抵押品拍卖
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 合约架构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
├── Lending.sol # 核心借贷合约(UUPS)
|
|||
|
|
├── LendingFactory.sol # 工厂合约
|
|||
|
|
├── Configurator.sol # 配置管理合约(UUPS)
|
|||
|
|
├── LendingConfiguration.sol # 配置结构体
|
|||
|
|
├── LendingStorage.sol # 存储定义
|
|||
|
|
├── LendingMath.sol # 数学计算库
|
|||
|
|
├── ConfiguratorStorage.sol # 配置器存储
|
|||
|
|
└── interfaces/
|
|||
|
|
├── ILending.sol # 借贷接口
|
|||
|
|
└── IPriceFeed.sol # 价格预言机接口
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 部署流程
|
|||
|
|
|
|||
|
|
### 步骤 1: 部署基础合约
|
|||
|
|
|
|||
|
|
运行部署脚本:
|
|||
|
|
```bash
|
|||
|
|
npx hardhat run scripts/deploy/07-deployLending.ts --network <network>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
部署内容:
|
|||
|
|
1. **LendingFactory** - 工厂合约
|
|||
|
|
2. **Configurator Implementation** - 配置管理实现合约
|
|||
|
|
3. **Configurator Proxy** - 配置管理代理合约
|
|||
|
|
4. **Lending Implementation** - 借贷池实现合约
|
|||
|
|
|
|||
|
|
### 步骤 2: 配置市场参数
|
|||
|
|
|
|||
|
|
运行配置脚本:
|
|||
|
|
```bash
|
|||
|
|
npx hardhat run scripts/deploy/08-configureLending.ts --network <network>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
配置内容:
|
|||
|
|
1. 设置工厂合约地址
|
|||
|
|
2. 配置市场参数(利率模型、清算参数等)
|
|||
|
|
3. 添加抵押资产配置
|
|||
|
|
4. 部署 Lending Proxy 代理合约
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 配置参数说明
|
|||
|
|
|
|||
|
|
### 利率模型参数
|
|||
|
|
|
|||
|
|
| 参数 | 说明 | 示例值 |
|
|||
|
|
|------|------|--------|
|
|||
|
|
| `supplyKink` | 供应利率拐点(利用率) | 80% |
|
|||
|
|
| `supplyPerYearInterestRateSlopeLow` | 供应拐点前斜率 | 3% APY |
|
|||
|
|
| `supplyPerYearInterestRateSlopeHigh` | 供应拐点后斜率 | 40% APY |
|
|||
|
|
| `borrowKink` | 借款利率拐点(利用率) | 80% |
|
|||
|
|
| `borrowPerYearInterestRateSlopeLow` | 借款拐点前斜率 | 5% APY |
|
|||
|
|
| `borrowPerYearInterestRateSlopeHigh` | 借款拐点后斜率 | 150% APY |
|
|||
|
|
|
|||
|
|
### 抵押资产参数
|
|||
|
|
|
|||
|
|
| 参数 | 说明 | 示例值 |
|
|||
|
|
|------|------|--------|
|
|||
|
|
| `borrowCollateralFactor` | 借款抵押率(LTV) | 80% |
|
|||
|
|
| `liquidateCollateralFactor` | 清算抵押率 | 85% |
|
|||
|
|
| `liquidationFactor` | 清算激励 | 5% |
|
|||
|
|
| `supplyCap` | 供应上限 | 100,000 ETH |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 核心功能流程
|
|||
|
|
|
|||
|
|
### 1. 存款(Supply)
|
|||
|
|
|
|||
|
|
```solidity
|
|||
|
|
lending.supply(1000 * 1e6); // 存入 1000 USDC
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**流程**:
|
|||
|
|
1. 用户授权 USDC 给 Lending 合约
|
|||
|
|
2. 调用 `supply()` 存入 USDC
|
|||
|
|
3. 合约记录用户正余额
|
|||
|
|
4. 开始计息
|
|||
|
|
|
|||
|
|
### 2. 存入抵押品(Supply Collateral)
|
|||
|
|
|
|||
|
|
```solidity
|
|||
|
|
lending.supplyCollateral(WETH, 10 * 1e18); // 存入 10 ETH
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**流程**:
|
|||
|
|
1. 用户授权抵押品(如 WETH)给 Lending 合约
|
|||
|
|
2. 调用 `supplyCollateral()` 存入抵押品
|
|||
|
|
3. 合约记录用户抵押品余额
|
|||
|
|
|
|||
|
|
### 3. 借款(Borrow)
|
|||
|
|
|
|||
|
|
```solidity
|
|||
|
|
lending.borrow(5000 * 1e6); // 借出 5000 USDC
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**流程**:
|
|||
|
|
1. 用户已存入足够的抵押品
|
|||
|
|
2. 调用 `borrow()` 借出 USDC
|
|||
|
|
3. 合约检查抵押品是否充足(根据 borrowCollateralFactor)
|
|||
|
|
4. 用户余额变为负数(表示借款)
|
|||
|
|
5. 开始计息
|
|||
|
|
|
|||
|
|
**借款能力计算**:
|
|||
|
|
```
|
|||
|
|
借款能力 = Σ(抵押品价值 × borrowCollateralFactor)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 取出资产(Withdraw)
|
|||
|
|
|
|||
|
|
```solidity
|
|||
|
|
lending.withdraw(500 * 1e6); // 取出 500 USDC
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**流程**:
|
|||
|
|
1. 调用 `withdraw()` 取出 USDC
|
|||
|
|
2. 如果用户有借款,检查抵押品是否充足
|
|||
|
|
3. 转账 USDC 给用户
|
|||
|
|
|
|||
|
|
### 5. 取出抵押品(Withdraw Collateral)
|
|||
|
|
|
|||
|
|
```solidity
|
|||
|
|
lending.withdrawCollateral(WETH, 2 * 1e18); // 取出 2 ETH
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**流程**:
|
|||
|
|
1. 调用 `withdrawCollateral()` 取出抵押品
|
|||
|
|
2. 如果用户有借款,检查剩余抵押品是否充足
|
|||
|
|
3. 转账抵押品给用户
|
|||
|
|
|
|||
|
|
### 6. 清算(Absorb)
|
|||
|
|
|
|||
|
|
```solidity
|
|||
|
|
lending.absorb(borrowerAddress); // 清算借款人
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**触发条件**:
|
|||
|
|
```
|
|||
|
|
债务 > Σ(抵押品价值 × liquidateCollateralFactor)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**流程**:
|
|||
|
|
1. 清算人调用 `absorb()` 清算不良贷款
|
|||
|
|
2. 合约检查借款人是否可被清算
|
|||
|
|
3. 将借款人的债务清零
|
|||
|
|
4. 将借款人的抵押品转移到清算库存
|
|||
|
|
|
|||
|
|
### 7. 购买清算抵押品(Buy Collateral)
|
|||
|
|
|
|||
|
|
```solidity
|
|||
|
|
lending.buyCollateral(WETH, 1 * 1e18, 2000 * 1e6);
|
|||
|
|
// 用 2000 USDC 购买至少 1 ETH
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**流程**:
|
|||
|
|
1. 购买者调用 `buyCollateral()`
|
|||
|
|
2. 按折扣价(storeFrontPriceFactor)计算可购买的抵押品数量
|
|||
|
|
3. 转账 USDC 给合约
|
|||
|
|
4. 转账抵押品给购买者
|
|||
|
|
|
|||
|
|
**折扣价格计算**:
|
|||
|
|
```
|
|||
|
|
折扣价 = 市场价 × storeFrontPriceFactor
|
|||
|
|
可购买数量 = 支付 USDC 数量 / 折扣价
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 利率计算
|
|||
|
|
|
|||
|
|
### 利用率
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
利用率 = 总借款 / 总供应
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 双拐点利率模型
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
如果 利用率 <= Kink:
|
|||
|
|
利率 = 基础利率 + 利用率 × 低斜率
|
|||
|
|
|
|||
|
|
如果 利用率 > Kink:
|
|||
|
|
超额利用率 = 利用率 - Kink
|
|||
|
|
利率 = 基础利率 + 低斜率 + 超额利用率 × 高斜率
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**示例**(借款利率,Kink = 80%):
|
|||
|
|
|
|||
|
|
| 利用率 | 借款利率 |
|
|||
|
|
|--------|----------|
|
|||
|
|
| 0% | 1.5% |
|
|||
|
|
| 40% | 3.5% |
|
|||
|
|
| 80% | 5.5% |
|
|||
|
|
| 90% | 20.5% |
|
|||
|
|
| 100% | 35.5% |
|
|||
|
|
|
|||
|
|
### 利率计算优化(采用 Compound V3 方式)
|
|||
|
|
|
|||
|
|
**关键优化**:配置时传入年化利率,初始化时自动转换为每秒利率
|
|||
|
|
|
|||
|
|
```solidity
|
|||
|
|
// 初始化时(只计算一次)
|
|||
|
|
uint256 SECONDS_PER_YEAR = 31,536,000;
|
|||
|
|
supplyPerSecondRate = supplyPerYearRate / SECONDS_PER_YEAR;
|
|||
|
|
borrowPerSecondRate = borrowPerYearRate / SECONDS_PER_YEAR;
|
|||
|
|
|
|||
|
|
// 每次计提利息(高效计算)
|
|||
|
|
newIndex = oldIndex + (oldIndex * perSecondRate * timeElapsed) / 1e18;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**优化效果**:
|
|||
|
|
- ✅ 精度更高:每秒利率避免了重复除法导致的精度损失
|
|||
|
|
- ✅ Gas 更低:每次计提节省 ~100 gas(~66% Gas 优化)
|
|||
|
|
- ✅ 计算更快:只需乘法,无需除以 31,536,000
|
|||
|
|
- ✅ 完全兼容:配置文件仍使用易读的年化利率
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 权限管理
|
|||
|
|
|
|||
|
|
### Owner 权限
|
|||
|
|
|
|||
|
|
Owner(所有者)可以执行以下操作:
|
|||
|
|
|
|||
|
|
1. **升级合约**:调用 `upgradeTo()` 升级 Lending 或 Configurator
|
|||
|
|
2. **暂停/恢复**:调用 `pause()` / `unpause()` 暂停或恢复合约
|
|||
|
|
3. **配置市场**:通过 Configurator 修改市场参数
|
|||
|
|
4. **转移所有权**:调用 `transferOwnership()` 转移 Owner
|
|||
|
|
|
|||
|
|
### 推荐配置
|
|||
|
|
|
|||
|
|
建议使用多签钱包(如 Gnosis Safe)作为 Owner:
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 部署后转移所有权到多签
|
|||
|
|
await lending.transferOwnership(GNOSIS_SAFE_ADDRESS);
|
|||
|
|
await configurator.transferOwnership(GNOSIS_SAFE_ADDRESS);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 安全注意事项
|
|||
|
|
|
|||
|
|
### ⚠️ 关键风险
|
|||
|
|
|
|||
|
|
1. **价格预言机风险**:依赖外部价格源,需确保价格源可靠
|
|||
|
|
2. **清算延迟风险**:市场剧烈波动时可能来不及清算
|
|||
|
|
3. **Owner 权限过大**:Owner 拥有所有管理权限,需使用多签
|
|||
|
|
|
|||
|
|
### 🔒 安全建议
|
|||
|
|
|
|||
|
|
1. **使用多签钱包**:将 Owner 设为 Gnosis Safe 等多签钱包
|
|||
|
|
2. **设置合理参数**:
|
|||
|
|
- `borrowCollateralFactor` < `liquidateCollateralFactor`
|
|||
|
|
- 合理的清算折扣(storeFrontPriceFactor)
|
|||
|
|
- 适当的 supplyCap 防止单一资产风险过大
|
|||
|
|
3. **监控系统**:实时监控抵押率,及时清算
|
|||
|
|
4. **价格源多样化**:考虑使用多个价格源取平均
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 升级流程
|
|||
|
|
|
|||
|
|
### 使用 upgrades 插件升级(推荐)
|
|||
|
|
|
|||
|
|
运行升级脚本:
|
|||
|
|
```bash
|
|||
|
|
npx hardhat run scripts/deploy/09-upgradeLending.ts --network <network>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**脚本特性**:
|
|||
|
|
- ✅ 自动验证存储布局兼容性
|
|||
|
|
- ✅ 自动部署新实现合约
|
|||
|
|
- ✅ 自动更新代理指向
|
|||
|
|
- ✅ 保留所有状态数据
|
|||
|
|
|
|||
|
|
**修改升级目标**:
|
|||
|
|
```typescript
|
|||
|
|
// 在 09-upgradeLending.ts 中修改
|
|||
|
|
const UPGRADE_LENDING = true; // true = 升级 Lending, false = 升级 Configurator
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 手动 UUPS 升级步骤(不推荐)
|
|||
|
|
|
|||
|
|
如果需要手动升级:
|
|||
|
|
|
|||
|
|
1. **部署新实现合约**:
|
|||
|
|
```typescript
|
|||
|
|
const NewLending = await ethers.getContractFactory("LendingV2");
|
|||
|
|
const newImpl = await NewLending.deploy();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **升级代理**:
|
|||
|
|
```typescript
|
|||
|
|
await lending.upgradeTo(newImpl.address);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 注意事项
|
|||
|
|
|
|||
|
|
- ✅ 只有 Owner 可以升级
|
|||
|
|
- ✅ 必须保持存储布局一致
|
|||
|
|
- ✅ 只能在末尾添加新存储变量
|
|||
|
|
- ⚠️ 升级前在测试网充分测试
|
|||
|
|
- 🔧 推荐使用 upgrades 插件,它会自动验证兼容性
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 监控指标
|
|||
|
|
|
|||
|
|
### 关键指标
|
|||
|
|
|
|||
|
|
1. **利用率**:`totalBorrow / totalSupply`
|
|||
|
|
2. **供应利率**:`getSupplyRate()`
|
|||
|
|
3. **借款利率**:`getBorrowRate()`
|
|||
|
|
4. **储备金**:`reserves`
|
|||
|
|
5. **清算库存**:`collateralReserves[asset]`
|
|||
|
|
|
|||
|
|
### 健康检查
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 检查利用率
|
|||
|
|
const utilization = totalBorrow.mul(1e18).div(totalSupply);
|
|||
|
|
console.log("Utilization:", utilization / 1e18 * 100, "%");
|
|||
|
|
|
|||
|
|
// 检查是否需要清算
|
|||
|
|
const isLiquidatable = await lending.isLiquidatable(userAddress);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 总结
|
|||
|
|
|
|||
|
|
YT Lending 提供了一个简化但功能完整的借贷池系统:
|
|||
|
|
|
|||
|
|
- ✅ 核心借贷功能(存款、借款、抵押品管理)
|
|||
|
|
- ✅ 清算机制(absorb + buyCollateral)
|
|||
|
|
- ✅ 动态利率模型(双拐点)
|
|||
|
|
- ✅ 可升级架构(UUPS)
|
|||
|
|
- ✅ 简化权限管理(Owner)
|
|||
|
|
|
|||
|
|
**适用场景**:
|
|||
|
|
- 中小型借贷协议
|
|||
|
|
- 需要快速上线的项目
|
|||
|
|
- 中心化或半中心化管理的借贷池
|
|||
|
|
|
|||
|
|
**限制**:
|
|||
|
|
- 单一基础资产(只能借贷一种资产)
|
|||
|
|
- 简化的权限模型(不支持 DAO 治理)
|
|||
|
|
- 需要可靠的价格预言机
|
|||
|
|
|