15,000 USDC
View results
Submission Details
Severity: gas

Inefficient for loops

Summary

The finding primarily focuses on optimizing gas usage by addressing inefficiencies related to the usage of .length in various functions within the contract.

Vulnerability Details

The audit identified an inefficiency in the contract's usage of .length in multiple functions, leading to increased gas consumption. Specifically, the .length property is being accessed repeatedly within loops, such as in the functions like getAccountCollateralValue(), which is called and read from _getAccountInformation(), _healthFactor(), and _revertIfHealthFactorIsBroken().

Example in constructor:

function getAccountCollateralValue(address user) public view returns (uint256 totalCollateralValueInUsd) {
// loop through each collateral token, get the amount they have deposited, and map it to
// the price, to get the USD value
for (uint256 i = 0; i < s_collateralTokens.length; i++) {
address token = s_collateralTokens[i];
uint256 amount = s_collateralDeposited[user][token];
totalCollateralValueInUsd += getUsdValue(token, amount);
}
return totalCollateralValueInUsd;
}

The getAccountCollateralValue() function is designed to calculate the total value of collateral deposited by a specific user. The function iterates through each collateral token registered in the protocol, fetches the amount of that token deposited by the user, and then maps it to the corresponding price to calculate the total value in USD. However, the inefficiency arises from the repeated use of the .length property to access the size of the s_collateralTokens array in every iteration. This means that the function reads the array length from storage multiple times, leading to unnecessary SLOAD(storage read) operations and increased gas costs for each iteration. As a result, when this function is called frequently or thes_collateralTokens` array becomes large, the cumulative gas cost can have a notable impact on the overall performance of the contract and may lead to higher transaction fees for users interacting with the protocol.

Impact

The inefficient usage of .length within loops results in higher gas consumption, which can lead to increased transaction costs and hinder the overall scalability of the DSC system. While this issue does not pose a direct security vulnerability, it can have a substantial impact on gas efficiency, especially during periods of high network congestion or gas prices.

Tools Used

VSCode, Foundry

Recommendations

To optimize gas usage and improve the overall efficiency of the DSCEngine contract, we recommend caching the .length value in local variables before entering loops where it is repeatedly accessed. This approach will reduce the repetitive lookups to .length and significantly enhance gas consumption efficiency.

Example of fix in getAccountCollateralValue

function getAccountCollateralValue(address user) public view returns (uint256 totalCollateralValueInUsd) {
uint256 collateralTokenCount = s_collateralTokens.length; // Cache the array length
for (uint256 i = 0; i < collateralTokenCount; i++) {
address token = s_collateralTokens[i];
uint256 amount = s_collateralDeposited[user][token];
totalCollateralValueInUsd += getUsdValue(token, amount);
}
return totalCollateralValueInUsd;
}

To optimize the getAccountCollateralValue function and reduce the repetitive storage reads of the array length, we can follow the cache-first approach. Instead of accessing the .length property in each iteration, we will cache the array length before entering the loop using collateralTokenCount. By caching the array length outside the loop, we avoid repetitive storage reads and reduce the gas cost of executing the function. The gas savings can be significant, especially when the s_collateralTokens array is large or when the function is called frequently.

Support

FAQs

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