change WUSD payment to USDC

This commit is contained in:
2025-12-24 16:41:26 +08:00
parent d2e9377f78
commit e21ee7a5df
160 changed files with 6038 additions and 4050 deletions

View File

@@ -77,7 +77,7 @@ contract Configurator is
// 设置新配置
configuratorParams[lendingProxy].baseToken = newConfiguration.baseToken;
configuratorParams[lendingProxy].baseTokenPriceFeed = newConfiguration.baseTokenPriceFeed;
configuratorParams[lendingProxy].lendingPriceSource = newConfiguration.lendingPriceSource;
configuratorParams[lendingProxy].supplyKink = newConfiguration.supplyKink;
configuratorParams[lendingProxy].supplyPerYearInterestRateSlopeLow = newConfiguration.supplyPerYearInterestRateSlopeLow;
configuratorParams[lendingProxy].supplyPerYearInterestRateSlopeHigh = newConfiguration.supplyPerYearInterestRateSlopeHigh;

View File

@@ -12,7 +12,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./LendingStorage.sol";
import "./LendingMath.sol";
import "../interfaces/ILending.sol";
import "../interfaces/IPriceFeed.sol";
import "../interfaces/IYTLendingPriceFeed.sol";
/**
* @title Lending
@@ -45,7 +45,7 @@ contract Lending is
// 设置基础配置
baseToken = config.baseToken;
baseTokenPriceFeed = config.baseTokenPriceFeed;
lendingPriceSource = config.lendingPriceSource;
// 常量:一年的秒数
uint64 SECONDS_PER_YEAR = 365 * 24 * 60 * 60; // 31,536,000
@@ -327,7 +327,7 @@ contract Lending is
if (oldBalance >= 0) revert NotLiquidatable();
// 计算所有抵押品的总价值(按 liquidationFactor 折扣)
uint256 basePrice = IPriceFeed(baseTokenPriceFeed).getPrice();
uint256 basePrice = IYTLendingPriceFeed(lendingPriceSource).getPrice(baseToken);
uint256 totalCollateralValue = 0;
for (uint i = 0; i < assetList.length; i++) {
@@ -336,7 +336,7 @@ contract Lending is
if (collateralAmount > 0) {
AssetConfig memory assetConfig = assetConfigs[asset];
uint256 assetPrice = IPriceFeed(assetConfig.priceFeed).getPrice();
uint256 assetPrice = IYTLendingPriceFeed(lendingPriceSource).getPrice(asset);
// 计算抵押品价值USD8位精度- 用于事件记录
uint256 assetScale = 10 ** assetConfig.decimals;
@@ -454,24 +454,44 @@ contract Lending is
/**
* @notice 计算支付指定baseAmount可购买的抵押品数量
* @dev 重新设计以避免在 1e30 价格精度下溢出
*/
function quoteCollateral(address asset, uint256 baseAmount) public view override returns (uint256) {
AssetConfig memory assetConfig = assetConfigs[asset];
uint256 assetPrice = IPriceFeed(assetConfig.priceFeed).getPrice();
uint256 basePrice = IPriceFeed(baseTokenPriceFeed).getPrice();
uint256 assetPrice = IYTLendingPriceFeed(lendingPriceSource).getPrice(asset);
uint256 basePrice = IYTLendingPriceFeed(lendingPriceSource).getPrice(baseToken);
uint256 FACTOR_SCALE = 1e18;
uint256 baseScale = 10 ** uint256(IERC20Metadata(baseToken).decimals());
uint256 assetScale = 10 ** uint256(assetConfig.decimals);
// 折扣因子
// 计算折扣因子
uint256 discountFactor = (storeFrontPriceFactor * (FACTOR_SCALE - assetConfig.liquidationFactor)) / FACTOR_SCALE;
// 分子: basePrice * baseAmount * assetScale * FACTOR_SCALE
// 分母: assetPrice * (FACTOR_SCALE - discountFactor) * baseScale
return (basePrice * baseAmount * assetScale * FACTOR_SCALE) /
(assetPrice * (FACTOR_SCALE - discountFactor) * baseScale);
// 计算折扣后的资产价格 (保持 1e30 精度)
uint256 effectiveAssetPrice = (assetPrice * (FACTOR_SCALE - discountFactor)) / FACTOR_SCALE;
// 为了避免溢出,我们需要重新排列计算:
// result = (basePrice * baseAmount * assetScale) / (effectiveAssetPrice * baseScale)
//
// 由于所有价格都是 1e30 精度,我们可以先约简价格:
// priceRatio = basePrice / effectiveAssetPrice (保持精度)
// result = (baseAmount * priceRatio * assetScale) / (1e30 * baseScale)
//
// 但为了避免精度损失,我们分步计算:
// step1 = baseAmount * assetScale / baseScale (token amount conversion)
// step2 = step1 * basePrice / effectiveAssetPrice (price conversion)
// 如果 baseScale 和 assetScale 相同(都是18),可以简化
if (baseScale == assetScale) {
// result = baseAmount * basePrice / effectiveAssetPrice
return (baseAmount * basePrice) / effectiveAssetPrice;
} else {
// 一般情况:分步计算避免溢出
uint256 adjustedAmount = (baseAmount * assetScale) / baseScale;
return (adjustedAmount * basePrice) / effectiveAssetPrice;
}
}
/**
@@ -486,7 +506,7 @@ contract Lending is
uint256 debt = uint256(-balance);
// 将 debt 转换为美元价值(使用 baseToken 价格)
uint256 basePrice = IPriceFeed(baseTokenPriceFeed).getPrice();
uint256 basePrice = IYTLendingPriceFeed(lendingPriceSource).getPrice(baseToken);
uint256 baseDecimals = IERC20Metadata(baseToken).decimals();
uint256 debtValue = (debt * basePrice) / (10 ** baseDecimals);
@@ -508,7 +528,7 @@ contract Lending is
uint256 amount = userCollateral[account][asset];
if (amount > 0) {
AssetConfig memory config = assetConfigs[asset];
uint256 price = IPriceFeed(config.priceFeed).getPrice();
uint256 price = IYTLendingPriceFeed(lendingPriceSource).getPrice(asset);
uint256 value = LendingMath.getCollateralValue(amount, price, config.decimals);
totalValue += (value * config.borrowCollateralFactor) / 1e18;
}
@@ -553,7 +573,7 @@ contract Lending is
uint256 debt = uint256(-balance);
// 将 debt 转换为美元价值(使用 baseToken 价格和 price feed 精度)
uint256 basePrice = IPriceFeed(baseTokenPriceFeed).getPrice();
uint256 basePrice = IYTLendingPriceFeed(lendingPriceSource).getPrice(baseToken);
uint256 baseDecimals = IERC20Metadata(baseToken).decimals();
uint256 debtValue = (debt * basePrice) / (10 ** baseDecimals);
@@ -564,7 +584,7 @@ contract Lending is
uint256 amount = userCollateral[account][asset];
if (amount > 0) {
AssetConfig memory config = assetConfigs[asset];
uint256 price = IPriceFeed(config.priceFeed).getPrice();
uint256 price = IYTLendingPriceFeed(lendingPriceSource).getPrice(asset);
uint256 value = LendingMath.getCollateralValue(amount, price, config.decimals);
collateralValue += (value * config.liquidateCollateralFactor) / 1e18;
}

View File

@@ -8,7 +8,6 @@ pragma solidity ^0.8.0;
contract LendingConfiguration {
struct AssetConfig {
address asset; // 资产地址
address priceFeed; // 价格预言机地址
uint8 decimals; // 小数位数
uint64 borrowCollateralFactor; // 借款抵押率
uint64 liquidateCollateralFactor; // 清算抵押率
@@ -18,7 +17,7 @@ contract LendingConfiguration {
struct Configuration {
address baseToken; // 基础资产
address baseTokenPriceFeed; // 基础资产价格预言机
address lendingPriceSource; // 借贷价格源
// 利率模型参数
uint64 supplyKink; // 供应拐点利用率

View File

@@ -7,7 +7,6 @@ pragma solidity ^0.8.0;
*/
library LendingMath {
uint256 internal constant FACTOR_SCALE = 1e18;
uint256 internal constant PRICE_SCALE = 1e8;
uint256 internal constant SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
/**

View File

@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/IYTVault.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract LendingPriceFeed is Ownable {
address public ytVault;
address public wusdAddress;
error InvalidYTVaultAddress();
error InvalidWUSDAddress();
constructor(address _ytVault, address _wusdAddress) Ownable(msg.sender) {
if (_ytVault == address(0)) revert InvalidYTVaultAddress();
if (_wusdAddress == address(0)) revert InvalidWUSDAddress();
ytVault = _ytVault;
wusdAddress = _wusdAddress;
}
function setYTVault(address _ytVault) external onlyOwner {
if (_ytVault == address(0)) revert InvalidYTVaultAddress();
ytVault = _ytVault;
}
function setWUSDAddress(address _wusdAddress) external onlyOwner {
if (_wusdAddress == address(0)) revert InvalidWUSDAddress();
wusdAddress = _wusdAddress;
}
function getPrice(address _token) external view returns (uint256) {
if (_token == wusdAddress) {
return IYTVault(ytVault).wusdPrice();
} else {
return IYTVault(_token).ytPrice();
}
}
}

View File

@@ -11,7 +11,7 @@ abstract contract LendingStorage is LendingConfiguration {
// 市场配置
address public baseToken;
address public baseTokenPriceFeed;
address public lendingPriceSource;
// 利率参数(每秒利率,已从年化利率转换)
uint64 public supplyKink;