Files
assetxContracts/contracts/ytLending/LendingPriceFeed.sol
2026-01-12 14:33:16 +08:00

80 lines
2.8 KiB
Solidity
Raw Blame History

This file contains ambiguous Unicode characters

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.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/IYTAssetVault.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";
contract LendingPriceFeed is OwnableUpgradeable, UUPSUpgradeable {
address public usdcAddress;
AggregatorV3Interface internal usdcPriceFeed;
/// @notice 价格过期阈值(秒)
uint256 public priceStalenesThreshold;
error InvalidUsdcAddress();
error InvalidUsdcPriceFeedAddress();
error InvalidChainlinkPrice();
error StalePrice();
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize(address _usdcAddress, address _usdcPriceFeed) external initializer {
__UUPSUpgradeable_init();
__Ownable_init(msg.sender);
if (_usdcAddress == address(0)) revert InvalidUsdcAddress();
if (_usdcPriceFeed == address(0)) revert InvalidUsdcPriceFeedAddress();
usdcAddress = _usdcAddress;
usdcPriceFeed = AggregatorV3Interface(_usdcPriceFeed);
priceStalenesThreshold = 3600; // 默认1小时
}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
function setUsdcAddress(address _usdcAddress) external onlyOwner {
if (_usdcAddress == address(0)) revert InvalidUsdcAddress();
usdcAddress = _usdcAddress;
}
/**
* @notice 设置价格过期阈值
* @param _threshold 阈值例如3600 = 1小时86400 = 24小时
*/
function setPriceStalenessThreshold(uint256 _threshold) external onlyOwner {
require(_threshold > 0 && _threshold <= 7 days, "Invalid threshold");
priceStalenesThreshold = _threshold;
}
function getPrice(address _token) external view returns (uint256) {
if (_token == usdcAddress) {
return _getUSDCPrice();
}
return IYTAssetVault(_token).ytPrice();
}
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) * 1e22; // 1e22 = 10^(30-8)
}
}