15,000 USDC
View results
Submission Details
Severity: gas
Valid

Use do while loops instead of for loops.

Summary

You can use do while loops instead of for loops to save gas.

Vulnerability Details

A do while loop will cost less gas since the condition is not being checked for the first iteration. Also, using do while loop with ++i is more gas efficient and wrapping ++i with unchecked keyword makes the whole iteration the most gas efficient of all. Also, the i is not initialized to 0 and the length of loop is cached.

Savings

There are two instances of for loops in the DSCEnginge.sol contract.

  1. Savings for getAccountCollateralValue() can be up to 373 gas:

Average Median Max
Before 42356 42356 42356
After 41983 41983 41983
  1. Savings for constructor can be up to 7381 gas:

Deployment Cost
Before 1004332
After 996951

Tools Used

Manual Review and gas report via $ forge test --gas-report

Recommendations

  1. For getAccountCollateralValue() change from:

/src/DSCEngine.sol
353: for (uint256 i = 0; i < s_collateralTokens.length; i++) {
354: address token = s_collateralTokens[i];
355: uint256 amount = s_collateralDeposited[user][token];
356: totalCollateralValueInUsd += getUsdValue(token, amount);
357: }

To:

/src/DSCEngine.sol
uint256 len = s_collateralTokens.length;
uint256 i;
do {
address token = s_collateralTokens[i];
uint256 amount = s_collateralDeposited[user][token];
totalCollateralValueInUsd += getUsdValue(token, amount);
unchecked {
++i;
}
} while (i < len);
  1. For constructor change from:

/src/DSCEngine.sol
118: for (uint256 i = 0; i < tokenAddresses.length; i++) {
119: s_priceFeeds[tokenAddresses[i]] = priceFeedAddresses[i];
120: s_collateralTokens.push(tokenAddresses[i]);
121: }

To:

/src/DSCEngine.sol
uint256 len = tokenAddresses.length;
uint256 i;
do {
s_priceFeeds[tokenAddresses[i]] = priceFeedAddresses[i];
s_collateralTokens.push(tokenAddresses[i]);
unchecked {
++i;
}
} while (i < len);

Support

FAQs

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