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
Rank: 77/120
Findings: 1
Award: $50.02
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0xA5DF, 0xDjango, 0xNazgul, 0xSmartContract, 0xackermann, 0xbepresent, 0xc0ffEE, 0xkatana, 2997ms, Amithuddar, Aymen0909, Bnke0x0, Chinmay, Chom, CodingNameKiki, Deivitto, Diraco, Dravee, ElKu, EthLedger, Fitraldys, Funen, IgnacioB, JC, Junnon, Lambda, LeoS, Metatron, MiloTruck, Noah3o6, NoamYakov, PaludoX0, Randyyy, ReyAdmirado, Rohan16, Rolezn, Ruhum, SaharAP, Sm4rty, SooYa, TomJ, Tomio, Waze, Yiko, _Adam, __141345__, a12jmx, ajtra, ak1, asutorufos, ballx, brgltd, c3phas, cRat1st0s, carlitox477, chrisdior4, d3e4, delfin454000, dharma09, djxploit, durianSausage, erictee, fatherOfBlocks, find_a_bug, flyx, francoHacker, gerdusx, gogo, gzeon, hakerbaya, ignacio, jag, kyteg, ladboy233, ltyu, m_Rassska, medikko, mics, mrpathfindr, newfork01, nxrblsrpr, oyc_109, pfapostol, rbserver, reassor, ret2basic, robee, sach1r0, saian, simon135, sryysryy, zeesaw
50.0208 USDC - $50.02
++var (--var) cost less gas than var++ (var--)
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
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
FraxlendWhitelist.sol#L51 FraxlendWhitelist.sol#L66 FraxlendWhitelist.sol#L81 FraxlendPairCore.sol#L265 FraxlendPairCore.sol#L270 FraxlendPair.sol#L289 FraxlendPair.sol#L308
Change all <= / >= operators for < / > and remember to increse / decrese in consecuence to maintain the logic (example, a <= b for a < b + 1)
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
Replace all > 0 for != 0
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
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
Each extra memory word of bytes past the original 32 incurs an MSTORE which costs 3 gas
LinearInterestRate.sol#L57 LinearInterestRate.sol#L61 LinearInterestRate.sol#L65 FraxlendPairDeployer.sol#L205 FraxlendPairDeployer.sol#L228 FraxlendPairDeployer.sol#L253 FraxlendPairDeployer.sol#L365 FraxlendPairDeployer.sol#L366
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.
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
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
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
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.
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
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
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
LinearInterestRate.sol#L47 VariableInterestRate.sol#L53 FraxlendPairCore.sol#L450 FraxlendPairDeployer.sol#L213 FraxlendPairDeployer.sol#L331 FraxlendPairDeployer.sol#L374 FraxlendPairHelper.sol#L201
++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
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
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
FraxlendPairCore.sol#L295 FraxlendPairDeployer.sol#L310 FraxlendPairDeployer.sol#L398
Use bytes32 instead of string when it's possible to save some gas'
FraxlendPairCore.sol#L51 FraxlendPairCore.sol#L92
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
Move the line IERC20 _assetContract = assetContract; from line 1167 to line 1175 before it use.
Remove the parameter _initData in VariableInterestRate.getNewRate._initData because of it's not used in the function.