15,000 USDC
View results
Submission Details
Severity: medium

Possibility of inaccurate Health Factor Calculation

Summary

The function _calculateHealthFactor calculates the health factor for the system based on the provided parameters totalDscMinted and collateralValueInUsd. However, there is a risk of potential loss of precision when performing a multiplication on the result of a division operation. In Solidity, division results in truncated integers, and when used in further calculations, it can lead to inaccuracies or loss of precision in the final result.

Vulnerability Details

In this function, the multiplication (collateralValueInUsd * LIQUIDATION_THRESHOLD) / LIQUIDATION_PRECISION could suffer from a loss of precision due to the division operation right after. As a result, the health factor calculation may not be as accurate as desired, potentially leading to incorrect health factor assessments for the system.

Impact

function _calculateHealthFactor(uint256 totalDscMinted, uint256 collateralValueInUsd)
internal
pure
returns (uint256)
{
if (totalDscMinted == 0) return type(uint256).max;
uint256 collateralAdjustedForThreshold = (collateralValueInUsd * LIQUIDATION_THRESHOLD) / LIQUIDATION_PRECISION;
return (collateralAdjustedForThreshold * 1e18) / totalDscMinted;
}

Tools Used

Manual review and slither

Recommendations

We can prevent truncation and ensure accurate health factor calculation if we reorder the execution for better precision

function _calculateHealthFactor(uint256 totalDscMinted, uint256 collateralValueInUsd)
internal
pure
returns (uint256)
{
if (totalDscMinted == 0) return type(uint256).max;
// Multiply first to prevent truncation, then divide
return (collateralValueInUsd * LIQUIDATION_THRESHOLD * 1e18) / (totalDscMinted * 100);
}

we can also use a fixed-point arithmetic or utilizing libraries that support fixed-point operations. By using fixed-point arithmetic, you can maintain the desired level of precision throughout the calculation process.

// Define the number of decimal places for the fixed-point arithmetic
uint256 constant DECIMALS = 18;
function _calculateHealthFactor(uint256 totalDscMinted, uint256 collateralValueInUsd) internal pure returns (uint256) {
if (totalDscMinted == 0) return type(uint256).max;
// Convert collateralValueInUsd to a fixed-point representation
uint256 collateralInUsdFixed = collateralValueInUsd * (10**DECIMALS);
// Calculate the collateral value adjusted for the liquidation threshold with fixed-point arithmetic
uint256 collateralAdjustedForThreshold = (collateralInUsdFixed * LIQUIDATION_THRESHOLD) / LIQUIDATION_PRECISION;
// Calculate the health factor using fixed-point arithmetic
uint256 healthFactorFixed = (collateralAdjustedForThreshold * (10**DECIMALS)) / totalDscMinted;
// Convert the healthFactorFixed back to the regular representation (without decimal places)
return healthFactorFixed / (10**DECIMALS);
}

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.