15,000 USDC
View results
Submission Details
Severity: gas

GAS REPORTS

Report

Gas Optimizations

Issue Instances
GAS-1 Cache array length outside of loop 2
GAS-2 For Operations that will not overflow, you could use unchecked 53
GAS-3 Don't initialize variables with default value 2
GAS-4 Functions guaranteed to revert when called by normal users can be marked payable 2
GAS-5 ++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too) 2

[GAS-1] Cache array length outside of loop

If not cached, the solidity compiler will always read the length of the array during each iteration. That is, if it is a storage array, this is an extra sload operation (100 additional extra gas for each iteration except for the first) and if it is a memory array, this is an extra mload operation (3 additional gas for each iteration except for the first).

Instances (2):

File: src/DSCEngine.sol
​
118: for (uint256 i = 0; i < tokenAddresses.length; i++) {
​
353: for (uint256 i = 0; i < s_collateralTokens.length; i++) {
​

[GAS-2] For Operations that will not overflow, you could use unchecked

Instances (53):

File: src/DSCEngine.sol
​
26: import {DecentralizedStableCoin} from "./DecentralizedStableCoin.sol";
​
27: import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
​
27: import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
​
27: import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
​
28: import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
​
28: import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
​
28: import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
​
28: import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
​
29: import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
​
29: import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
​
29: import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
​
29: import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
​
29: import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
​
30: import {OracleLib} from "./libraries/OracleLib.sol";
​
30: import {OracleLib} from "./libraries/OracleLib.sol";
​
72: uint256 private constant LIQUIDATION_THRESHOLD = 50; // 200% overcollateralized
​
72: uint256 private constant LIQUIDATION_THRESHOLD = 50; // 200% overcollateralized
​
75: uint256 private constant LIQUIDATION_BONUS = 10; // this means a 10% bonus
​
75: uint256 private constant LIQUIDATION_BONUS = 10; // this means a 10% bonus
​
77: mapping(address token => address priceFeed) private s_priceFeeds; // tokenToPriceFeed
​
77: mapping(address token => address priceFeed) private s_priceFeeds; // tokenToPriceFeed
​
118: for (uint256 i = 0; i < tokenAddresses.length; i++) {
​
118: for (uint256 i = 0; i < tokenAddresses.length; i++) {
​
155: s_collateralDeposited[msg.sender][tokenCollateralAddress] += amountCollateral;
​
198: s_DSCMinted[msg.sender] += amountDscToMint;
​
214: _revertIfHealthFactorIsBroken(msg.sender); // I don't think this would ever hit...
​
214: _revertIfHealthFactorIsBroken(msg.sender); // I don't think this would ever hit...
​
251: uint256 bonusCollateral = (tokenAmountFromDebtCovered * LIQUIDATION_BONUS) / LIQUIDATION_PRECISION;
​
251: uint256 bonusCollateral = (tokenAmountFromDebtCovered * LIQUIDATION_BONUS) / LIQUIDATION_PRECISION;
​
252: uint256 totalCollateralToRedeem = tokenAmountFromDebtCovered + bonusCollateral;
​
273: s_DSCMinted[onBehalfOf] -= amountDscToBurn;
​
285: s_collateralDeposited[from][tokenCollateralAddress] -= amountCollateral;
​
330: uint256 collateralAdjustedForThreshold = (collateralValueInUsd * LIQUIDATION_THRESHOLD) / LIQUIDATION_PRECISION;
​
330: uint256 collateralAdjustedForThreshold = (collateralValueInUsd * LIQUIDATION_THRESHOLD) / LIQUIDATION_PRECISION;
​
331: return (collateralAdjustedForThreshold * 1e18) / totalDscMinted;
​
331: return (collateralAdjustedForThreshold * 1e18) / totalDscMinted;
​
347: return (usdAmountInWei * PRECISION) / (uint256(price) * ADDITIONAL_FEED_PRECISION);
​
347: return (usdAmountInWei * PRECISION) / (uint256(price) * ADDITIONAL_FEED_PRECISION);
​
347: return (usdAmountInWei * PRECISION) / (uint256(price) * ADDITIONAL_FEED_PRECISION);
​
353: for (uint256 i = 0; i < s_collateralTokens.length; i++) {
​
353: for (uint256 i = 0; i < s_collateralTokens.length; i++) {
​
356: totalCollateralValueInUsd += getUsdValue(token, amount);
​
366: return ((uint256(price) * ADDITIONAL_FEED_PRECISION) * amount) / PRECISION;
​
366: return ((uint256(price) * ADDITIONAL_FEED_PRECISION) * amount) / PRECISION;
​
366: return ((uint256(price) * ADDITIONAL_FEED_PRECISION) * amount) / PRECISION;
​
File: src/DecentralizedStableCoin.sol
​
26: import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
​
26: import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
​
26: import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
​
26: import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
​
26: import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
​
27: import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
​
27: import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
​
27: import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
​

[GAS-3] Don't initialize variables with default value

Instances (2):

File: src/DSCEngine.sol
​
118: for (uint256 i = 0; i < tokenAddresses.length; i++) {
​
353: for (uint256 i = 0; i < s_collateralTokens.length; i++) {
​

[GAS-4] Functions guaranteed to revert when called by normal users can be marked payable

If a function modifier such as onlyOwner is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided.

Instances (2):

File: src/DecentralizedStableCoin.sol
​
46: function burn(uint256 _amount) public override onlyOwner {
​
57: function mint(address _to, uint256 _amount) external onlyOwner returns (bool) {
​

[GAS-5] ++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too)

Saves 5 gas per loop

Instances (2):

File: src/DSCEngine.sol
​
118: for (uint256 i = 0; i < tokenAddresses.length; i++) {
​
353: for (uint256 i = 0; i < s_collateralTokens.length; i++) {
​

Low Issues

Issue Instances
L-1 Empty Function Body - Consider commenting why 1

[L-1] Empty Function Body - Consider commenting why

Instances (1):

File: src/DecentralizedStableCoin.sol
​
44: constructor() ERC20("DecentralizedStableCoin", "DSC") {}
​

Support

FAQs

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

Give us feedback!