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: 93/120
Findings: 1
Award: $22.05
🌟 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
22.0485 USDC - $22.05
Title: calldata
instead of memory
for RO function parameters
Impact: If a reference type function parameter is read-only, it is cheaper in gas to use calldata instead of memory. Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory.
Try to use calldata as a data location because it will avoid copies and also makes sure that the data cannot be modified.
Proof of Concept: VaultAccount.sol#L17 VaultAccount.sol#L34
Recommended Mitigation Steps:
Replace memory
with calldata
Title: Using +=
or -=
can save gas
Proof of Concept: VaultAccount.sol#L26 VaultAccount.sol#L43
Recommended Mitigation Steps: Change to:
shares += 1;
Title: Use of uint8
in for loop increases gas costs
Proof of Concept: SafeERC20.sol#L22
Recommended Mitigation Steps:
Change uint8
to uint256
Title: Default value initialization
Impact: If a variable is not set/initialized, it is assumed to have the default value (0, false, 0x0 etc depending on the data type). Explicitly initializing it with its default value is an anti-pattern and wastes gas.
Proof of Concept: SafeERC20.sol#L22 FraxlendPair.sol#L289 FraxlendPair.sol#L308
Recommended Mitigation Steps: Remove explicit initialization for default values.
Title: Using unchecked and prefix increment is more effective for gas saving:
Proof of Concept: SafeERC20.sol#L22 FraxlendPair.sol#L289 FraxlendPair.sol#L308 FraxlendPairCore.sol#L265-L270
Recommended Mitigation Steps: Change to:
for (i = 0; i < 32 && data[i] != 0;) { // ... unchecked { ++i; } }
Title: Caching length
for loop can save gas
Proof of Concept: FraxlendPair.sol#L289 FraxlendPair.sol#L308 FraxlendPairCore.sol#L265-L270
Recommended Mitigation Steps: Change to:
uint256 Length = _lenders.length; for (uint256 i = 0; i < _lenders.Length; i++) {
Title: Using storage
instead of memory
for struct can save gas
Proof of Concept: FraxlendPairCore.sol#L419 FraxlendPairCore.sol#L517
Recommended Mitigation Steps:
Replace memory
with storage
Title: Unused lib
Proof of Concept: FraxlendPairDeployer.sol#L45
Recommended Mitigation Steps: remove unused can save gas
Title: Set as constant
can save gas
Proof of Concept: FraxlendPairDeployer.sol#L49-L51
Recommended Mitigation Steps:
Change to constant
and make it private
or internal
Title: Reduce the size of error messages (Long revert Strings)
Impact: Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition is met. Revert strings that are longer than 32 bytes require at least one additional mstore, along with additional overhead for computing memory offset, etc.
Proof of Concept: FraxlendPairDeployer.sol#L205 FraxlendPairDeployer.sol#L228 FraxlendPairDeployer.sol#L253 FraxlendPairDeployer.sol#L365-L369
Recommended Mitigation Steps: Consider shortening the revert strings to fit in 32 bytes
Title: Custom errors from Solidity 0.8.4 are cheaper than revert strings
Impact: Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met) while providing the same amount of information
Custom errors are defined using the error statement reference: https://blog.soliditylang.org/2021/04/21/custom-errors/
Proof of Concept: FraxlendPairDeployer.sol#L205 FraxlendPairDeployer.sol#L228 FraxlendPairDeployer.sol#L253 FraxlendPairDeployer.sol#L365-L369
Recommended Mitigation Steps: Replace require statements with custom errors.
Title: Remove or replace unused state variable
Impact: Saves a storage slot. If the variable is assigned a non-zero value, saves Gsset (20000 gas). If it's assigned a zero value, saves Gsreset (2900 gas). If the variable remains unassigned, there is no gas savings. If the state variable is overriding an interface's public function, mark the variable as constant or immutable so that it does not use a storage slot, and manually add a getter function
Reference: here
Proof of Concept: FraxlendPairCore.sol#L51
Title: Using multiple require
instead &&
can save gas
Proof of Concept: LinearInterestRate.sol#L57-L68
Recommended Mitigation Steps: Change to:
require(_minInterest < MAX_INT, "LinearInterestRate: _minInterest < MAX_INT"); require( _minInterest <= _vertexInterest, "LinearInterestRate: _minInterest <= _vertexInterest"); require(_minInterest >= MIN_INT, "LinearInterestRate: _minInterest >= MIN_INT");
Title: Using !=
is more gas efficient in require
statement
Proof of Concept: LinearInterestRate.sol#L66
Recommended Mitigation Steps:
Change from >0
to !=
require( _vertexUtilization < MAX_VERTEX_UTIL && _vertexUtilization != 0, "LinearInterestRate: _vertexUtilization < MAX_VERTEX_UTIL && _vertexUtilization != 0" );