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);