update
This commit is contained in:
@@ -77,6 +77,12 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
|
||||
priceStalenesThreshold = 3600; // 默认1小时
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice 授权升级(仅gov可调用)
|
||||
* @param newImplementation 新实现合约地址
|
||||
*/
|
||||
function _authorizeUpgrade(address newImplementation) internal override onlyGov {}
|
||||
|
||||
/**
|
||||
* @notice 设置USDC地址
|
||||
* @param _usdcAddress USDC地址
|
||||
@@ -94,12 +100,6 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
|
||||
usdcPriceFeed = AggregatorV3Interface(_usdcPriceFeed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice 授权升级(仅gov可调用)
|
||||
* @param newImplementation 新实现合约地址
|
||||
*/
|
||||
function _authorizeUpgrade(address newImplementation) internal override onlyGov {}
|
||||
|
||||
/**
|
||||
* @notice 设置keeper权限
|
||||
* @param _keeper keeper地址
|
||||
|
||||
@@ -203,17 +203,7 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
|
||||
maxUsdyAmounts[_token] = _maxUsdyAmount;
|
||||
stableTokens[_token] = _isStable;
|
||||
}
|
||||
|
||||
function clearWhitelistedToken(address _token) external onlyGov {
|
||||
if (!whitelistedTokens[_token]) revert TokenNotWhitelisted();
|
||||
totalTokenWeights = totalTokenWeights - tokenWeights[_token];
|
||||
delete whitelistedTokens[_token];
|
||||
delete stableTokens[_token];
|
||||
delete tokenDecimals[_token];
|
||||
delete tokenWeights[_token];
|
||||
delete maxUsdyAmounts[_token];
|
||||
}
|
||||
|
||||
|
||||
function setSwapFees(
|
||||
uint256 _swapFee,
|
||||
uint256 _stableSwapFee,
|
||||
@@ -241,12 +231,6 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
|
||||
emit SwapEnabledSet(_isSwapEnabled);
|
||||
}
|
||||
|
||||
function withdrawToken(address _token, address _receiver, uint256 _amount) external onlyGov {
|
||||
if (!emergencyMode) revert NotInEmergency();
|
||||
IERC20(_token).safeTransfer(_receiver, _amount);
|
||||
_updateTokenBalance(_token);
|
||||
}
|
||||
|
||||
function setMaxSwapSlippageBps(uint256 _slippageBps) external onlyGov {
|
||||
if (_slippageBps > 2000) revert SlippageTooHigh(); // 最大20%
|
||||
maxSwapSlippageBps = _slippageBps;
|
||||
@@ -406,6 +390,22 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
|
||||
|
||||
return amountOutAfterFees;
|
||||
}
|
||||
|
||||
function clearWhitelistedToken(address _token) external onlyGov {
|
||||
if (!whitelistedTokens[_token]) revert TokenNotWhitelisted();
|
||||
totalTokenWeights = totalTokenWeights - tokenWeights[_token];
|
||||
delete whitelistedTokens[_token];
|
||||
delete stableTokens[_token];
|
||||
delete tokenDecimals[_token];
|
||||
delete tokenWeights[_token];
|
||||
delete maxUsdyAmounts[_token];
|
||||
}
|
||||
|
||||
function withdrawToken(address _token, address _receiver, uint256 _amount) external onlyGov {
|
||||
if (!emergencyMode) revert NotInEmergency();
|
||||
IERC20(_token).safeTransfer(_receiver, _amount);
|
||||
_updateTokenBalance(_token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice 获取代币价格(带价差)
|
||||
|
||||
@@ -100,6 +100,7 @@ contract YTLPToken is Initializable, ERC20Upgradeable, OwnableUpgradeable, UUPSU
|
||||
(bool success, ) = poolManager.call(
|
||||
abi.encodeWithSignature("onLPTransfer(address,address)", from, to)
|
||||
);
|
||||
require(success, "Failed to call onLPTransfer");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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地址
|
||||
|
||||
@@ -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 总资产 = 合约余额 + 被管理的资产
|
||||
|
||||
Reference in New Issue
Block a user