fix contract
This commit is contained in:
@@ -71,6 +71,7 @@ contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrade
|
||||
event HandlerSet(address indexed handler, bool isActive);
|
||||
event GovChanged(address indexed oldGov, address indexed newGov);
|
||||
event AumAdjustmentChanged(uint256 addition, uint256 deduction);
|
||||
event CooldownInherited(address indexed from, address indexed to, uint256 cooldownTime);
|
||||
|
||||
modifier onlyGov() {
|
||||
if (msg.sender != gov) revert Forbidden();
|
||||
@@ -138,6 +139,24 @@ contract YTPoolManager is Initializable, UUPSUpgradeable, ReentrancyGuardUpgrade
|
||||
emit AumAdjustmentChanged(_addition, _deduction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice LP 代币转账时的回调函数
|
||||
* @param _from 发送方地址
|
||||
* @param _to 接收方地址
|
||||
* @dev 当 LP 代币转账时,接收方继承发送方的冷却时间,防止绕过冷却期
|
||||
*/
|
||||
function onLPTransfer(address _from, address _to) external {
|
||||
// 只允许 ytLP 代币合约调用
|
||||
if (msg.sender != ytLP) revert Forbidden();
|
||||
|
||||
// 如果发送方有冷却时间记录,且接收方的冷却时间更早(或没有记录)
|
||||
// 则将发送方的冷却时间继承给接收方
|
||||
if (lastAddedAt[_from] > 0 && lastAddedAt[_to] < lastAddedAt[_from]) {
|
||||
lastAddedAt[_to] = lastAddedAt[_from];
|
||||
emit CooldownInherited(_from, _to, lastAddedAt[_from]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice 为指定账户添加流动性(Handler调用)
|
||||
*/
|
||||
|
||||
@@ -24,6 +24,7 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
|
||||
error SpreadTooHigh();
|
||||
error InvalidAddress();
|
||||
error InvalidChainlinkPrice();
|
||||
error StalePrice();
|
||||
|
||||
address public gov;
|
||||
|
||||
@@ -35,6 +36,7 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
|
||||
|
||||
// 价格保护参数
|
||||
uint256 public maxPriceChangeBps; // 5% 最大价格变动
|
||||
uint256 public priceStalenesThreshold; // 价格过期阈值(秒)
|
||||
|
||||
/// @notice USDC价格Feed
|
||||
AggregatorV3Interface internal usdcPriceFeed;
|
||||
@@ -72,6 +74,7 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
|
||||
usdcPriceFeed = AggregatorV3Interface(_usdcPriceFeed);
|
||||
gov = msg.sender;
|
||||
maxPriceChangeBps = 500; // 5% 最大价格变动
|
||||
priceStalenesThreshold = 3600; // 默认1小时
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,6 +119,15 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
|
||||
maxPriceChangeBps = _maxPriceChangeBps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice 设置价格过期阈值
|
||||
* @param _threshold 阈值(秒),例如:3600 = 1小时,86400 = 24小时
|
||||
*/
|
||||
function setPriceStalenessThreshold(uint256 _threshold) external onlyGov {
|
||||
require(_threshold > 0 && _threshold <= 7 days, "Invalid threshold");
|
||||
priceStalenesThreshold = _threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice 设置代币价差
|
||||
* @param _token 代币地址
|
||||
@@ -220,15 +232,21 @@ contract YTPriceFeed is Initializable, UUPSUpgradeable {
|
||||
*/
|
||||
function _getUSDCPrice() internal view returns (uint256) {
|
||||
(
|
||||
/* uint80 roundId */,
|
||||
uint80 roundId,
|
||||
int256 price,
|
||||
/* uint256 startedAt */,
|
||||
/* uint256 updatedAt */,
|
||||
/* uint80 answeredInRound */
|
||||
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) * 1e22; // 1e22 = 10^(30-8)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,12 @@ contract YTLPToken is Initializable, ERC20Upgradeable, OwnableUpgradeable, UUPSU
|
||||
|
||||
error NotMinter();
|
||||
error InvalidMinter();
|
||||
error InvalidPoolManager();
|
||||
|
||||
mapping(address => bool) public isMinter;
|
||||
|
||||
address public poolManager;
|
||||
|
||||
event MinterSet(address indexed minter, bool isActive);
|
||||
|
||||
/**
|
||||
@@ -56,6 +59,16 @@ contract YTLPToken is Initializable, ERC20Upgradeable, OwnableUpgradeable, UUPSU
|
||||
emit MinterSet(_minter, _isActive);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice 设置 PoolManager 地址
|
||||
* @param _poolManager PoolManager 合约地址
|
||||
* @dev 用于在转账时通知 PoolManager 更新冷却时间
|
||||
*/
|
||||
function setPoolManager(address _poolManager) external onlyOwner {
|
||||
if (_poolManager == address(0)) revert InvalidPoolManager();
|
||||
poolManager = _poolManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice 铸造ytLP代币
|
||||
* @param _to 接收地址
|
||||
@@ -74,6 +87,22 @@ contract YTLPToken is Initializable, ERC20Upgradeable, OwnableUpgradeable, UUPSU
|
||||
_burn(_from, _amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice 重写 _update 函数,在转账时更新冷却时间
|
||||
* @dev 当 LP 代币转账时,接收方继承发送方的冷却时间,防止绕过冷却期
|
||||
*/
|
||||
function _update(address from, address to, uint256 value) internal override {
|
||||
super._update(from, to, value);
|
||||
|
||||
// 只在实际转账时触发(不包括 mint 和 burn)
|
||||
if (from != address(0) && to != address(0) && poolManager != address(0)) {
|
||||
// 通知 PoolManager 更新接收方的冷却时间
|
||||
(bool success, ) = poolManager.call(
|
||||
abi.encodeWithSignature("onLPTransfer(address,address)", from, to)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev 预留存储空间,用于未来升级时添加新的状态变量
|
||||
* 50个slot = 50 * 32 bytes = 1600 bytes
|
||||
|
||||
Reference in New Issue
Block a user