Fraxlend (Frax Finance) contest - ajtra's results

Fraxlend: A permissionless lending platform and the final piece of the Frax Finance Defi Trinity.

General Information

Platform: Code4rena

Start Date: 12/08/2022

Pot Size: $50,000 USDC

Total HM: 15

Participants: 120

Period: 5 days

Judge: Justin Goro

Total Solo HM: 6

Id: 153

League: ETH

Frax Finance

Findings Distribution

Researcher Performance

Rank: 77/120

Findings: 1

Award: $50.02

🌟 Selected for report: 0

🚀 Solo Findings: 0

Index

  1. Post-increment/decrement cost more gas then pre-increment/decrement
  2. Array length should not be looked up in every loop of a for-loop
  3. Operatos <= or >= cost more gas than operators < or >
  4. != 0 is cheaper than > 0
  5. Variable1 = Variable1 + (-) Variable2 is cheaper in gas cost than variable1 += (-=) variable2.
  6. Require / Revert strings longer than 32 bytes cost extra gas
  7. Use custom errors rather than REVERT()/REQUIRE() strings to save deployment gas
  8. Usage of uints/ints smaller than 32 Bytes (256 bits) incurs overhead
  9. Initialize variables with default values are not needed
  10. Using bools for storage incurs overhead
  11. ABI.ENCODE() is less efficient than ABI.ENCODEPACKED()
  12. Use unchecked when it's not possible to overflow
  13. Calldata vs Memory
  14. Use bytes32 instead of string
  15. Reordering code to save gas
  16. Parameter not used in the function

Details

1. Post-increment/decrement cost more gas then pre-increment/decrement

Description

++var (--var) cost less gas than var++ (var--)

Lines in the code

SafeERC20.sol#L24 SafeERC20.sol#L27 FraxlendWhitelist.sol#L51 FraxlendWhitelist.sol#L66 FraxlendWhitelist.sol#L81 FraxlendPair.sol#L289 FraxlendPair.sol#L308 FraxlendPairDeployer.sol#L130 FraxlendPairDeployer.sol#L158

2. Array length should not be looked up in every loop of a for-loop

Description

Storage array length checks incur an extra Gwarmaccess (100 gas) per loop. Store the array length in a variable and use it in the for loop helps to save gas

Lines in the code

FraxlendWhitelist.sol#L51 FraxlendWhitelist.sol#L66 FraxlendWhitelist.sol#L81 FraxlendPairCore.sol#L265 FraxlendPairCore.sol#L270 FraxlendPair.sol#L289 FraxlendPair.sol#L308

3. Operatos <= or >= cost more gas than operators < or >

Description

Change all <= / >= operators for < / > and remember to increse / decrese in consecuence to maintain the logic (example, a <= b for a < b + 1)

Lines in the code

SafeERC20.sol#L19 LinearInterestRate.sol#L58 LinearInterestRate.sol#L62 FraxlendPairCore.sol#L196 FraxlendPairCore.sol#L315 FraxlendPairCore.sol#L472 FraxlendPairCore.sol#L473 FraxlendPairCore.sol#L525 FraxlendPairCore.sol#L533 FraxlendPairCore.sol#L988 FraxlendPairCore.sol#L1000 FraxlendPairDeployer.sol#L365 FraxlendPairHelper.sol#L134 FraxlendPairHelper.sol#L142 FraxlendPairHelper.sol#L284 FraxlendPairHelper.sol#L292

4. != 0 is cheaper than > 0

Description

Replace all > 0 for != 0

Lines in the code

LinearInterestRate.sol#L66 FraxlendPairCore.sol#L477 FraxlendPairCore.sol#L754 FraxlendPairCore.sol#L835 FraxlendPairCore.sol#L1002 FraxlendPairCore.sol#L1094 FraxlendPairDeployer.sol#L379 FraxlendPairDeployer.sol#L380 FraxlendPairHelper.sol#L235 FraxlendPairHelper.sol#L292

5. Variable1 = Variable1 + (-) Variable2 is cheaper in gas cost than variable1 += (-=) variable2.

Description

Lines in the code

FraxlendPairCore.sol#L475 FraxlendPairCore.sol#L476 FraxlendPairCore.sol#L484 FraxlendPairCore.sol#L566 FraxlendPairCore.sol#L567 FraxlendPairCore.sol#L643 FraxlendPairCore.sol#L644 FraxlendPairCore.sol#L718 FraxlendPairCore.sol#L719 FraxlendPairCore.sol#L724 FraxlendPairCore.sol#L772 FraxlendPairCore.sol#L773 FraxlendPairCore.sol#L813 FraxlendPairCore.sol#L815 FraxlendPairCore.sol#L863 FraxlendPairCore.sol#L864 FraxlendPairCore.sol#L867 FraxlendPairCore.sol#L1008 FraxlendPairCore.sol#L1011 FraxlendPairCore.sol#L1012 FraxlendPair.sol#L252 FraxlendPair.sol#L253

6. Require / Revert strings longer than 32 bytes cost extra gas

Description

Each extra memory word of bytes past the original 32 incurs an MSTORE which costs 3 gas

Lines in the code

LinearInterestRate.sol#L57 LinearInterestRate.sol#L61 LinearInterestRate.sol#L65 FraxlendPairDeployer.sol#L205 FraxlendPairDeployer.sol#L228 FraxlendPairDeployer.sol#L253 FraxlendPairDeployer.sol#L365 FraxlendPairDeployer.sol#L366

7. Use custom errors rather than REVERT()/REQUIRE() strings to save deployment gas

Description

Custom errors are available from solidity version 0.8.4. Custom errors save ~50 gas each time they�re hitby avoiding having to allocate and store the revert string. Not defining the strings also save deployment gas.

Lines in the code

LinearInterestRate.sol#L52 LinearInterestRate.sol#L57 LinearInterestRate.sol#L61 LinearInterestRate.sol#L65 FraxlendPairDeployer.sol#L205 FraxlendPairDeployer.sol#L228 FraxlendPairDeployer.sol#L253 FraxlendPairDeployer.sol#L365 FraxlendPairDeployer.sol#L366 FraxlendPairDeployer.sol#L399

8. Usage of uints/ints smaller than 32 Bytes (256 bits) incurs overhead

Description

When using elements that are smaller than 32 bytes, your contract's gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size. Use a larger size then downcast where needed

Lines in the code

SafeERC20.sol#L22 SafeERC20.sol#L55 SafeERC20.sol#L57 VaultAccount.sol#L5 VaultAccount.sol#L6 LinearInterestRate.sol#L76 LinearInterestRate.sol#L78 LinearInterestRate.sol#L85 LinearInterestRate.sol#L88 LinearInterestRate.sol#L90 VariableInterestRate.sol#L35 VariableInterestRate.sol#L36 VariableInterestRate.sol#L37 VariableInterestRate.sol#L40 VariableInterestRate.sol#L41 VariableInterestRate.sol#L63 VariableInterestRate.sol#L64 VariableInterestRate.sol#L66 VariableInterestRate.sol#L71 VariableInterestRate.sol#L78 FraxlendPairConstants.sol#L41 FraxlendPairConstants.sol#L47 FraxlendPairCore.sol#L106 FraxlendPairCore.sol#L107 FraxlendPairCore.sol#L108 FraxlendPairCore.sol#L109 FraxlendPairCore.sol#L116 FraxlendPairCore.sol#L117 FraxlendPairCore.sol#L400 FraxlendPairCore.sol#L415 FraxlendPairCore.sol#L434 FraxlendPairCore.sol#L435 FraxlendPairCore.sol#L448 FraxlendPairCore.sol#L464 FraxlendPairCore.sol#L465 FraxlendPairCore.sol#L472 FraxlendPairCore.sol#L473 FraxlendPairCore.sol#L475 FraxlendPairCore.sol#L476 FraxlendPairCore.sol#L484 FraxlendPairCore.sol#L542 FraxlendPairCore.sol#L543 FraxlendPairCore.sol#L544 FraxlendPairCore.sol#L561 FraxlendPairCore.sol#L562 FraxlendPairCore.sol#L594 FraxlendPairCore.sol#L613 FraxlendPairCore.sol#L625 FraxlendPairCore.sol#L626 FraxlendPairCore.sol#L668 FraxlendPairCore.sol#L684 FraxlendPairCore.sol#L707 FraxlendPairCore.sol#L719 FraxlendPairCore.sol#L757 FraxlendPairCore.sol#L857 FraxlendPairCore.sol#L858 FraxlendPairCore.sol#L886 FraxlendPairCore.sol#L937 FraxlendPairCore.sol#L951 FraxlendPairCore.sol#L967 FraxlendPairCore.sol#L993 FraxlendPairCore.sol#L997 FraxlendPairCore.sol#L998 FraxlendPairCore.sol#L1001 FraxlendPairCore.sol#L1005 FraxlendPairCore.sol#L1100 FraxlendPairCore.sol#L1209 FraxlendPair.sol#L84 FraxlendPair.sol#L137 FraxlendPair.sol#L141 FraxlendPair.sol#L165 FraxlendPair.sol#L166 FraxlendPair.sol#L211 FraxlendPair.sol#L215 FraxlendPair.sol#L228 FraxlendPair.sol#L234 FraxlendPair.sol#L240 FraxlendPair.sol#L252 FraxlendPairHelper.sol#L54 FraxlendPairHelper.sol#L55 FraxlendPairHelper.sol#L56 FraxlendPairHelper.sol#L57 FraxlendPairHelper.sol#L112 FraxlendPairHelper.sol#L113 FraxlendPairHelper.sol#L114 FraxlendPairHelper.sol#L115 FraxlendPairHelper.sol#L133 FraxlendPairHelper.sol#L141 FraxlendPairHelper.sol#L161 FraxlendPairHelper.sol#L166 FraxlendPairHelper.sol#L180 FraxlendPairHelper.sol#L182 FraxlendPairHelper.sol#L198 FraxlendPairHelper.sol#L232 FraxlendPairHelper.sol#L234 FraxlendPairHelper.sol#L243 FraxlendPairHelper.sol#L249 FraxlendPairHelper.sol#L251 FraxlendPairHelper.sol#L252 FraxlendPairHelper.sol#L259 FraxlendPairHelper.sol#L264 FraxlendPairHelper.sol#L267 FraxlendPairHelper.sol#L289 FraxlendPairHelper.sol#L295

9. Initialize variables with default values are not needed

Description

If a variable is not set/initialized, it is assumed to have the default value (0 for uint, false for bool, address(0) for address,etc). Explicitly initializing it with its default value is an anti-pattern and wastes gas.

Lines in the code

SafeERC20.sol#L22 FraxlendWhitelist.sol#L51 FraxlendWhitelist.sol#L66 FraxlendWhitelist.sol#L81 FraxlendPairCore.sol#L265 FraxlendPairCore.sol#L270 FraxlendPair.sol#L289 FraxlendPair.sol#L308 FraxlendPairDeployer.sol#L402

10. Using bools for storage incurs overhead

Description

Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas), and to avoid Gsset (20000 gas) when changing from 'false' to 'true', after having been 'true' in the past

Lines in the code

FraxlendWhitelist.sol#L32 FraxlendWhitelist.sol#L35 FraxlendWhitelist.sol#L38 FraxlendPairCore.sol#L78 FraxlendPairCore.sol#L133 FraxlendPairCore.sol#L134 FraxlendPairCore.sol#L136 FraxlendPairCore.sol#L137 FraxlendPairDeployer.sol#L94 FraxlendPairDeployer.sol#L138 FraxlendPairHelper.sol#L33 FraxlendPairHelper.sol#L34

11. ABI.ENCODE() is less efficient than ABI.ENCODEPACKED()

Lines in the code

LinearInterestRate.sol#L47 VariableInterestRate.sol#L53 FraxlendPairCore.sol#L450 FraxlendPairDeployer.sol#L213 FraxlendPairDeployer.sol#L331 FraxlendPairDeployer.sol#L374 FraxlendPairHelper.sol#L201

12. Use unchecked when it's not possible to overflow

Description

++i/i++ should be unchecked{++i}/unchecked{i++} when it is not possible for them to overflow, as is the case when used in for- and while-loops

Lines in the code

SafeERC20.sol#L24 SafeERC20.sol#L27 FraxlendWhitelist.sol#L51 FraxlendWhitelist.sol#L66 FraxlendWhitelist.sol#L81 FraxlendPairCore.sol#L265 FraxlendPairCore.sol#L270 FraxlendPair.sol#L289 FraxlendPair.sol#L308

13. Calldata vs Memory

Description

Use calldata instead of memory in a function parameter when you are only to read the data can save gas by storing it in calldata

Lines in the code

FraxlendPairCore.sol#L295 FraxlendPairDeployer.sol#L310 FraxlendPairDeployer.sol#L398

14. Use bytes32 instead of string

Description

Use bytes32 instead of string when it's possible to save some gas'

Lines in the code

FraxlendPairCore.sol#L51 FraxlendPairCore.sol#L92

15. Reordering code to save gas

Description

FraxlendPairHelper.previewUpdateExchangeRate

Move the following lines after the if's sentences and before it's use. (-). Remove the line (+). Add the line

    function previewUpdateExchangeRate(address _fraxlendPairAddress) public view returns (uint256 _exchangeRate) {
        IFraxlendPair _fraxlendPair = IFraxlendPair(_fraxlendPairAddress);
        address _oracleMultiply = _fraxlendPair.oracleMultiply();
-       address _oracleDivide = _fraxlendPair.oracleDivide();
-       uint256 _oracleNormalization = _fraxlendPair.oracleNormalization();

        uint256 _price = uint256(1e36);
        if (_oracleMultiply != address(0)) {
            (, int256 _answer, , , ) = AggregatorV3Interface(_oracleMultiply).latestRoundData();
            if (_answer <= 0) {
                revert OracleLTEZero(_oracleMultiply);
            }
            _price = _price * uint256(_answer);
        }

+       address _oracleDivide = _fraxlendPair.oracleDivide();
        if (_oracleDivide != address(0)) {
            (, int256 _answer, , , ) = AggregatorV3Interface(_oracleDivide).latestRoundData();
            if (_answer <= 0) {
                revert OracleLTEZero(_oracleDivide);
            }
            _price = _price / uint256(_answer);
        }
+       uint256 _oracleNormalization = _fraxlendPair.oracleNormalization();
        _exchangeRate = _price / _oracleNormalization;
    }

FraxlendPairHelper.sol#L125-L149

FraxlendPairCore.repayAssetWithCollateral

Move the line IERC20 _assetContract = assetContract; from line 1167 to line 1175 before it use.

FraxlendPairCore.sol#L1167

16. Parameter not used in the function

Description

Remove the parameter _initData in VariableInterestRate.getNewRate._initData because of it's not used in the function.

Lines in the code

VariableInterestRate.sol#L35

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter