Files
assetxContracts/doc/YT资产金库系统操作流程图.md
2025-12-18 13:07:35 +08:00

1554 lines
129 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# YT资产金库系统操作流程图
## 目录
1. [创建Vault流程](#1-创建vault流程)
2. [用户存款流程depositYT](#2-用户存款流程deposityt)
3. [用户提款流程withdrawYT](#3-用户提款流程withdrawyt)
4. [价格更新流程](#4-价格更新流程)
5. [资产管理流程 - 提取投资](#5-资产管理流程---提取投资)
6. [资产管理流程 - 归还资产](#6-资产管理流程---归还资产)
7. [批量操作流程](#7-批量操作流程)
8. [查询信息流程](#8-查询信息流程)
9. [暂停功能流程](#9-暂停功能流程)
---
## 1. 创建Vault流程
```
┌─────────────────────────────────────────────────────────────────────┐
│ Owner (系统管理员) │
└────────────────────────────┬────────────────────────────────────────┘
│ 1. 调用 createVault()
│ name: "YT-A Token"
│ symbol: "YT-A"
│ manager: 0x123...
│ hardCap: 1,000,000 YT
│ wusd: 0x7Cd...或0使用默认
│ redemptionTime: 2025-02-15 00:00:00
│ initialWusdPrice: 1.05e30
│ initialYtPrice: 1.05e30
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetFactory.sol │
│ ───────────────────────────────────────────────────────────────── │
│ function createVault(...) │
│ │
│ 权限检查: │
│ ✓ onlyOwner - 只有Factory owner可以创建 │
│ ✓ manager != address(0) - 管理员地址有效 │
└────────────────────────────┬────────────────────────────────────────┘
│ 2. 确定硬顶值
│ _hardCap == 0 ? defaultHardCap : _hardCap
│ → 使用传入的 1,000,000 YT
┌─────────────────────────────────────────────────────────────────────┐
│ 编码初始化数据 │
│ ───────────────────────────────────────────────────────────────── │
│ bytes memory initData = abi.encodeWithSelector( │
│ YTAssetVault.initialize.selector, │
│ "YT-A Token", │
│ "YT-A", │
│ 0x123..., // manager │
│ 1000000e18, // hardCap │
│ 0x7Cd..., // wusd │
│ 1739577600, // redemptionTime (Unix时间戳) │
│ 1050000000000000000000000000000, // 1.05e30 │
│ 1050000000000000000000000000000 // 1.05e30 │
│ ) │
└────────────────────────────┬────────────────────────────────────────┘
│ 3. 部署ERC1967代理合约
│ new ERC1967Proxy(vaultImplementation, initData)
┌─────────────────────────────────────────────────────────────────────┐
│ 部署并初始化YTAssetVault │
│ ───────────────────────────────────────────────────────────────── │
│ 新合约地址: 0xVault001... │
│ │
│ ① __ERC20_init("YT-A Token", "YT-A") │
│ • 初始化ERC20代币 │
│ • name: "YT-A Token" │
│ • symbol: "YT-A" │
│ • decimals: 18 │
│ │
│ ② __UUPSUpgradeable_init() │
│ • 初始化UUPS升级模式 │
│ │
│ ③ __ReentrancyGuard_init() │
│ • 初始化重入保护 │
│ │
│ ④ 设置基本参数 │
│ factory = msg.sender (YTAssetFactory地址) │
│ manager = 0x123... │
│ hardCap = 1,000,000 * 1e18 │
│ wusdAddress = 0x7Cd... │
│ │
│ ⑤ __Pausable_init() │
│ • 初始化暂停功能(默认未暂停) │
│ │
│ ⑥ 设置价格精度1e30
│ wusdPrice = 1.05e30 (初始价格1.05) │
│ ytPrice = 1.05e30 (初始价格1.05) │
│ │
│ ⑦ 设置赎回时间 │
│ nextRedemptionTime = 1739577600 (2025-02-15) │
└────────────────────────────┬────────────────────────────────────────┘
│ 4. 记录到Factory
┌─────────────────────────────────────────────────────────────────────┐
│ Factory状态更新 │
│ ───────────────────────────────────────────────────────────────── │
│ allVaults.push(0xVault001...) │
│ isVault[0xVault001...] = true │
│ │
│ 触发事件: │
│ emit VaultCreated( │
│ 0xVault001..., │
│ 0x123..., // manager │
│ "YT-A Token", │
│ "YT-A", │
│ 1000000e18, // hardCap │
│ 0 // index │
│ ) │
└────────────────────────────┬────────────────────────────────────────┘
│ 5. 返回vault地址
┌─────────────────────────────────────────────────────────────────────┐
│ 创建完成 │
│ ───────────────────────────────────────────────────────────────── │
│ 返回值: 0xVault001... │
│ │
│ Vault状态
│ • totalSupply: 0 │
│ • totalAssets: 0 WUSD │
│ • wusdPrice: 1.05 (精度1e30) │
│ • ytPrice: 1.05 (精度1e30) │
│ • hardCap: 1,000,000 YT │
│ • nextRedemptionTime: 2025-02-15 00:00:00 │
│ • 可接受用户存款 ✓ │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 2. 用户存款流程depositYT
```
┌─────────────────────────────────────────────────────────────────────┐
│ 用户 (User) │
│ 持有: 10,000 WUSD │
└────────────────────────────┬────────────────────────────────────────┘
│ 0. 预览操作(可选)
│ 调用 previewBuy(10000e18)
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetVault.sol │
│ ───────────────────────────────────────────────────────────────── │
│ function previewBuy(10000e18) returns (uint256 ytAmount) │
│ │
│ 计算逻辑: │
│ ytAmount = (wusdAmount × wusdPrice) ÷ ytPrice │
│ = (10,000 × 1.05e30) ÷ 1.05e30 │
│ = 10,000 YT │
│ │
│ 返回预览结果: 10,000 YT │
└─────────────────────────────────────────────────────────────────────┘
│ 1. 授权WUSD给Vault
│ WUSD.approve(vault, 10000e18)
┌─────────────────────────────────────────────────────────────────────┐
│ WUSD授权检查 │
│ ✓ allowance[user][vault] >= 10,000 WUSD │
└────────────────────────────┬────────────────────────────────────────┘
│ 2. 调用 depositYT(10000e18)
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetVault.depositYT() │
│ ───────────────────────────────────────────────────────────────── │
│ function depositYT(uint256 _wusdAmount) │
│ • 非重入保护: nonReentrant │
│ • 暂停检查: whenNotPaused │
│ • 参数: 10,000 WUSD │
└────────────────────────────┬────────────────────────────────────────┘
│ 3. 参数验证
┌─────────────────────────────────────────────────────────────────────┐
│ 参数检查 │
│ ───────────────────────────────────────────────────────────────── │
│ ① _wusdAmount > 0 │
│ ✓ 10,000 > 0 通过 │
└────────────────────────────┬────────────────────────────────────────┘
│ 4. 计算可获得的YT数量
┌─────────────────────────────────────────────────────────────────────┐
│ 计算YT数量 │
│ ───────────────────────────────────────────────────────────────── │
│ 公式ytAmount = (wusdAmount × wusdPrice) ÷ ytPrice │
│ │
│ 当前价格: │
│ • wusdPrice = 1.05e30 │
│ • ytPrice = 1.05e30 │
│ │
│ 计算过程: │
│ ytAmount = (10,000e18 × 1.05e30) ÷ 1.05e30 │
│ = 10,000e18 │
│ = 10,000 YT │
└────────────────────────────┬────────────────────────────────────────┘
│ 5. 检查硬顶限制
┌─────────────────────────────────────────────────────────────────────┐
│ 硬顶检查 │
│ ───────────────────────────────────────────────────────────────── │
│ if (hardCap > 0 && totalSupply() + ytAmount > hardCap) │
│ revert HardCapExceeded() │
│ │
│ 当前状态: │
│ • hardCap = 1,000,000 YT │
│ • totalSupply() = 0 YT (首次存款) │
│ • ytAmount = 10,000 YT │
│ • 0 + 10,000 = 10,000 ≤ 1,000,000 ✓ 通过 │
└────────────────────────────┬────────────────────────────────────────┘
│ 6. 转入WUSDCEI模式 - Checks完成
┌─────────────────────────────────────────────────────────────────────┐
│ 代币转移Effects
│ ───────────────────────────────────────────────────────────────── │
│ IERC20(wusdAddress).safeTransferFrom( │
│ msg.sender, // 用户地址 │
│ address(this), // Vault地址 │
│ 10000e18 // 转入10,000 WUSD │
│ ) │
│ │
│ 结果: │
│ • 用户WUSD余额: 10,000 → 0 │
│ • Vault WUSD余额: 0 → 10,000 │
└────────────────────────────┬────────────────────────────────────────┘
│ 7. 铸造YT代币给用户
┌─────────────────────────────────────────────────────────────────────┐
│ 铸造YT代币 │
│ ───────────────────────────────────────────────────────────────── │
│ _mint(msg.sender, 10000e18) │
│ │
│ ERC20铸造
│ • balanceOf[user] += 10,000 YT │
│ • totalSupply += 10,000 YT │
│ │
│ 结果: │
│ • 用户YT余额: 0 → 10,000 YT │
│ • 总供应量: 0 → 10,000 YT │
└────────────────────────────┬────────────────────────────────────────┘
│ 8. 触发事件
┌─────────────────────────────────────────────────────────────────────┐
│ 事件记录Interactions
│ ───────────────────────────────────────────────────────────────── │
│ emit Buy( │
│ msg.sender, // 用户地址 │
│ 10000e18, // WUSD数量 │
│ 10000e18 // YT数量 │
│ ) │
└────────────────────────────┬────────────────────────────────────────┘
│ 9. 返回YT数量
┌─────────────────────────────────────────────────────────────────────┐
│ 存款完成 │
│ ───────────────────────────────────────────────────────────────── │
│ 用户最终状态: │
│ • WUSD余额: 0 │
│ • YT余额: 10,000 YT │
│ │
│ Vault最终状态
│ • totalSupply: 10,000 YT │
│ • totalAssets: 10,000 WUSD │
│ • idleAssets: 10,000 WUSD │
│ • managedAssets: 0 WUSD │
│ │
│ 返回值: 10,000 YT │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 3. 用户提款流程withdrawYT
```
┌─────────────────────────────────────────────────────────────────────┐
│ 用户 (User) │
│ 持有: 5,000 YT │
└────────────────────────────┬────────────────────────────────────────┘
│ 0. 预览操作(可选)
│ 调用 previewSell(5000e18)
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetVault.sol │
│ ───────────────────────────────────────────────────────────────── │
│ function previewSell(5000e18) returns (uint256 wusdAmount) │
│ │
│ 计算逻辑: │
│ wusdAmount = (ytAmount × ytPrice) ÷ wusdPrice │
│ = (5,000 × 1.05e30) ÷ 1.05e30 │
│ = 5,000 WUSD │
│ │
│ 返回预览结果: 5,000 WUSD │
└─────────────────────────────────────────────────────────────────────┘
│ 1. 检查赎回时间(可选)
│ 调用 canRedeemNow()
┌─────────────────────────────────────────────────────────────────────┐
│ 赎回时间检查 │
│ ───────────────────────────────────────────────────────────────── │
│ function canRedeemNow() returns (bool) │
│ return block.timestamp >= nextRedemptionTime │
│ │
│ 检查: │
│ • 当前时间: 2025-02-16 10:00:00 (1739692800) │
│ • 赎回时间: 2025-02-15 00:00:00 (1739577600) │
│ • 1739692800 >= 1739577600 ✓ 可以赎回 │
│ │
│ getTimeUntilNextRedemption() = 0 秒 │
└─────────────────────────────────────────────────────────────────────┘
│ 2. 调用 withdrawYT(5000e18)
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetVault.withdrawYT() │
│ ───────────────────────────────────────────────────────────────── │
│ function withdrawYT(uint256 _ytAmount) │
│ • 非重入保护: nonReentrant │
│ • 暂停检查: whenNotPaused │
│ • 参数: 5,000 YT │
└────────────────────────────┬────────────────────────────────────────┘
│ 3. 多重验证
┌─────────────────────────────────────────────────────────────────────┐
│ 参数检查 │
│ ───────────────────────────────────────────────────────────────── │
│ ① _ytAmount > 0 │
│ ✓ 5,000 > 0 通过 │
│ │
│ ② balanceOf(msg.sender) >= _ytAmount │
│ ✓ 10,000 >= 5,000 通过 │
│ (用户持有足够的YT) │
│ │
│ ③ block.timestamp >= nextRedemptionTime │
│ ✓ 2025-02-16 >= 2025-02-15 通过 │
│ (已到赎回时间) │
└────────────────────────────┬────────────────────────────────────────┘
│ 4. 计算可获得的WUSD数量
┌─────────────────────────────────────────────────────────────────────┐
│ 计算WUSD数量 │
│ ───────────────────────────────────────────────────────────────── │
│ 公式wusdAmount = (ytAmount × ytPrice) ÷ wusdPrice │
│ │
│ 假设价格已更新: │
│ • wusdPrice = 1.00e30 (WUSD价格回落到1.0) │
│ • ytPrice = 1.10e30 (YT价格上涨到1.1) │
│ │
│ 计算过程: │
│ wusdAmount = (5,000e18 × 1.10e30) ÷ 1.00e30 │
│ = (5,000e18 × 1.10) ÷ 1.00 │
│ = 5,500e18 │
│ = 5,500 WUSD │
│ │
│ 用户获得收益: 5,500 - 5,000 = 500 WUSD (10%增值) │
└────────────────────────────┬────────────────────────────────────────┘
│ 5. 检查Vault流动性
┌─────────────────────────────────────────────────────────────────────┐
│ 流动性检查 │
│ ───────────────────────────────────────────────────────────────── │
│ uint256 availableWUSD = IERC20(wusdAddress).balanceOf(vault) │
│ if (wusdAmount > availableWUSD) revert InsufficientWUSD() │
│ │
│ 当前状态: │
│ • Vault中WUSD余额: 10,000 WUSD │
│ • 需要支付: 5,500 WUSD │
│ • 5,500 ≤ 10,000 ✓ 流动性充足 │
│ │
│ 注意: │
│ 如果manager已提取部分资金进行投资availableWUSD可能不足 │
│ 此时用户需要等待manager归还资金 │
└────────────────────────────┬────────────────────────────────────────┘
│ 6. 销毁用户的YTCEI - Effects
┌─────────────────────────────────────────────────────────────────────┐
│ 销毁YT代币 │
│ ───────────────────────────────────────────────────────────────── │
│ _burn(msg.sender, 5000e18) │
│ │
│ ERC20销毁
│ • balanceOf[user] -= 5,000 YT │
│ • totalSupply -= 5,000 YT │
│ │
│ 结果: │
│ • 用户YT余额: 10,000 → 5,000 YT │
│ • 总供应量: 10,000 → 5,000 YT │
└────────────────────────────┬────────────────────────────────────────┘
│ 7. 转出WUSD给用户
┌─────────────────────────────────────────────────────────────────────┐
│ 代币转移Interactions
│ ───────────────────────────────────────────────────────────────── │
│ IERC20(wusdAddress).safeTransfer( │
│ msg.sender, // 用户地址 │
│ 5500e18 // 转出5,500 WUSD │
│ ) │
│ │
│ 结果: │
│ • Vault WUSD余额: 10,000 → 4,500 │
│ • 用户WUSD余额: 0 → 5,500 │
└────────────────────────────┬────────────────────────────────────────┘
│ 8. 触发事件
┌─────────────────────────────────────────────────────────────────────┐
│ 事件记录 │
│ ───────────────────────────────────────────────────────────────── │
│ emit Sell( │
│ msg.sender, // 用户地址 │
│ 5000e18, // YT数量 │
│ 5500e18 // WUSD数量 │
│ ) │
└────────────────────────────┬────────────────────────────────────────┘
│ 9. 返回WUSD数量
┌─────────────────────────────────────────────────────────────────────┐
│ 提款完成 │
│ ───────────────────────────────────────────────────────────────── │
│ 用户最终状态: │
│ • YT余额: 5,000 YT (剩余) │
│ • WUSD余额: 5,500 WUSD (获得) │
│ • 收益: 500 WUSD (10%增值) │
│ │
│ Vault最终状态
│ • totalSupply: 5,000 YT │
│ • totalAssets: 4,500 WUSD (假设无managedAssets) │
│ • idleAssets: 4,500 WUSD │
│ │
│ 返回值: 5,500 WUSD │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 4. 价格更新流程
```
┌─────────────────────────────────────────────────────────────────────┐
│ Oracle / Manager │
│ 接收到最新价格数据: │
│ • WUSD价格: $1.02 │
│ • YT-A价格: $1.15 │
└────────────────────────────┬────────────────────────────────────────┘
│ 方式1: Manager直接更新
│ 调用 vault.updatePrices()
│ 方式2: Factory批量更新
│ 调用 factory.updateVaultPrices()
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetVault.updatePrices() │
│ ───────────────────────────────────────────────────────────────── │
│ function updatePrices( │
│ uint256 _wusdPrice, // 1.02e30 │
│ uint256 _ytPrice // 1.15e30 │
│ ) external onlyManager │
│ │
│ 权限检查: │
│ • msg.sender == manager ✓ 或 │
│ • msg.sender == factory ✓ │
└────────────────────────────┬────────────────────────────────────────┘
│ 1. 价格验证
┌─────────────────────────────────────────────────────────────────────┐
│ 价格有效性检查 │
│ ───────────────────────────────────────────────────────────────── │
│ if (_wusdPrice == 0 || _ytPrice == 0) │
│ revert InvalidPrice() │
│ │
│ 检查: │
│ • _wusdPrice = 1.02e30 ≠ 0 ✓ │
│ • _ytPrice = 1.15e30 ≠ 0 ✓ │
│ │
│ 注意: │
│ • 价格必须 > 0 │
│ • 价格精度为1e30 │
│ • 没有时间间隔限制,可随时更新 │
└────────────────────────────┬────────────────────────────────────────┘
│ 2. 更新价格状态
┌─────────────────────────────────────────────────────────────────────┐
│ 更新存储状态 │
│ ───────────────────────────────────────────────────────────────── │
│ wusdPrice = _wusdPrice │
│ ytPrice = _ytPrice │
│ │
│ 更新前: │
│ • wusdPrice: 1.05e30 → 1.02e30 (下降2.86%) │
│ • ytPrice: 1.05e30 → 1.15e30 (上涨9.52%) │
│ │
│ 影响: │
│ ① 后续depositYT计算变化 │
│ ytAmount = wusdAmount × 1.02 / 1.15 │
│ → 用户用相同WUSD获得更少YT │
│ │
│ ② 后续withdrawYT计算变化 │
│ wusdAmount = ytAmount × 1.15 / 1.02 │
│ → 用户用相同YT获得更多WUSD │
└────────────────────────────┬────────────────────────────────────────┘
│ 3. 触发事件
┌─────────────────────────────────────────────────────────────────────┐
│ 事件记录 │
│ ───────────────────────────────────────────────────────────────── │
│ emit PriceUpdated( │
│ 1020000000000000000000000000000, // wusdPrice │
│ 1150000000000000000000000000000, // ytPrice │
│ 1739692800 // timestamp │
│ ) │
│ │
│ 链下监听: │
│ • 前端可监听此事件更新UI显示 │
│ • 用户可看到最新的兑换比率 │
└────────────────────────────┬────────────────────────────────────────┘
│ 4. 完成更新
┌─────────────────────────────────────────────────────────────────────┐
│ 更新完成 │
│ ───────────────────────────────────────────────────────────────── │
│ 当前兑换比率示例: │
│ │
│ 存款 (depositYT): │
│ • 1,000 WUSD → (1,000 × 1.02) / 1.15 = 886.96 YT │
│ │
│ 提款 (withdrawYT): │
│ • 1,000 YT → (1,000 × 1.15) / 1.02 = 1,127.45 WUSD │
│ │
│ YT持有者收益
│ • 价格从1.05到1.15增值9.52% │
│ • 持有1,000 YT相当于价值1,127.45 WUSD │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 5. 资产管理流程 - 提取投资
```
┌─────────────────────────────────────────────────────────────────────┐
│ Manager (资产管理员) │
│ 计划: 提取50,000 WUSD进行外部投资 │
└────────────────────────────┬────────────────────────────────────────┘
│ 1. 调用 withdrawForManagement()
│ _to: manager地址
│ _amount: 50,000 WUSD
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetVault.withdrawForManagement() │
│ ───────────────────────────────────────────────────────────────── │
│ function withdrawForManagement( │
│ address _to, // 0x123... (manager) │
│ uint256 _amount // 50,000 WUSD │
│ ) external onlyManager nonReentrant whenNotPaused │
│ │
│ 权限检查: │
│ ✓ onlyManager - 只有manager可调用 │
│ ✓ nonReentrant - 重入保护 │
│ ✓ whenNotPaused - 暂停检查 │
└────────────────────────────┬────────────────────────────────────────┘
│ 2. 参数验证
┌─────────────────────────────────────────────────────────────────────┐
│ 验证检查 │
│ ───────────────────────────────────────────────────────────────── │
│ ① if (_amount == 0) revert InvalidAmount() │
│ ✓ 50,000 > 0 通过 │
│ │
│ ② uint256 availableAssets = vault.balance(WUSD) │
│ if (_amount > availableAssets) revert InvalidAmount() │
│ │
│ Vault当前状态
│ • totalAssets: 100,000 WUSD │
│ • idleAssets: 100,000 WUSD (全部在vault中) │
│ • managedAssets: 0 WUSD │
│ │
│ 检查: │
│ • availableAssets = 100,000 WUSD │
│ • 50,000 ≤ 100,000 ✓ 通过 │
└────────────────────────────┬────────────────────────────────────────┘
│ 3. 更新managedAssetsCEI - Effects
┌─────────────────────────────────────────────────────────────────────┐
│ 状态更新 │
│ ───────────────────────────────────────────────────────────────── │
│ managedAssets += _amount │
│ │
│ 更新: │
│ • managedAssets: 0 → 50,000 WUSD │
│ │
│ 重要说明: │
│ managedAssets记录了被管理员提取、正在进行外部投资的WUSD数量 │
│ 这部分资产不在vault合约中但仍计入totalAssets │
└────────────────────────────┬────────────────────────────────────────┘
│ 4. 转出WUSDInteractions
┌─────────────────────────────────────────────────────────────────────┐
│ 代币转移 │
│ ───────────────────────────────────────────────────────────────── │
│ IERC20(wusdAddress).safeTransfer( │
│ _to, // manager地址 │
│ 50000e18 // 50,000 WUSD │
│ ) │
│ │
│ 转账结果: │
│ • Vault WUSD余额: 100,000 → 50,000 WUSD │
│ • Manager WUSD余额: +50,000 WUSD │
└────────────────────────────┬────────────────────────────────────────┘
│ 5. 触发事件
┌─────────────────────────────────────────────────────────────────────┐
│ 事件记录 │
│ ───────────────────────────────────────────────────────────────── │
│ emit AssetsWithdrawn( │
│ 0x123..., // manager地址 │
│ 50000e18 // 提取数量 │
│ ) │
└────────────────────────────┬────────────────────────────────────────┘
│ 6. 提取完成
┌─────────────────────────────────────────────────────────────────────┐
│ 提取完成 │
│ ───────────────────────────────────────────────────────────────── │
│ Vault最终状态
│ • totalAssets(): 100,000 WUSD (不变!) │
│ 计算: idleAssets + managedAssets │
│ = 50,000 + 50,000 = 100,000 │
│ │
│ • idleAssets(): 50,000 WUSD │
│ (vault合约实际持有的WUSD) │
│ │
│ • managedAssets: 50,000 WUSD │
│ (manager正在管理的WUSD) │
│ │
│ • totalSupply: 100,000 YT (不变) │
│ │
│ 用户影响: │
│ ✓ totalAssets不变YT价值不受影响 │
│ ✓ 用户依然持有相同价值的YT份额 │
│ ✗ 暂时无法提款流动性不足需等待manager归还 │
│ │
│ Manager后续操作
│ → 用50,000 WUSD进行DeFi投资 │
│ → 赚取收益 │
│ → 通过depositManagedAssets归还 │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 6. 资产管理流程 - 归还资产
```
┌─────────────────────────────────────────────────────────────────────┐
│ Manager (资产管理员) │
│ 投资收益情况: │
│ • 提取: 50,000 WUSD │
│ • 投资收益: +5,000 WUSD │
│ • 准备归还: 55,000 WUSD (本金+利润) │
└────────────────────────────┬────────────────────────────────────────┘
│ 1. 授权WUSD给Vault
│ WUSD.approve(vault, 55000e18)
┌─────────────────────────────────────────────────────────────────────┐
│ WUSD授权检查 │
│ ✓ allowance[manager][vault] >= 55,000 WUSD │
└────────────────────────────┬────────────────────────────────────────┘
│ 2. 调用 depositManagedAssets()
│ _amount: 55,000 WUSD
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetVault.depositManagedAssets() │
│ ───────────────────────────────────────────────────────────────── │
│ function depositManagedAssets( │
│ uint256 _amount // 55,000 WUSD │
│ ) external onlyManager nonReentrant whenNotPaused │
│ │
│ 权限检查: │
│ ✓ onlyManager - 只有manager可调用 │
│ ✓ nonReentrant - 重入保护 │
│ ✓ whenNotPaused - 暂停检查 │
└────────────────────────────┬────────────────────────────────────────┘
│ 3. 参数验证
┌─────────────────────────────────────────────────────────────────────┐
│ 验证检查 │
│ ───────────────────────────────────────────────────────────────── │
│ if (_amount == 0) revert InvalidAmount() │
│ ✓ 55,000 > 0 通过 │
│ │
│ 当前Vault状态
│ • idleAssets: 50,000 WUSD │
│ • managedAssets: 50,000 WUSD │
│ • totalAssets: 100,000 WUSD │
└────────────────────────────┬────────────────────────────────────────┘
│ 4. 更新managedAssetsCEI - Effects
┌─────────────────────────────────────────────────────────────────────┐
│ 状态更新(关键逻辑) │
│ ───────────────────────────────────────────────────────────────── │
│ if (_amount >= managedAssets) { │
│ // 归还金额 >= 提取金额清零managedAssets │
│ managedAssets = 0 │
│ } else { │
│ // 归还金额 < 提取金额,部分归还 │
│ managedAssets -= _amount │
│ } │
│ │
│ 本例计算: │
│ • _amount = 55,000 WUSD │
│ • managedAssets = 50,000 WUSD │
│ • 55,000 >= 50,000 ✓ 进入第一个分支 │
│ • managedAssets = 0 │
│ │
│ 多余的5,000 WUSD如何处理
│ → 自动增加到vault余额成为利润 │
│ → totalAssets会增加 │
│ → 所有YT持有者共享这部分收益 │
└────────────────────────────┬────────────────────────────────────────┘
│ 5. 转入WUSDInteractions
┌─────────────────────────────────────────────────────────────────────┐
│ 代币转移 │
│ ───────────────────────────────────────────────────────────────── │
│ IERC20(wusdAddress).safeTransferFrom( │
│ msg.sender, // manager地址 │
│ address(this), // vault地址 │
│ 55000e18 // 55,000 WUSD │
│ ) │
│ │
│ 转账结果: │
│ • Manager WUSD余额: -55,000 WUSD │
│ • Vault WUSD余额: 50,000 → 105,000 WUSD │
└────────────────────────────┬────────────────────────────────────────┘
│ 6. 触发事件
┌─────────────────────────────────────────────────────────────────────┐
│ 事件记录 │
│ ───────────────────────────────────────────────────────────────── │
│ emit AssetsDeposited( │
│ 55000e18 // 归还数量 │
│ ) │
└────────────────────────────┬────────────────────────────────────────┘
│ 7. 归还完成
┌─────────────────────────────────────────────────────────────────────┐
│ 归还完成 │
│ ───────────────────────────────────────────────────────────────── │
│ Vault最终状态
│ • totalAssets(): 105,000 WUSD (增加了5,000!) │
│ 计算: idleAssets + managedAssets │
│ = 105,000 + 0 = 105,000 │
│ │
│ • idleAssets(): 105,000 WUSD │
│ (vault合约实际持有的WUSD包含收益) │
│ │
│ • managedAssets: 0 WUSD │
│ (所有资产已归还) │
│ │
│ • totalSupply: 100,000 YT (不变) │
│ │
│ 收益分配: │
│ • 投资收益: 5,000 WUSD │
│ • 收益率: 5,000 / 50,000 = 10% │
│ • 每个YT的价值提升: │
│ 之前: 100,000 WUSD / 100,000 YT = 1.0 WUSD/YT │
│ 现在: 105,000 WUSD / 100,000 YT = 1.05 WUSD/YT │
│ │
│ 用户影响: │
│ ✓ 所有YT持有者自动获得5%增值 │
│ ✓ 可以提款了(流动性恢复) │
│ ✓ 如果用户提取YT会按1.05的比例获得更多WUSD │
│ │
│ 示例: │
│ 用户持有10,000 YT提取时可获得
│ (10,000 × 1.05 WUSD/YT) = 10,500 WUSD │
│ 相比初始存入的10,000 WUSD获利500 WUSD (5%) │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 7. 批量操作流程
### 7.1 批量创建Vault
```
┌─────────────────────────────────────────────────────────────────────┐
│ Owner (系统管理员) │
│ 计划: 批量创建3个不同的YT Vault │
└────────────────────────────┬────────────────────────────────────────┘
│ 调用 createVaultBatch()
│ • names: ["YT-A", "YT-B", "YT-C"]
│ • symbols: ["YTA", "YTB", "YTC"]
│ • managers: [0x111, 0x222, 0x333]
│ • hardCaps: [1000000e18, 500000e18, 2000000e18]
│ • wusd: 0x7Cd...
│ • redemptionTimes: [time1, time2, time3]
│ • initialWusdPrices: [1.05e30, 1.05e30, 1.05e30]
│ • initialYtPrices: [1.05e30, 1.02e30, 1.10e30]
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetFactory.createVaultBatch() │
│ ───────────────────────────────────────────────────────────────── │
│ 1. 参数长度验证 │
│ require(所有数组长度相等) │
│ ✓ 所有数组长度都是3 │
│ │
│ 2. 循环创建 │
│ for (i = 0; i < 3; i++) { │
│ vaults[i] = this.createVault(...) │
│ } │
└────────────────────────────┬────────────────────────────────────────┘
├─────────┬─────────┐
│ │ │
第1个Vault │ 第2个Vault │ 第3个Vault
▼ │ ▼ │ ▼
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ YT-A Token │ │ YT-B Token │ │ YT-C Token │
│ Symbol: YTA │ │ Symbol: YTB │ │ Symbol: YTC │
│ Manager: 0x111 │ │ Manager: 0x222 │ │ Manager: 0x333 │
│ HardCap: 1M YT │ │ HardCap: 500K YT │ │ HardCap: 2M YT │
│ YT Price: 1.05 │ │ YT Price: 1.02 │ │ YT Price: 1.10 │
│ 地址: 0xVault001 │ │ 地址: 0xVault002 │ │ 地址: 0xVault003 │
└───────────────────┘ └───────────────────┘ └───────────────────┘
│ │ │
└─────────┴─────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 批量创建完成 │
│ ───────────────────────────────────────────────────────────────── │
│ 返回值: [0xVault001, 0xVault002, 0xVault003] │
│ │
│ Factory状态
│ • allVaults.length: 3 │
│ • isVault[0xVault001] = true │
│ • isVault[0xVault002] = true │
│ • isVault[0xVault003] = true │
│ │
│ 优势: │
│ ✓ 一次交易创建多个vault节省gas │
│ ✓ 原子操作,全部成功或全部失败 │
│ ✓ 统一管理多个资产池 │
└─────────────────────────────────────────────────────────────────────┘
```
### 7.2 批量更新价格
```
┌─────────────────────────────────────────────────────────────────────┐
│ Oracle / Owner │
│ 接收到3个vault的最新价格数据 │
└────────────────────────────┬────────────────────────────────────────┘
│ 调用 updateVaultPricesBatch()
│ • vaults: [0xVault001, 0xVault002, 0xVault003]
│ • wusdPrices: [1.02e30, 1.03e30, 1.01e30]
│ • ytPrices: [1.15e30, 1.08e30, 1.20e30]
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetFactory.updateVaultPricesBatch() │
│ ───────────────────────────────────────────────────────────────── │
│ 1. 参数验证 │
│ require(数组长度相等) │
│ ✓ 所有数组长度都是3 │
│ │
│ 2. 循环更新 │
│ for (i = 0; i < 3; i++) { │
│ YTAssetVault(vaults[i]).updatePrices( │
│ wusdPrices[i], │
│ ytPrices[i] │
│ ) │
│ emit PricesUpdated(vaults[i], wusdPrices[i], ytPrices[i]) │
│ } │
└────────────────────────────┬────────────────────────────────────────┘
├─────────┬─────────┐
│ │ │
Vault001 │ Vault002 │ Vault003
价格更新 │ 价格更新 │ 价格更新
▼ │ ▼ │ ▼
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ WUSD: 1.02 │ │ WUSD: 1.03 │ │ WUSD: 1.01 │
│ YT: 1.15 │ │ YT: 1.08 │ │ YT: 1.20 │
│ 涨幅: +9.52% │ │ 涨幅: +2.88% │ │ 涨幅: +9.09% │
└───────────────────┘ └───────────────────┘ └───────────────────┘
│ │ │
└─────────┴─────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 批量更新完成 │
│ ───────────────────────────────────────────────────────────────── │
│ 优势: │
│ ✓ 一次交易更新多个vault价格 │
│ ✓ 节省gas费用 │
│ ✓ 确保所有vault价格同时更新 │
│ ✓ 适合定时任务批量更新 │
│ │
│ 触发的事件: │
│ • PricesUpdated × 3 │
│ • PriceUpdated × 3 (从各个vault) │
└─────────────────────────────────────────────────────────────────────┘
```
### 7.3 批量设置赎回时间
```
┌─────────────────────────────────────────────────────────────────────┐
│ Owner (系统管理员) │
│ 统一设置赎回时间: 2025-03-15 00:00:00 │
└────────────────────────────┬────────────────────────────────────────┘
│ 调用 setVaultNextRedemptionTimeBatch()
│ • vaults: [0xVault001, 0xVault002, 0xVault003]
│ • nextRedemptionTime: 1741996800
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetFactory.setVaultNextRedemptionTimeBatch() │
│ ───────────────────────────────────────────────────────────────── │
│ for (i = 0; i < vaults.length; i++) { │
│ YTAssetVault(vaults[i]).setNextRedemptionTime( │
│ _nextRedemptionTime │
│ ) │
│ emit NextRedemptionTimeSet(vaults[i], _nextRedemptionTime) │
│ } │
└────────────────────────────┬────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 批量设置完成 │
│ ───────────────────────────────────────────────────────────────── │
│ 所有3个vault的赎回时间都设置为: │
│ 2025-03-15 00:00:00 │
│ │
│ 用户影响: │
│ ✓ 所有vault的用户在同一天可以赎回 │
│ ✓ 统一管理赎回周期 │
│ ✓ 类似基金的统一开放日 │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 8. 查询信息流程
### 8.1 查询单个Vault信息
```
┌─────────────────────────────────────────────────────────────────────┐
│ 前端应用 / 查询者 │
└────────────────────────────┬────────────────────────────────────────┘
│ 调用 vault.getVaultInfo()
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetVault.getVaultInfo() │
│ ───────────────────────────────────────────────────────────────── │
│ function getVaultInfo() returns ( │
│ uint256 _totalAssets, │
│ uint256 _idleAssets, │
│ uint256 _managedAssets, │
│ uint256 _totalSupply, │
│ uint256 _hardCap, │
│ uint256 _wusdPrice, │
│ uint256 _ytPrice, │
│ uint256 _nextRedemptionTime │
│ ) │
└────────────────────────────┬────────────────────────────────────────┘
│ 读取状态
┌─────────────────────────────────────────────────────────────────────┐
│ 返回完整信息 │
│ ───────────────────────────────────────────────────────────────── │
│ 返回示例: │
│ { │
│ totalAssets: 105000e18, // 105,000 WUSD │
│ idleAssets: 105000e18, // 105,000 WUSD │
│ managedAssets: 0, // 0 WUSD │
│ totalSupply: 100000e18, // 100,000 YT │
│ hardCap: 1000000e18, // 1,000,000 YT │
│ wusdPrice: 1020000000000000000000000000000, // 1.02 │
│ ytPrice: 1150000000000000000000000000000, // 1.15 │
│ nextRedemptionTime: 1739577600 // 2025-02-15 00:00:00 │
│ } │
│ │
│ 计算衍生指标: │
│ • 每YT价值: 105,000 / 100,000 = 1.05 WUSD │
│ • 资金利用率: (105,000 - 0) / 105,000 = 100% │
│ • 硬顶使用率: 100,000 / 1,000,000 = 10% │
│ • 当前兑换率: 1 WUSD = 1.02/1.15 = 0.887 YT │
└─────────────────────────────────────────────────────────────────────┘
```
### 8.2 通过Factory查询Vault信息
```
┌─────────────────────────────────────────────────────────────────────┐
│ 前端应用 / 查询者 │
└────────────────────────────┬────────────────────────────────────────┘
│ 调用 factory.getVaultInfo(vaultAddress)
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetFactory.getVaultInfo() │
│ ───────────────────────────────────────────────────────────────── │
│ function getVaultInfo(address _vault) returns ( │
│ bool exists, │
│ uint256 totalAssets, │
│ uint256 idleAssets, │
│ uint256 managedAssets, │
│ uint256 totalSupply, │
│ uint256 hardCap, │
│ uint256 wusdPrice, │
│ uint256 ytPrice, │
│ uint256 nextRedemptionTime │
│ ) │
└────────────────────────────┬────────────────────────────────────────┘
│ 1. 检查vault是否存在
┌─────────────────────────────────────────────────────────────────────┐
│ 存在性检查 │
│ ───────────────────────────────────────────────────────────────── │
│ exists = isVault[_vault] │
│ if (!exists) return (false, 0, 0, 0, 0, 0, 0, 0, 0) │
└────────────────────────────┬────────────────────────────────────────┘
│ 2. 调用vault获取信息
┌─────────────────────────────────────────────────────────────────────┐
│ 返回完整信息 │
│ ───────────────────────────────────────────────────────────────── │
│ { │
│ exists: true, // ✓ vault存在 │
│ totalAssets: 105000e18, │
│ idleAssets: 105000e18, │
│ managedAssets: 0, │
│ totalSupply: 100000e18, │
│ hardCap: 1000000e18, │
│ wusdPrice: 1020000000000000000000000000000, │
│ ytPrice: 1150000000000000000000000000000, │
│ nextRedemptionTime: 1739577600 │
│ } │
│ │
│ 优势: │
│ ✓ 通过factory统一查询 │
│ ✓ 可验证vault是否为合法vault │
│ ✓ 一次调用获取所有信息 │
└─────────────────────────────────────────────────────────────────────┘
```
### 8.3 查询所有Vault列表
```
┌─────────────────────────────────────────────────────────────────────┐
│ 前端应用 / 查询者 │
└────────────────────────────┬────────────────────────────────────────┘
│ 1. 获取总数量
│ factory.getVaultCount()
┌─────────────────────────────────────────────────────────────────────┐
│ 获取Vault总数 │
│ ───────────────────────────────────────────────────────────────── │
│ function getVaultCount() returns (uint256) │
│ return allVaults.length │
│ │
│ 返回: 3 (有3个vault) │
└────────────────────────────┬────────────────────────────────────────┘
│ 2. 获取所有vault地址
│ factory.getAllVaults()
┌─────────────────────────────────────────────────────────────────────┐
│ 获取所有Vault地址 │
│ ───────────────────────────────────────────────────────────────── │
│ function getAllVaults() returns (address[] memory) │
│ return allVaults │
│ │
│ 返回: [0xVault001, 0xVault002, 0xVault003] │
└────────────────────────────┬────────────────────────────────────────┘
│ 3. 或分页查询
│ factory.getVaults(0, 2)
┌─────────────────────────────────────────────────────────────────────┐
│ 分页查询Vault地址 │
│ ───────────────────────────────────────────────────────────────── │
│ function getVaults(uint256 _start, uint256 _end) │
│ │
│ 参数: │
│ • _start: 0 (起始索引) │
│ • _end: 2 (结束索引,不包含) │
│ │
│ 返回: [0xVault001, 0xVault002] │
│ │
│ 优势: │
│ ✓ 适合vault数量很多时的分页加载 │
│ ✓ 减少单次调用的gas消耗 │
│ ✓ 改善前端加载性能 │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 附录:重要概念说明
### A. 价格精度 (PRICE_PRECISION)
```
精度: 1e30 (10^30)
示例:
• 价格 1.0 表示为: 1000000000000000000000000000000 (1e30)
• 价格 1.05 表示为: 1050000000000000000000000000000 (1.05e30)
• 价格 0.98 表示为: 980000000000000000000000000000 (0.98e30)
为什么使用1e30而不是1e18
✓ 更高的精度,减少舍入误差
✓ 适合复杂的价格计算
✓ 支持更精确的价格波动
```
### B. 兑换计算公式
```
存款 (depositYT):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ytAmount = (wusdAmount × wusdPrice) ÷ ytPrice
示例:
• 存入1,000 WUSD
• wusdPrice = 1.05e30
• ytPrice = 1.10e30
• ytAmount = (1,000 × 1.05) ÷ 1.10 = 954.55 YT
提款 (withdrawYT):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
wusdAmount = (ytAmount × ytPrice) ÷ wusdPrice
示例:
• 提取1,000 YT
• ytPrice = 1.10e30
• wusdPrice = 1.05e30
• wusdAmount = (1,000 × 1.10) ÷ 1.05 = 1,047.62 WUSD
```
### C. 资产状态计算
```
Vault资产状态
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
totalAssets = idleAssets + managedAssets
• idleAssets: vault合约中实际持有的WUSD
• managedAssets: manager提取、正在投资的WUSD
• totalAssets: 用户可赎回的总价值
示例:
vault余额: 50,000 WUSD
managedAssets: 50,000 WUSD
totalAssets: 100,000 WUSD (不变)
用户持有10,000 YT价值:
(10,000 / 100,000) × 100,000 = 10,000 WUSD
```
### D. 硬顶机制
```
硬顶 (Hard Cap):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
限制YT代币的最大供应量
作用:
✓ 控制vault规模
✓ 风险管理
✓ 防止过度铸造
检查时机:
• 每次depositYT时检查
• if (totalSupply + ytAmount > hardCap) revert
动态调整:
• Factory owner可以通过setHardCap调整
• 但不能低于当前totalSupply
```
### E. 统一赎回时间
```
赎回时间 (nextRedemptionTime):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
所有用户统一的赎回开放时间
特点:
✓ 类似基金的开放日
✓ 所有用户同时可赎回
✓ 不是个人锁定期
检查:
• block.timestamp >= nextRedemptionTime
• 未到时间调用withdrawYT会revert
管理:
• Factory owner可以设置
• 支持批量设置多个vault
```
### F. CEI模式
```
CEI模式 (Checks-Effects-Interactions):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
安全的合约编写模式,防止重入攻击
1. Checks (检查)
• 验证参数
• 检查权限
• 检查余额
2. Effects (状态更新)
• 更新合约状态
• 修改余额
• 记录变化
3. Interactions (外部交互)
• 转账代币
• 调用外部合约
• 触发事件
配合nonReentrant modifier确保安全
```
### G. UUPS升级模式
```
UUPS (Universal Upgradeable Proxy Standard):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
可升级合约的标准实现方式
结构:
┌─────────────┐
│ ERC1967Proxy│ ← 用户交互的地址(不变)
└──────┬──────┘
│ delegatecall
┌─────────────┐
│ Implementation│ ← 逻辑合约(可升级)
└─────────────┘
优势:
✓ 合约地址不变
✓ 状态数据保留
✓ 可以修复bug和添加功能
✓ 升级权限由Factory控制
注意:
• 不能在状态变量声明时初始化
• 必须使用initialize函数
• 保留__gap数组用于未来扩展
```
---
## 9. 暂停功能流程
### 9.1 暂停单个Vault
```
┌─────────────────────────────────────────────────────────────────────┐
│ Factory Owner (紧急情况) │
│ 检测到: YT-A Vault 存在安全问题 │
└────────────────────────────────┬────────────────────────────────────┘
│ 1. 调用 pauseVault(vaultAddress)
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetFactory.pauseVault() │
│ ───────────────────────────────────────────────────────────────── │
│ function pauseVault(address _vault) external onlyOwner │
│ │
│ 权限检查: │
│ ✓ onlyOwner - 只有Factory owner可调用 │
│ ✓ isVault[_vault] - 验证vault存在 │
└────────────────────────────┬────────────────────────────────────────┘
│ 2. 调用 vault.pause()
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetVault.pause() │
│ ───────────────────────────────────────────────────────────────── │
│ internal _pause() │
│ • 设置 paused = true │
│ • 触发 Paused 事件 │
└────────────────────────────┬────────────────────────────────────────┘
│ 3. 暂停生效
┌─────────────────────────────────────────────────────────────────────┐
│ Vault已暂停 │
│ ───────────────────────────────────────────────────────────────── │
│ 被阻止的操作revert EnforcedPause
│ ✗ depositYT() - 用户无法存款 │
│ ✗ withdrawYT() - 用户无法提款 │
│ ✗ withdrawForManagement() - Manager无法提取资产 │
│ ✗ depositManagedAssets() - Manager无法归还资产 │
│ │
│ 仍可用的操作: │
│ ✓ balanceOf() - 查询余额 │
│ ✓ totalSupply() - 查询总供应 │
│ ✓ totalAssets() - 查询总资产 │
│ ✓ getVaultInfo() - 查询详细信息 │
│ ✓ previewBuy() - 预览存款 │
│ ✓ previewSell() - 预览提款 │
│ ✓ canRedeemNow() - 检查赎回状态 │
│ │
│ 用户影响: │
│ • 所有资金操作暂停 │
│ • 资产安全锁定 │
│ • 可以查看但无法操作 │
└─────────────────────────────────────────────────────────────────────┘
```
### 9.2 恢复单个Vault
```
┌─────────────────────────────────────────────────────────────────────┐
│ Factory Owner (问题已解决) │
│ 安全问题已修复,可以恢复正常运行 │
└────────────────────────────┬────────────────────────────────────────┘
│ 1. 调用 unpauseVault(vaultAddress)
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetFactory.unpauseVault() │
│ ───────────────────────────────────────────────────────────────── │
│ function unpauseVault(address _vault) external onlyOwner │
│ │
│ 权限检查: │
│ ✓ onlyOwner - 只有Factory owner可调用 │
│ ✓ isVault[_vault] - 验证vault存在 │
└────────────────────────────┬────────────────────────────────────────┘
│ 2. 调用 vault.unpause()
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetVault.unpause() │
│ ───────────────────────────────────────────────────────────────── │
│ internal _unpause() │
│ • 设置 paused = false │
│ • 触发 Unpaused 事件 │
└────────────────────────────┬────────────────────────────────────────┘
│ 3. 恢复完成
┌─────────────────────────────────────────────────────────────────────┐
│ Vault恢复正常 │
│ ───────────────────────────────────────────────────────────────── │
│ 所有功能恢复: │
│ ✓ depositYT() - 用户可以存款 │
│ ✓ withdrawYT() - 用户可以提款(如已过赎回时间) │
│ ✓ withdrawForManagement() - Manager可以提取资产 │
│ ✓ depositManagedAssets() - Manager可以归还资产 │
│ │
│ 系统状态: │
│ • 所有操作恢复正常 │
│ • 用户资产未受影响 │
│ • 暂停期间的价格更新仍然有效 │
└─────────────────────────────────────────────────────────────────────┘
```
### 9.3 批量暂停Vaults
```
┌─────────────────────────────────────────────────────────────────────┐
│ Factory Owner (系统级紧急) │
│ 检测到系统性风险需要暂停多个Vault │
└────────────────────────────┬────────────────────────────────────────┘
│ 1. 调用 pauseVaultBatch(vaultAddresses)
│ vaults: [0xVault001, 0xVault002, 0xVault003]
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetFactory.pauseVaultBatch() │
│ ───────────────────────────────────────────────────────────────── │
│ function pauseVaultBatch(address[] memory _vaults) │
│ │
│ 批量处理: │
│ for (i = 0; i < _vaults.length; i++) { │
│ require(isVault[_vaults[i]]) // 验证每个vault │
│ YTAssetVault(_vaults[i]).pause() │
│ } │
└────────────────────────────┬────────────────────────────────────────┘
├─────────┬─────────┐
│ │ │
Vault001 │ Vault002 │ Vault003
暂停 │ 暂停 │ 暂停
▼ │ ▼ │ ▼
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ YT-A Vault │ │ YT-B Vault │ │ YT-C Vault │
│ 状态: PAUSED │ │ 状态: PAUSED │ │ 状态: PAUSED │
│ 所有操作冻结 │ │ 所有操作冻结 │ │ 所有操作冻结 │
└───────────────────┘ └───────────────────┘ └───────────────────┘
│ │ │
└─────────┴─────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 批量暂停完成 │
│ ───────────────────────────────────────────────────────────────── │
│ 优势: │
│ ✓ 一次交易暂停多个vault │
│ ✓ 节省gas费用 │
│ ✓ 原子操作,全部成功或全部失败 │
│ ✓ 快速响应系统性风险 │
│ │
│ 系统影响: │
│ • 所有指定vault的资金操作立即冻结 │
│ • 用户资产安全保护 │
│ • 管理员可以调查和修复问题 │
└─────────────────────────────────────────────────────────────────────┘
```
### 9.4 批量恢复Vaults
```
┌─────────────────────────────────────────────────────────────────────┐
│ Factory Owner (风险已消除) │
│ 问题已解决恢复所有暂停的Vault │
└────────────────────────────┬────────────────────────────────────────┘
│ 1. 调用 unpauseVaultBatch(vaultAddresses)
┌─────────────────────────────────────────────────────────────────────┐
│ YTAssetFactory.unpauseVaultBatch() │
│ ───────────────────────────────────────────────────────────────── │
│ 批量恢复所有vault │
│ • 验证每个vault存在 │
│ • 调用每个vault的unpause() │
│ • 原子操作执行 │
└────────────────────────────┬────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 系统全面恢复 │
│ ───────────────────────────────────────────────────────────────── │
│ 所有vault恢复正常运行 │
│ 用户可以继续所有操作 │
└─────────────────────────────────────────────────────────────────────┘
```
### 暂停功能的应用场景:
```
┌─────────────────────────────────────────────────────────────────────┐
│ 使用场景和最佳实践 │
│ │
│ 何时使用暂停功能: │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ │
│ 1⃣ 安全漏洞发现 │
│ • 发现合约安全问题 │
│ • 暂停受影响的vault │
│ • 保护用户资产 │
│ • 修复后恢复 │
│ │
│ 2⃣ 价格异常 │
│ • 价格预言机故障 │
│ • 价格剧烈波动 │
│ • 暂停交易防止损失 │
│ • 价格稳定后恢复 │
│ │
│ 3⃣ 系统升级 │
│ • 准备合约升级 │
│ • 暂停所有操作 │
│ • 执行升级 │
│ • 验证后恢复 │
│ │
│ 4⃣ 流动性危机 │
│ • Manager提取资金后未及时归还 │
│ • 暂停提款防止挤兑 │
│ • 等待资金回流 │
│ • 流动性恢复后解除 │
│ │
│ 5⃣ 监管要求 │
│ • 配合监管调查 │
│ • 临时冻结操作 │
│ • 保留完整记录 │
│ │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ │
│ 最佳实践: │
│ ✓ 暂停前公告(如有时间) │
│ ✓ 记录暂停原因 │
│ ✓ 快速调查和修复 │
│ ✓ 恢复前全面测试 │
│ ✓ 恢复后公告说明 │
│ │
│ 注意事项: │
│ ⚠️ 暂停不影响已持有的资产价值 │
│ ⚠️ 暂停期间价格仍可更新由Factory
│ ⚠️ Manager在暂停期间也无法操作 │
│ ⚠️ 查询功能不受影响 │
└─────────────────────────────────────────────────────────────────────┘
```