This commit is contained in:
2025-12-25 13:29:35 +08:00
parent e21ee7a5df
commit cbe16b7f40
25 changed files with 43 additions and 740 deletions

View File

@@ -10,11 +10,6 @@ import "../../interfaces/IYTVault.sol";
import "../../interfaces/IYTLPToken.sol";
import "../../interfaces/IUSDY.sol";
/**
* @title YTPoolManager
* @notice 管理ytLP的铸造和赎回计算池子AUM
* @dev UUPS可升级合约
*/
contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
using SafeERC20 for IERC20;
@@ -82,13 +77,6 @@ contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrade
_;
}
/**
* @notice 初始化合约
* @param _ytVault YTVault合约地址
* @param _usdy USDY代币地址
* @param _ytLP ytLP代币地址
* @param _cooldownDuration 冷却时间(秒)
*/
function initialize(
address _ytVault,
address _usdy,
@@ -108,10 +96,6 @@ contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrade
cooldownDuration = _cooldownDuration;
}
/**
* @notice 授权升级仅gov可调用
* @param newImplementation 新实现合约地址
*/
function _authorizeUpgrade(address newImplementation) internal override onlyGov {}
function setGov(address _gov) external onlyGov {
@@ -138,9 +122,6 @@ contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrade
emit AumAdjustmentChanged(_addition, _deduction);
}
/**
* @notice 为指定账户添加流动性Handler调用
*/
function addLiquidityForAccount(
address _fundingAccount,
address _account,
@@ -186,9 +167,6 @@ contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrade
return mintAmount;
}
/**
* @notice 为指定账户移除流动性Handler调用
*/
function removeLiquidityForAccount(
address _account,
address _tokenOut,
@@ -235,11 +213,6 @@ contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrade
return amountOut;
}
/**
* @notice 获取ytLP价格
* @param _maximise 是否取最大值
* @return ytLP价格18位精度
*/
function getPrice(bool _maximise) external view returns (uint256) {
uint256 aum = getAumInUsdy(_maximise);
uint256 supply = IERC20(ytLP).totalSupply();
@@ -249,11 +222,6 @@ contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrade
return aum * YTLP_PRECISION / supply;
}
/**
* @notice 获取池子总价值AUM
* @param _maximise true=使用最大价格(添加流动性时), false=使用最小价格(移除流动性时)
* @return USDY计价的总价值
*/
function getAumInUsdy(bool _maximise) public view returns (uint256) {
uint256 aum = IYTVault(ytVault).getPoolValue(_maximise);
@@ -267,10 +235,5 @@ contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrade
return aum;
}
/**
* @dev 预留存储空间,用于未来升级时添加新的状态变量
* 50个slot = 50 * 32 bytes = 1600 bytes
*/
uint256[50] private __gap;
}
}

View File

@@ -6,11 +6,6 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "../../interfaces/IYTAssetVault.sol";
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";
/**
* @title YTPriceFeed
* @notice 价格读取器直接从YT合约读取价格变量带保护机制和价差
* @dev UUPS可升级合约
*/
contract YTPriceFeed is Initializable, UUPSUpgradeable {
/// @custom:oz-upgrades-unsafe-allow constructor
@@ -33,19 +28,14 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
address public usdcAddress;
// 价格保护参数
uint256 public maxPriceChangeBps; // 5% 最大价格变动
/// @notice USDC价格Feed
AggregatorV3Interface internal usdcPriceFeed;
// 价差配置(每个代币可以有不同的价差)
mapping(address => uint256) public spreadBasisPoints;
// 价格历史记录
mapping(address => uint256) public lastPrice;
// 价格更新权限
mapping(address => bool) public isKeeper;
event PriceUpdate(address indexed token, uint256 oldPrice, uint256 newPrice, uint256 timestamp);
@@ -62,9 +52,6 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
_;
}
/**
* @notice 初始化合约
*/
function initialize(address _usdcAddress, address _usdcPriceFeed) external initializer {
__UUPSUpgradeable_init();
if (_usdcAddress == address(0)) revert InvalidAddress();
@@ -74,64 +61,33 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
maxPriceChangeBps = 500; // 5% 最大价格变动
}
/**
* @notice 设置USDC地址
* @param _usdcAddress USDC地址
*/
function setUSDCAddress(address _usdcAddress) external onlyGov {
if (_usdcAddress == address(0)) revert InvalidAddress();
usdcAddress = _usdcAddress;
}
/**
* @notice 设置USDC价格Feed
* @param _usdcPriceFeed USDC价格Feed地址
*/
function setUSDCPriceFeed(address _usdcPriceFeed) external onlyGov {
usdcPriceFeed = AggregatorV3Interface(_usdcPriceFeed);
}
/**
* @notice 授权升级仅gov可调用
* @param newImplementation 新实现合约地址
*/
function _authorizeUpgrade(address newImplementation) internal override onlyGov {}
/**
* @notice 设置keeper权限
* @param _keeper keeper地址
* @param _isActive 是否激活
*/
function setKeeper(address _keeper, bool _isActive) external onlyGov {
isKeeper[_keeper] = _isActive;
emit KeeperSet(_keeper, _isActive);
}
/**
* @notice 设置最大价格变动百分比
* @param _maxPriceChangeBps 最大变动(基点)
*/
function setMaxPriceChangeBps(uint256 _maxPriceChangeBps) external onlyGov {
if (_maxPriceChangeBps > 2000) revert MaxChangeTooHigh(); // 最大20%
maxPriceChangeBps = _maxPriceChangeBps;
}
/**
* @notice 设置代币价差
* @param _token 代币地址
* @param _spreadBasisPoints 价差基点例如10 = 0.1%, 100 = 1%
*/
function setSpreadBasisPoints(address _token, uint256 _spreadBasisPoints) external onlyGov {
if (_spreadBasisPoints > MAX_SPREAD_BASIS_POINTS) revert SpreadTooHigh();
spreadBasisPoints[_token] = _spreadBasisPoints;
emit SpreadUpdate(_token, _spreadBasisPoints);
}
/**
* @notice 批量设置代币价差
* @param _tokens 代币地址数组
* @param _spreadBasisPoints 价差数组
*/
function setSpreadBasisPointsForMultiple(
address[] calldata _tokens,
uint256[] calldata _spreadBasisPoints
@@ -144,11 +100,6 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
}
}
/**
* @notice 更新并缓存代币价格keeper调用
* @param _token 代币地址
* @return 更新后的价格
*/
function updatePrice(address _token) external onlyKeeper returns (uint256) {
if (_token == usdcAddress) {
return _getUSDCPrice();
@@ -157,10 +108,8 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
uint256 oldPrice = lastPrice[_token];
uint256 newPrice = _getRawPrice(_token);
// 价格波动检查
_validatePriceChange(_token, newPrice);
// 更新缓存价格
lastPrice[_token] = newPrice;
emit PriceUpdate(_token, oldPrice, newPrice, block.timestamp);
@@ -168,31 +117,13 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
return newPrice;
}
/**
* @notice 强制更新价格(紧急情况)
* @param _token 代币地址
* @param _price 新价格
*/
function forceUpdatePrice(address _token, uint256 _price) external onlyGov {
uint256 oldPrice = lastPrice[_token];
lastPrice[_token] = _price;
emit PriceUpdate(_token, oldPrice, _price, block.timestamp);
}
/**
* @notice 获取YT代币价格带波动保护和价差
* @param _token 代币地址
* @param _maximise true=最大价格(上浮价差,对协议有利), false=最小价格(下压价差,对协议有利)
* @return 价格30位精度
*
* 使用场景:
* - 添加流动性时AUM计算_maximise=true高估AUM用户获得较少LP
* - 移除流动性时AUM计算_maximise=false低估AUM用户获得较少代币
* - buyUSDY时用户卖代币_maximise=false低估用户代币价值
* - sellUSDY时用户买代币_maximise=true高估需支付的代币价值
* - swap时tokenIn_maximise=false低估输入
* - swap时tokenOut_maximise=true高估输出
*/
function getPrice(address _token, bool _maximise) external view returns (uint256) {
if (_token == usdcAddress) {
return _getUSDCPrice();
@@ -200,24 +131,15 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
uint256 basePrice = _getRawPrice(_token);
// 价格波动检查
_validatePriceChange(_token, basePrice);
// 应用价差
return _applySpread(_token, basePrice, _maximise);
}
/**
* @notice 直接读取YT代币的ytPrice变量
*/
function _getRawPrice(address _token) private view returns (uint256) {
return IYTAssetVault(_token).ytPrice();
}
/**
* @notice 获取并验证USDC价格从Chainlink
* @return 返回uint256格式的USDC价格精度为1e30
*/
function _getUSDCPrice() internal view returns (uint256) {
(
/* uint80 roundId */,
@@ -232,13 +154,6 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
return uint256(price) * 1e22; // 1e22 = 10^(30-8)
}
/**
* @notice 应用价差
* @param _token 代币地址
* @param _basePrice 基础价格
* @param _maximise true=上浮价格false=下压价格
* @return 应用价差后的价格
*/
function _applySpread(
address _token,
uint256 _basePrice,
@@ -246,41 +161,30 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
) private view returns (uint256) {
uint256 spread = spreadBasisPoints[_token];
// 如果没有设置价差,直接返回基础价格
if (spread == 0) {
return _basePrice;
}
if (_maximise) {
// 上浮价格basePrice * (1 + spread%)
return _basePrice * (BASIS_POINTS_DIVISOR + spread) / BASIS_POINTS_DIVISOR;
} else {
// 下压价格basePrice * (1 - spread%)
return _basePrice * (BASIS_POINTS_DIVISOR - spread) / BASIS_POINTS_DIVISOR;
}
}
/**
* @notice 验证价格变动是否在允许范围内
*/
function _validatePriceChange(address _token, uint256 _newPrice) private view {
uint256 oldPrice = lastPrice[_token];
// 首次设置价格,跳过检查
if (oldPrice == 0) {
return;
}
// 计算价格变动百分比
uint256 priceDiff = _newPrice > oldPrice ? _newPrice - oldPrice : oldPrice - _newPrice;
uint256 maxDiff = oldPrice * maxPriceChangeBps / BASIS_POINTS_DIVISOR;
if (priceDiff > maxDiff) revert PriceChangeTooLarge();
}
/**
* @notice 获取价格详细信息
*/
function getPriceInfo(address _token) external view returns (
uint256 currentPrice,
uint256 cachedPrice,
@@ -303,13 +207,9 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
minPrice = _applySpread(_token, currentPrice, false);
}
}
/**
* @notice 获取最大价格(上浮价差)
*/
function getMaxPrice(address _token) external view returns (uint256) {
if (_token == usdcAddress) {
// USDC通常不需要价差直接返回原价格
return _getUSDCPrice();
}
uint256 basePrice = _getRawPrice(_token);
@@ -317,12 +217,8 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
return _applySpread(_token, basePrice, true);
}
/**
* @notice 获取最小价格(下压价差)
*/
function getMinPrice(address _token) external view returns (uint256) {
if (_token == usdcAddress) {
// USDC通常不需要价差直接返回原价格
return _getUSDCPrice();
}
uint256 basePrice = _getRawPrice(_token);
@@ -330,9 +226,5 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
return _applySpread(_token, basePrice, false);
}
/**
* @dev 预留存储空间,用于未来升级时添加新的状态变量
* 50个slot = 50 * 32 bytes = 1600 bytes
*/
uint256[50] private __gap;
}
}

View File

@@ -10,11 +10,6 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../../interfaces/IYTPoolManager.sol";
import "../../interfaces/IYTVault.sol";
/**
* @title YTRewardRouter
* @notice 用户交互入口
* @dev UUPS可升级合约
*/
contract YTRewardRouter is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable {
using SafeERC20 for IERC20;
@@ -48,13 +43,6 @@ contract YTRewardRouter is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrad
_;
}
/**
* @notice 初始化合约
* @param _usdy USDY代币地址
* @param _ytLP ytLP代币地址
* @param _ytPoolManager YTPoolManager地址
* @param _ytVault YTVault地址
*/
function initialize(
address _usdy,
address _ytLP,
@@ -78,35 +66,16 @@ contract YTRewardRouter is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrad
ytVault = _ytVault;
}
/**
* @notice 授权升级仅gov可调用
* @param newImplementation 新实现合约地址
*/
function _authorizeUpgrade(address newImplementation) internal override onlyGov {}
/**
* @notice 暂停合约仅gov可调用
* @dev 暂停后,所有资金流动操作将被禁止
*/
function pause() external onlyGov {
_pause();
}
/**
* @notice 恢复合约仅gov可调用
*/
function unpause() external onlyGov {
_unpause();
}
/**
* @notice 添加流动性
* @param _token YT代币或USDC地址
* @param _amount 代币数量
* @param _minUsdy 最小USDY数量
* @param _minYtLP 最小ytLP数量
* @return ytLPAmount 获得的ytLP数量
*/
function addLiquidity(
address _token,
uint256 _amount,
@@ -132,14 +101,6 @@ contract YTRewardRouter is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrad
return ytLPAmount;
}
/**
* @notice 移除流动性
* @param _tokenOut 输出代币地址
* @param _ytLPAmount ytLP数量
* @param _minOut 最小输出数量
* @param _receiver 接收地址
* @return amountOut 获得的代币数量
*/
function removeLiquidity(
address _tokenOut,
uint256 _ytLPAmount,
@@ -161,15 +122,6 @@ contract YTRewardRouter is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrad
return amountOut;
}
/**
* @notice YT代币互换
* @param _tokenIn 输入代币地址
* @param _tokenOut 输出代币地址
* @param _amountIn 输入数量
* @param _minOut 最小输出数量
* @param _receiver 接收地址
* @return amountOut 获得的代币数量
*/
function swapYT(
address _tokenIn,
address _tokenOut,
@@ -192,29 +144,15 @@ contract YTRewardRouter is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrad
return amountOut;
}
/**
* @notice 获取ytLP价格
* @return ytLP价格18位精度
*/
function getYtLPPrice() external view returns (uint256) {
return IYTPoolManager(ytPoolManager).getPrice(true);
}
/**
* @notice 获取账户价值
* @param _account 账户地址
* @return 账户持有的ytLP价值USDY计价
*/
function getAccountValue(address _account) external view returns (uint256) {
uint256 ytLPBalance = IERC20(ytLP).balanceOf(_account);
uint256 ytLPPrice = IYTPoolManager(ytPoolManager).getPrice(true);
return ytLPBalance * ytLPPrice / (10 ** 18);
}
/**
* @dev 预留存储空间,用于未来升级时添加新的状态变量
* 50个slot = 50 * 32 bytes = 1600 bytes
*/
uint256[50] private __gap;
}
}

View File

@@ -9,11 +9,6 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../../interfaces/IUSDY.sol";
import "../../interfaces/IYTPriceFeed.sol";
/**
* @title YTVault
* @notice 核心资金池处理YT代币的存储、交换和动态手续费
* @dev UUPS可升级合约
*/
contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
using SafeERC20 for IERC20;
@@ -50,38 +45,32 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
address public priceFeed;
address public usdy;
mapping(address => bool) public isSwapper; // 授权的swap调用者
mapping(address => bool) public isSwapper;
bool public isSwapEnabled;
bool public emergencyMode;
// 代币白名单
address[] public allWhitelistedTokens;
mapping(address => bool) public whitelistedTokens;
mapping(address => bool) public stableTokens; // 稳定币标记
mapping(address => bool) public stableTokens;
mapping(address => uint256) public tokenDecimals;
mapping(address => uint256) public tokenWeights;
uint256 public totalTokenWeights;
// 池子资产
mapping(address => uint256) public poolAmounts;
mapping(address => uint256) public tokenBalances; // 跟踪实际代币余额
mapping(address => uint256) public tokenBalances;
// USDY债务追踪用于动态手续费
mapping(address => uint256) public usdyAmounts;
mapping(address => uint256) public maxUsdyAmounts;
// 手续费配置
uint256 public swapFeeBasisPoints;
uint256 public stableSwapFeeBasisPoints;
uint256 public taxBasisPoints;
uint256 public stableTaxBasisPoints;
bool public hasDynamicFees;
// 全局滑点保护
uint256 public maxSwapSlippageBps; // 10% 最大滑点
uint256 public maxSwapSlippageBps;
// 单笔交易限额
mapping(address => uint256) public maxSwapAmount;
event Swap(
@@ -129,11 +118,6 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
_;
}
/**
* @notice 初始化合约
* @param _usdy USDY代币地址
* @param _priceFeed 价格预言机地址
*/
function initialize(address _usdy, address _priceFeed) external initializer {
if (_usdy == address(0) || _priceFeed == address(0)) revert InvalidAddress();
@@ -144,7 +128,6 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
usdy = _usdy;
priceFeed = _priceFeed;
// 初始化默认值
isSwapEnabled = true;
emergencyMode = false;
swapFeeBasisPoints = 30;
@@ -152,16 +135,11 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
taxBasisPoints = 50;
stableTaxBasisPoints = 20;
hasDynamicFees = true;
maxSwapSlippageBps = 1000; // 10% 最大滑点
maxSwapSlippageBps = 1000;
// 将 USDY 标记为稳定币,这样 USDY ↔ 稳定币的互换可以享受低费率
stableTokens[_usdy] = true;
}
/**
* @notice 授权升级仅gov可调用
* @param newImplementation 新实现合约地址
*/
function _authorizeUpgrade(address newImplementation) internal override onlyGov {}
function setGov(address _gov) external onlyGov {
@@ -248,7 +226,7 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
}
function setMaxSwapSlippageBps(uint256 _slippageBps) external onlyGov {
if (_slippageBps > 2000) revert SlippageTooHigh(); // 最大20%
if (_slippageBps > 2000) revert SlippageTooHigh();
maxSwapSlippageBps = _slippageBps;
}
@@ -256,12 +234,6 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
maxSwapAmount[_token] = _amount;
}
/**
* @notice 用YT代币购买USDY添加流动性时调用
* @param _token YT代币地址
* @param _receiver USDY接收地址
* @return usdyAmountAfterFees 实际获得的USDY数量
*/
function buyUSDY(address _token, address _receiver)
external
onlyPoolManager
@@ -298,12 +270,6 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
return usdyAmountAfterFees;
}
/**
* @notice 用USDY卖出换取YT代币移除流动性时调用
* @param _token YT代币地址
* @param _receiver YT代币接收地址
* @return amountOutAfterFees 实际获得的YT代币数量
*/
function sellUSDY(address _token, address _receiver)
external
onlyPoolManager
@@ -319,29 +285,23 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
uint256 price = _getPrice(_token, true);
// 计算赎回金额(扣费前)
uint256 redemptionAmount = usdyAmount * PRICE_PRECISION / price;
redemptionAmount = _adjustForDecimals(redemptionAmount, usdy, _token);
if (redemptionAmount == 0) revert InvalidAmount();
// 计算手续费和实际转出金额
uint256 feeBasisPoints = _getSwapFeeBasisPoints(usdy, _token, redemptionAmount);
uint256 amountOut = redemptionAmount * (BASIS_POINTS_DIVISOR - feeBasisPoints) / BASIS_POINTS_DIVISOR;
if (amountOut == 0) revert InvalidAmount();
if (poolAmounts[_token] < amountOut) revert InsufficientPool();
// 计算实际转出的代币对应的USDY价值用于减少usdyAmount记账
uint256 usdyAmountOut = amountOut * price / PRICE_PRECISION;
usdyAmountOut = _adjustForDecimals(usdyAmountOut, _token, usdy);
// 手续费留在池子:只减少实际转出的部分
_decreasePoolAmount(_token, amountOut);
_decreaseUsdyAmount(_token, usdyAmountOut);
// 销毁USDY
IUSDY(usdy).burn(address(this), usdyAmount);
// 转出代币
IERC20(_token).safeTransfer(_receiver, amountOut);
_updateTokenBalance(_token);
@@ -350,13 +310,6 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
return amountOut;
}
/**
* @notice YT代币互换
* @param _tokenIn 输入代币地址
* @param _tokenOut 输出代币地址
* @param _receiver 接收地址
* @return amountOutAfterFees 实际获得的输出代币数量
*/
function swap(
address _tokenIn,
address _tokenOut,
@@ -370,7 +323,6 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
uint256 amountIn = _transferIn(_tokenIn);
if (amountIn == 0) revert InvalidAmount();
// 检查单笔交易限额
if (maxSwapAmount[_tokenIn] > 0) {
if (amountIn > maxSwapAmount[_tokenIn]) revert AmountExceedsLimit();
}
@@ -390,7 +342,6 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
if (amountOutAfterFees == 0) revert InvalidAmount();
if (poolAmounts[_tokenOut] < amountOutAfterFees) revert InsufficientPool();
// 全局滑点保护10%
_validateSwapSlippage(amountIn, amountOutAfterFees, priceIn, priceOut);
_increasePoolAmount(_tokenIn, amountIn);
@@ -407,26 +358,14 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
return amountOutAfterFees;
}
/**
* @notice 获取代币价格(带价差)
* @param _token 代币地址
* @param _maximise true=最大价格, false=最小价格
* @return 价格30位精度
*/
function getPrice(address _token, bool _maximise) external view returns (uint256) {
return _getPrice(_token, _maximise);
}
/**
* @notice 获取最大价格
*/
function getMaxPrice(address _token) external view returns (uint256) {
return _getPrice(_token, true);
}
/**
* @notice 获取最小价格
*/
function getMinPrice(address _token) external view returns (uint256) {
return _getPrice(_token, false);
}
@@ -435,11 +374,6 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
return allWhitelistedTokens;
}
/**
* @notice 获取池子总价值
* @param _maximise true=使用最大价格(对协议有利), false=使用最小价格(对用户有利)
* @return 池子总价值USDY计价
*/
function getPoolValue(bool _maximise) external view returns (uint256) {
uint256 totalValue = 0;
for (uint256 i = 0; i < allWhitelistedTokens.length; i++) {
@@ -476,13 +410,6 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
usdyAmounts[_token] = value - _amount;
}
/**
* @notice 获取swap手续费率公开方法供前端调用
* @param _tokenIn 输入代币
* @param _tokenOut 输出代币
* @param _usdyAmount USDY数量
* @return 手续费率basis points
*/
function getSwapFeeBasisPoints(
address _tokenIn,
address _tokenOut,
@@ -549,14 +476,11 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
? nextAmount - targetAmount
: targetAmount - nextAmount;
// 改善平衡 → 降低手续费
if (nextDiff < initialDiff) {
uint256 rebateBps = _taxBasisPoints * initialDiff / targetAmount;
return rebateBps > _feeBasisPoints ? 0 : _feeBasisPoints - rebateBps;
}
// 恶化平衡 → 提高手续费
// taxBps = tax * (a + b) / (2 * target)
uint256 sumDiff = initialDiff + nextDiff;
if (sumDiff / 2 > targetAmount) {
sumDiff = targetAmount * 2;
@@ -596,10 +520,8 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
uint256 _priceIn,
uint256 _priceOut
) private view {
// 计算预期输出(不含手续费)
uint256 expectedOut = _amountIn * _priceIn / _priceOut;
// 计算实际滑点
if (expectedOut > _amountOut) {
uint256 slippage = (expectedOut - _amountOut) * BASIS_POINTS_DIVISOR / expectedOut;
if (slippage > maxSwapSlippageBps) revert SlippageTooHigh();
@@ -629,10 +551,5 @@ contract YTVault is Initializable, UUPSUpgradeable, ReentrancyGuardUpgradeable {
return _amount * (10 ** (decimalsTo - decimalsFrom));
}
/**
* @dev 预留存储空间,用于未来升级时添加新的状态变量
* 50个slot = 50 * 32 bytes = 1600 bytes
*/
uint256[50] private __gap;
}
}