update lending buyCollateral function

This commit is contained in:
2026-01-07 10:49:49 +08:00
parent 5f2750c80e
commit c8cb4dbecd
12 changed files with 468 additions and 30 deletions

View File

@@ -373,6 +373,7 @@ contract Lending is
/**
* @notice 购买清算后的抵押品
* @dev 自动限制购买量到可用储备,只收取实际需要的费用
*/
function buyCollateral(
address asset,
@@ -388,15 +389,24 @@ contract Lending is
revert NotForSale(); // 储备金充足,无需出售
}
// 计算可购买的抵押品数量
// 计算可购买的抵押品数量(基于用户愿意支付的 baseAmount
uint256 collateralAmount = quoteCollateral(asset, baseAmount);
// 验证数
if (collateralAmount < minAmount) revert InsufficientBalance();
if (collateralAmount > collateralReserves[asset]) revert InsufficientBalance();
// 自动限制到可用储备
// 这样可以防止价格波动导致交易失败
if (collateralAmount > collateralReserves[asset]) {
collateralAmount = collateralReserves[asset];
}
// 收取清算人支付的资金
IERC20(baseToken).transferFrom(msg.sender, address(this), baseAmount);
// 滑点保护:确保购买量不低于用户的最小期望
if (collateralAmount < minAmount) revert InsufficientBalance();
// 根据实际购买量计算需要支付的金额(而非固定的 baseAmount
// 这样如果购买量被限制,用户只需支付相应的费用
uint256 actualBaseAmount = quoteBaseAmount(asset, collateralAmount);
// 收取实际需要的资金
IERC20(baseToken).transferFrom(msg.sender, address(this), actualBaseAmount);
// 抵押品出库
collateralReserves[asset] -= collateralAmount;
@@ -405,7 +415,38 @@ contract Lending is
IERC20(asset).safeTransfer(recipient, collateralAmount);
// 注意:收入会自动体现在 getReserves() 中,因为 balance 增加了
emit BuyCollateral(msg.sender, asset, baseAmount, collateralAmount);
emit BuyCollateral(msg.sender, asset, actualBaseAmount, collateralAmount);
}
/**
* @notice 计算购买指定数量抵押品需要支付的 baseToken 数量(反向计算)
* @param asset 抵押品地址
* @param collateralAmount 要购买的抵押品数量
* @return 需要支付的 baseToken 数量
*/
function quoteBaseAmount(address asset, uint256 collateralAmount) internal view returns (uint256) {
AssetConfig memory assetConfig = assetConfigs[asset];
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;
// 计算折扣后的资产价格
uint256 effectiveAssetPrice = (assetPrice * (FACTOR_SCALE - discountFactor)) / FACTOR_SCALE;
// 反向计算baseAmount = (collateralAmount * effectiveAssetPrice * baseScale) / (basePrice * assetScale)
if (baseScale == assetScale) {
return (collateralAmount * effectiveAssetPrice) / basePrice;
} else {
uint256 adjustedAmount = (collateralAmount * baseScale) / assetScale;
return (adjustedAmount * effectiveAssetPrice) / basePrice;
}
}
/**