This commit is contained in:
2026-01-19 11:56:15 +08:00
parent d56f83726b
commit ae33e0ec07
26 changed files with 222 additions and 217 deletions

View File

@@ -91,6 +91,87 @@ contract YTAssetFactory is Initializable, UUPSUpgradeable, OwnableUpgradeable {
defaultHardCap = _defaultHardCap;
emit DefaultHardCapSet(_defaultHardCap);
}
/**
* @notice 设置指定vault的硬顶
* @param _vault vault地址
* @param _hardCap 新的硬顶值
*/
function setHardCap(address _vault, uint256 _hardCap) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
YTAssetVault(_vault).setHardCap(_hardCap);
emit HardCapSet(_vault, _hardCap);
}
/**
* @notice 批量设置硬顶
* @param _vaults vault地址数组
* @param _hardCaps 硬顶值数组
*/
function setHardCapBatch(
address[] memory _vaults,
uint256[] memory _hardCaps
) external onlyOwner {
require(_vaults.length == _hardCaps.length, "Length mismatch");
for (uint256 i = 0; i < _vaults.length; i++) {
if (!isVault[_vaults[i]]) revert VaultNotExists();
YTAssetVault(_vaults[i]).setHardCap(_hardCaps[i]);
emit HardCapSet(_vaults[i], _hardCaps[i]);
}
}
/**
* @notice 设置vault的管理员
* @param _vault vault地址
* @param _manager 新管理员地址
*/
function setVaultManager(address _vault, address _manager) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
if (_manager == address(0)) revert InvalidAddress();
YTAssetVault(_vault).setManager(_manager);
}
/**
* @notice 设置vault的价格过期阈值
* @param _vault vault地址
* @param _threshold 阈值(秒)
*/
function setPriceStalenessThreshold(address _vault, uint256 _threshold) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
YTAssetVault(_vault).setPriceStalenessThreshold(_threshold);
}
/**
* @notice 设置vault的下一个赎回时间
* @param _vault vault地址
* @param _nextRedemptionTime 赎回时间Unix时间戳
*/
function setVaultNextRedemptionTime(address _vault, uint256 _nextRedemptionTime) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
YTAssetVault(_vault).setNextRedemptionTime(_nextRedemptionTime);
emit NextRedemptionTimeSet(_vault, _nextRedemptionTime);
}
/**
* @notice 批量设置赎回时间
* @param _vaults vault地址数组
* @param _nextRedemptionTime 统一的赎回时间
*/
function setVaultNextRedemptionTimeBatch(
address[] memory _vaults,
uint256 _nextRedemptionTime
) external onlyOwner {
for (uint256 i = 0; i < _vaults.length; i++) {
if (!isVault[_vaults[i]]) revert VaultNotExists();
YTAssetVault(_vaults[i]).setNextRedemptionTime(_nextRedemptionTime);
emit NextRedemptionTimeSet(_vaults[i], _nextRedemptionTime);
}
}
/**
* @notice 创建新的YTAssetVault
@@ -196,87 +277,6 @@ contract YTAssetFactory is Initializable, UUPSUpgradeable, OwnableUpgradeable {
}
}
/**
* @notice 设置指定vault的硬顶
* @param _vault vault地址
* @param _hardCap 新的硬顶值
*/
function setHardCap(address _vault, uint256 _hardCap) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
YTAssetVault(_vault).setHardCap(_hardCap);
emit HardCapSet(_vault, _hardCap);
}
/**
* @notice 批量设置硬顶
* @param _vaults vault地址数组
* @param _hardCaps 硬顶值数组
*/
function setHardCapBatch(
address[] memory _vaults,
uint256[] memory _hardCaps
) external onlyOwner {
require(_vaults.length == _hardCaps.length, "Length mismatch");
for (uint256 i = 0; i < _vaults.length; i++) {
if (!isVault[_vaults[i]]) revert VaultNotExists();
YTAssetVault(_vaults[i]).setHardCap(_hardCaps[i]);
emit HardCapSet(_vaults[i], _hardCaps[i]);
}
}
/**
* @notice 设置vault的管理员
* @param _vault vault地址
* @param _manager 新管理员地址
*/
function setVaultManager(address _vault, address _manager) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
if (_manager == address(0)) revert InvalidAddress();
YTAssetVault(_vault).setManager(_manager);
}
/**
* @notice 设置vault的价格过期阈值
* @param _vault vault地址
* @param _threshold 阈值(秒)
*/
function setPriceStalenessThreshold(address _vault, uint256 _threshold) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
YTAssetVault(_vault).setPriceStalenessThreshold(_threshold);
}
/**
* @notice 设置vault的下一个赎回时间
* @param _vault vault地址
* @param _nextRedemptionTime 赎回时间Unix时间戳
*/
function setVaultNextRedemptionTime(address _vault, uint256 _nextRedemptionTime) external onlyOwner {
if (!isVault[_vault]) revert VaultNotExists();
YTAssetVault(_vault).setNextRedemptionTime(_nextRedemptionTime);
emit NextRedemptionTimeSet(_vault, _nextRedemptionTime);
}
/**
* @notice 批量设置赎回时间
* @param _vaults vault地址数组
* @param _nextRedemptionTime 统一的赎回时间
*/
function setVaultNextRedemptionTimeBatch(
address[] memory _vaults,
uint256 _nextRedemptionTime
) external onlyOwner {
for (uint256 i = 0; i < _vaults.length; i++) {
if (!isVault[_vaults[i]]) revert VaultNotExists();
YTAssetVault(_vaults[i]).setNextRedemptionTime(_nextRedemptionTime);
emit NextRedemptionTimeSet(_vaults[i], _nextRedemptionTime);
}
}
/**
* @notice 暂停vault紧急情况
* @param _vault vault地址

View File

@@ -180,48 +180,6 @@ contract YTAssetVault is
*/
function _authorizeUpgrade(address newImplementation) internal override onlyFactory {}
/**
* @notice 获取并验证USDC价格从Chainlink
* @return 返回uint256格式的USDC价格精度为1e8
*/
function _getUSDCPrice() internal view returns (uint256) {
(
uint80 roundId,
int256 price,
/* uint256 startedAt */,
uint256 updatedAt,
uint80 answeredInRound
) = usdcPriceFeed.latestRoundData();
// 价格有效性检查
if (price <= 0) revert InvalidChainlinkPrice();
// 新鲜度检查:确保价格数据不过期
if (updatedAt == 0) revert StalePrice();
if (answeredInRound < roundId) revert StalePrice();
if (block.timestamp - updatedAt > priceStalenesThreshold) revert StalePrice();
return uint256(price);
}
/**
* @notice 计算价格转换因子
* @dev 转换因子 = 10^(ytDecimals) * PRICE_PRECISION / (10^(usdcDecimals) * CHAINLINK_PRICE_PRECISION)
* @return 价格转换因子
*/
function _getPriceConversionFactor() internal view returns (uint256) {
uint8 ytDecimals = decimals();
// 分子: 10^ytDecimals * PRICE_PRECISION (1e30)
uint256 numerator = (10 ** ytDecimals) * PRICE_PRECISION;
// 分母: 10^usdcDecimals * CHAINLINK_PRICE_PRECISION (1e8)
uint256 denominator = (10 ** usdcDecimals) * CHAINLINK_PRICE_PRECISION;
// 返回转换因子
return numerator / denominator;
}
/**
* @notice 设置硬顶
* @param _hardCap 新的硬顶值
@@ -250,21 +208,6 @@ contract YTAssetVault is
priceStalenesThreshold = _threshold;
}
/**
* @notice 暂停合约仅factory可调用
* @dev 暂停后,所有资金流动操作将被禁止
*/
function pause() external onlyFactory {
_pause();
}
/**
* @notice 恢复合约仅factory可调用
*/
function unpause() external onlyFactory {
_unpause();
}
/**
* @notice 设置下一个赎回开放时间仅factory可调用
* @param _nextRedemptionTime 下一个赎回时间Unix时间戳
@@ -442,6 +385,102 @@ contract YTAssetVault is
emit BatchProcessed(startIndex, processedUpToIndex, processedCount, totalDistributed);
}
/**
* @notice 提取USDC用于外部投资
* @param _to 接收地址
* @param _amount 提取数量
*/
function withdrawForManagement(address _to, uint256 _amount) external onlyManager nonReentrant whenNotPaused {
if (_amount == 0) revert InvalidAmount();
uint256 availableAssets = IERC20(usdcAddress).balanceOf(address(this));
if (_amount > availableAssets) revert InvalidAmount();
managedAssets += _amount;
IERC20(usdcAddress).safeTransfer(_to, _amount);
emit AssetsWithdrawn(_to, _amount);
}
/**
* @notice 将管理的资产归还到金库(可以归还更多,产生收益)
* @param _amount 归还数量
*/
function depositManagedAssets(uint256 _amount) external onlyManager nonReentrant whenNotPaused {
if (_amount == 0) revert InvalidAmount();
// 先更新状态遵循CEI模式
if (_amount >= managedAssets) {
// 归还金额 >= 已管理资产managedAssets归零多余部分是收益
managedAssets = 0;
} else {
// 归还金额 < 已管理资产,部分归还
managedAssets -= _amount;
}
// 从manager转入USDC到合约
IERC20(usdcAddress).transferFrom(msg.sender, address(this), _amount);
emit AssetsDeposited(_amount);
}
/**
* @notice 暂停合约仅factory可调用
* @dev 暂停后,所有资金流动操作将被禁止
*/
function pause() external onlyFactory {
_pause();
}
/**
* @notice 恢复合约仅factory可调用
*/
function unpause() external onlyFactory {
_unpause();
}
/**
* @notice 获取并验证USDC价格从Chainlink
* @return 返回uint256格式的USDC价格精度为1e8
*/
function _getUSDCPrice() internal view returns (uint256) {
(
uint80 roundId,
int256 price,
/* uint256 startedAt */,
uint256 updatedAt,
uint80 answeredInRound
) = usdcPriceFeed.latestRoundData();
// 价格有效性检查
if (price <= 0) revert InvalidChainlinkPrice();
// 新鲜度检查:确保价格数据不过期
if (updatedAt == 0) revert StalePrice();
if (answeredInRound < roundId) revert StalePrice();
if (block.timestamp - updatedAt > priceStalenesThreshold) revert StalePrice();
return uint256(price);
}
/**
* @notice 计算价格转换因子
* @dev 转换因子 = 10^(ytDecimals) * PRICE_PRECISION / (10^(usdcDecimals) * CHAINLINK_PRICE_PRECISION)
* @return 价格转换因子
*/
function _getPriceConversionFactor() internal view returns (uint256) {
uint8 ytDecimals = decimals();
// 分子: 10^ytDecimals * PRICE_PRECISION (1e30)
uint256 numerator = (10 ** ytDecimals) * PRICE_PRECISION;
// 分母: 10^usdcDecimals * CHAINLINK_PRICE_PRECISION (1e8)
uint256 denominator = (10 ** usdcDecimals) * CHAINLINK_PRICE_PRECISION;
// 返回转换因子
return numerator / denominator;
}
/**
* @notice 查询用户的所有提现请求ID
@@ -535,45 +574,6 @@ contract YTAssetVault is
return block.timestamp >= nextRedemptionTime;
}
/**
* @notice 提取USDC用于外部投资
* @param _to 接收地址
* @param _amount 提取数量
*/
function withdrawForManagement(address _to, uint256 _amount) external onlyManager nonReentrant whenNotPaused {
if (_amount == 0) revert InvalidAmount();
uint256 availableAssets = IERC20(usdcAddress).balanceOf(address(this));
if (_amount > availableAssets) revert InvalidAmount();
managedAssets += _amount;
IERC20(usdcAddress).safeTransfer(_to, _amount);
emit AssetsWithdrawn(_to, _amount);
}
/**
* @notice 将管理的资产归还到金库(可以归还更多,产生收益)
* @param _amount 归还数量
*/
function depositManagedAssets(uint256 _amount) external onlyManager nonReentrant whenNotPaused {
if (_amount == 0) revert InvalidAmount();
// 先更新状态遵循CEI模式
if (_amount >= managedAssets) {
// 归还金额 >= 已管理资产managedAssets归零多余部分是收益
managedAssets = 0;
} else {
// 归还金额 < 已管理资产,部分归还
managedAssets -= _amount;
}
// 从manager转入USDC到合约
IERC20(usdcAddress).transferFrom(msg.sender, address(this), _amount);
emit AssetsDeposited(_amount);
}
/**
* @notice 获取总资产(包含被管理的资产)
* @return 总资产 = 合约余额 + 被管理的资产