Assessment reports>Avon>Medium findings>Incorrect borrowed assets calculation in the function ,_isPositionSafe
Category: Coding Mistakes

Incorrect borrowed assets calculation in the function _isPositionSafe

Medium Impact
Medium Severity
Medium Likelihood

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

Remediation

Zellic © 2025Back to top ↑