Files
assetxContracts/contracts/ytLending/LendingMath.sol

161 lines
5.8 KiB
Solidity
Raw Permalink Normal View History

2025-12-18 13:07:35 +08:00
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title LendingMath
* @notice
*/
library LendingMath {
uint256 internal constant FACTOR_SCALE = 1e18;
uint256 internal constant PRICE_SCALE = 1e8;
uint256 internal constant SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
/**
* @notice
* @param principal
* @param index
* @return
*/
function principalToBalance(int104 principal, uint256 index) internal pure returns (int256) {
return int256(principal) * int256(index) / int256(FACTOR_SCALE);
}
/**
* @notice
* @param balance
* @param index
* @return
*/
function balanceToPrincipal(int256 balance, uint256 index) internal pure returns (int104) {
return int104((balance * int256(FACTOR_SCALE)) / int256(index));
}
/**
* @notice
* @dev absorb
*/
function repayAndSupplyAmount(int104 oldPrincipal, int104 newPrincipal) internal pure returns (uint104, uint104) {
// 如果新本金小于旧本金,没有偿还或供应
if (newPrincipal < oldPrincipal) return (0, 0);
if (newPrincipal <= 0) {
// 从负数变得更接近0偿还债务
return (uint104(newPrincipal - oldPrincipal), 0);
} else if (oldPrincipal >= 0) {
// 两个都是正数(增加存款)
return (0, uint104(newPrincipal - oldPrincipal));
} else {
// 从负数变正数(偿还所有债务并存款)
return (uint104(-oldPrincipal), uint104(newPrincipal));
}
}
/**
* @notice
* @dev withdraw/borrow
*/
function withdrawAndBorrowAmount(int104 oldPrincipal, int104 newPrincipal) internal pure returns (uint104, uint104) {
// 如果新本金大于旧本金,没有提取或借款
if (newPrincipal > oldPrincipal) return (0, 0);
if (newPrincipal >= 0) {
// 还是正数(提取存款)
return (uint104(oldPrincipal - newPrincipal), 0);
} else if (oldPrincipal <= 0) {
// 两个都是负数(增加借款)
return (0, uint104(oldPrincipal - newPrincipal));
} else {
// 从正数变负数(提取所有存款并借款)
return (uint104(oldPrincipal), uint104(-newPrincipal));
}
}
/**
* @notice
* @param totalSupply
* @param totalBorrow
* @return (scaled by 1e18)
*/
function getUtilization(uint256 totalSupply, uint256 totalBorrow) internal pure returns (uint64) {
if (totalSupply == 0) return 0;
return uint64((totalBorrow * FACTOR_SCALE) / totalSupply);
}
/**
* @notice
*/
function getSupplyRate(
uint256 utilization,
uint64 supplyKink,
uint64 supplyPerSecondInterestRateSlopeLow,
uint64 supplyPerSecondInterestRateSlopeHigh,
uint64 supplyPerSecondInterestRateBase
) internal pure returns (uint64) {
if (utilization <= supplyKink) {
return supplyPerSecondInterestRateBase + uint64((utilization * supplyPerSecondInterestRateSlopeLow) / FACTOR_SCALE);
} else {
uint256 excessUtil = utilization - supplyKink;
return supplyPerSecondInterestRateBase + supplyPerSecondInterestRateSlopeLow +
uint64((excessUtil * supplyPerSecondInterestRateSlopeHigh) / FACTOR_SCALE);
}
}
/**
* @notice
*/
function getBorrowRate(
uint256 utilization,
uint64 borrowKink,
uint64 borrowPerSecondInterestRateSlopeLow,
uint64 borrowPerSecondInterestRateSlopeHigh,
uint64 borrowPerSecondInterestRateBase
) internal pure returns (uint64) {
if (utilization <= borrowKink) {
return borrowPerSecondInterestRateBase + uint64((utilization * borrowPerSecondInterestRateSlopeLow) / FACTOR_SCALE);
} else {
uint256 excessUtil = utilization - borrowKink;
return borrowPerSecondInterestRateBase + borrowPerSecondInterestRateSlopeLow +
uint64((excessUtil * borrowPerSecondInterestRateSlopeHigh) / FACTOR_SCALE);
}
}
/**
* @notice
* @param index
* @param interestRatePerSecond
* @param timeElapsed
* @return
*/
function accrueInterest(
uint256 index,
uint64 interestRatePerSecond,
uint256 timeElapsed
) internal pure returns (uint256) {
// 优化:每秒利率直接乘以时间,只需一次除法
uint256 interestAccrued = (index * interestRatePerSecond * timeElapsed) / FACTOR_SCALE;
return index + interestAccrued;
}
/**
* @notice
*/
function getCollateralValue(
uint256 collateralAmount,
uint256 collateralPrice,
uint8 collateralDecimals
) internal pure returns (uint256) {
return (collateralAmount * collateralPrice) / (10 ** collateralDecimals);
}
/**
* @notice
*/
function getBorrowCapacity(
uint256 collateralValue,
uint64 borrowCollateralFactor
) internal pure returns (uint256) {
return (collateralValue * borrowCollateralFactor) / FACTOR_SCALE;
}
}