Platform: Code4rena
Start Date: 14/09/2022
Pot Size: $50,000 USDC
Total HM: 25
Participants: 110
Period: 5 days
Judge: hickuphh3
Total Solo HM: 9
Id: 162
League: ETH
Rank: 92/110
Findings: 1
Award: $16.18
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: pfapostol
Also found by: 0x040, 0x1f8b, 0x4non, 0xNazgul, 0xSmartContract, 0xc0ffEE, 0xkatana, Aymen0909, Bnke0x0, Deivitto, Diana, JAGADESH, KIntern_NA, Lambda, MiloTruck, R2, RaymondFam, Respx, ReyAdmirado, Rohan16, RoiEvenHaim, Rolezn, Ruhum, Saintcode_, Samatak, Sm4rty, SnowMan, Tomio, Tomo, WilliamAmbrozic, _Adam, __141345__, ajtra, ak1, async, c3phas, ch0bu, cryptostellar5, d3e4, delfin454000, dharma09, djxploit, durianSausage, eierina, erictee, fatherOfBlocks, gianganhnguyen, gogo, ignacio, imare, jag, jonatascm, leosathya, lukris02, malinariy, oyc_109, pashov, pauliax, peanuts, peiw, prasantgupta52, robee, rokinot, rotcivegaf, rvierdiiev, seyni, simon135, slowmoses, sryysryy, tnevler, zishansami
16.1756 USDC - $16.18
Title: Set as immutable
can save gas
Proof of Concept: RewardsFactory.sol#L9-L11 PegOracle.sol#L10-L11
Recommended Mitigation Steps: can be set as immutable, which already set once in the constructor
Title: abi.encode() is less efficient than abi.encodePacked()
Proof of Concept: RewardsFactory.sol#L150
Title: Using SafeMath for solidity >0.8
Proof of Concept: StakingRewards.sol#L29
Recommended Mitigation Steps:
it's better to remove using SafeMath for uint256
for solidity >0.8
reference: https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2465
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: StakingRewards.sol#L36 Vault.sol#L443
Recommended Mitigation Steps: Remove explicit initialization for default values.
Title: Using !=
is more gas efficient in require
statement
Proof of Concept: StakingRewards.sol#L119 PegOracle.sol#L98 PegOracle.sol#L121 Vault.sol#L187
Recommended Mitigation Steps:
Change from > 0
to != 0
Title: Comparison operators
Proof of Concept: StakingRewards.sol#L189
Recommended Mitigation Steps:
Replace <=
with <
, and >=
with >
for gas optimization
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: StakingRewards.sol (various line) PegOracle.sol (various line) SemiFungibleVault.sol#L118
Recommended Mitigation Steps: Replace require statements with custom errors.
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: StakingRewards.sol#L228 SemiFungibleVault.sol#L118
Recommended Mitigation Steps: Consider shortening the revert strings to fit in 32 bytes
Title: Consider make constant as private to save gas
Proof of Concept: Controller.sol#L16
Recommended Mitigation Steps:
I suggest changing the visibility from public
to internal
or private
Title: Using == false
cost more gas
Proof of Concept: Controller.sol#L93 Vault.sol#L217 Controller.sol#L211
Recommended Mitigation Steps: Change to:
require(!vault.idExists(epochEnd));
Title: Using *=
can save gas
Proof of Concept: PegOracle.sol#L74 Controller.sol#L300
Recommended Mitigation Steps: Change to:
nowPrice *= decimals10;
Title: Using unchecked and prefix increment is more effective for gas saving:
Proof of Concept: Vault.sol#L443
Recommended Mitigation Steps: Change to:
for (uint256 i = 0; i < epochsLength();) { // ... unchecked { ++i; } }