Incorrect borrowed assets calculation in the function _isPositionSafe
Description
The function _isPositionSafe is used to check whether the position of a specified borrower is healthy by comparing the amount of borrowed assets with the maxBorrowLimit calculated based on the collateral value and the loan-to-value ratio.
In the calculation of maxBorrowLimit, s.config.lltv is represented with the precision of PoolConstants.WAD. Therefore, when calculating the borrowed assets, it is necessary to multiply by PoolConstants.WAD to maintain consistency in precision with the maxBorrowLimit.
An intuitive way to calculate the borrowed assets is PoolConstants.WAD * position.borrowShares.toAssetUp(s.totalBorrowAssets, s.totalBorrowShares). However, the implementation uses position.borrowShares * s.totalBorrowAssets.toAssetUp(PoolConstants.WAD, s.totalBorrowShares).
function _isPositionSafe(
PoolStorage.PoolState storage s,
address borrower
) internal view returns (bool) {
PoolStorage.Position memory position = s.positions[borrower];
if (position.borrowShares == 0) return true;
uint256 assetRatio = s.totalBorrowAssets.toAssetsUp(PoolConstants.WAD, s.totalBorrowShares);
uint256 borrowedAssets = position.borrowShares * assetRatio;
uint256 collateralPrice = IOracle(s.config.oracle).getCollateralToLoanPrice();
uint256 maxBorrowLimit = position.collateral
.mulDiv((collateralPrice * s.config.lltv), PoolConstants.ORACLE_PRICE_SCALE);
return maxBorrowLimit >= borrowedAssets;
}Impact
Because the function toAssetsUp adds VIRTUAL_ASSETS to the totalAssets and adds VIRTUAL_SHARES to the totalShares, the results of formula PoolConstants.WAD.toAssetUp(s.totalBorrowAssets, s.totalBorrowShares) and formula s.totalBorrowAssets.toAssetUp(PoolConstants.WAD, s.totalBorrowShares) may differ slightly.
function toAssetsUp(uint256 shares, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {
return shares.mulDiv(totalAssets + VIRTUAL_ASSETS, totalShares + VIRTUAL_SHARES, Math.Rounding.Ceil);
}This will affect the calculation of the borrowedAssets and further impact the assessment of the position's health status.
Recommendations
Consider updating based on the following code:
-uint256 assetRatio = s.totalBorrowAssets.toAssetsUp(PoolConstants.WAD, s.totalBorrowShares);
+uint256 assetRatio = uint256(PoolConstants.WAD).toAssetsUp(s.totalBorrowAssets, s.totalBorrowShares);