Platform: Code4rena
Start Date: 25/08/2022
Pot Size: $75,000 USDC
Total HM: 35
Participants: 147
Period: 7 days
Judge: 0xean
Total Solo HM: 15
Id: 156
League: ETH
Rank: 81/147
Findings: 2
Award: $86.90
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: zzzitron
Also found by: 0x040, 0x1f8b, 0x52, 0x85102, 0xDjango, 0xNazgul, 0xNineDec, 0xSky, 0xSmartContract, 0xkatana, 8olidity, Aymen0909, Bahurum, BipinSah, Bnke0x0, CRYP70, CertoraInc, Ch_301, Chandr, Chom, CodingNameKiki, Deivitto, DimSon, Diraco, ElKu, EthLedger, Funen, GalloDaSballo, Guardian, IllIllI, JansenC, Jeiwan, Lambda, LeoS, Margaret, MasterCookie, PPrieditis, PaludoX0, Picodes, PwnPatrol, RaymondFam, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, StevenL, The_GUILD, TomJ, Tomo, Trust, Waze, __141345__, ajtra, ak1, apostle0x01, aviggiano, bin2chen, bobirichman, brgltd, c3phas, cRat1st0s, carlitox477, cccz, ch13fd357r0y3r, cloudjunky, cryptphi, csanuragjain, d3e4, datapunk, delfin454000, devtooligan, dipp, djxploit, durianSausage, eierina, enckrish, erictee, fatherOfBlocks, gogo, grGred, hansfriese, hyh, ignacio, indijanc, itsmeSTYJ, ladboy233, lukris02, martin, medikko, mics, natzuu, ne0n, nxrblsrpr, okkothejawa, oyc_109, p_crypt0, pfapostol, prasantgupta52, rajatbeladiya, rbserver, reassor, ret2basic, robee, rokinot, rvierdiiev, shenwilly, sikorico, sorrynotsorry, tnevler, tonisives, w0Lfrum, yixxas
54.3187 DAI - $54.32
VOTES.sol
Line 45-48
The return code line is unreachable because the previous line of code would revert preventing the function from returning true, which is understandably done in deliberation.
The function could be refactored as follows with a good side effect of reducing the contract size:
function transfer(address to_, uint256 amount_) public pure override returns (bool) { revert VOTES_TransferDisabled(); }
PRICE.sol
Line 126
numbe is missing an "r"
PRICE.sol
Line 58-59
PRICE.sol
Line 82-91
ohmEthDecimals
is already 18 decimals long as could be vividly verified on Chainlink Data Feeds for OHMv2 / ETH pair. Lines 84 & 89 can be omitted since exponent is always equal to reserveEthDecimals
considering decimals - ohmEthDecimals
is going to be zero. As such, Lines 90-91 could be rewritten as follows:
if (reserveEthDecimals > 38) revert Price_InvalidParams(); _scaleFactor = 10**exponent;
Note: Variable decimals
at line 59 cannot be deleted since it's being called/referenced by Operator.sol.
The if condition for cushionDebtBuffer should ensure the input parameter should not exceed 100% (percent with 3 decimals, i.e. 100_000 = 100 %) just like it has been included for reserveFactor. Hence, the following two code lines should be refactored as follows:
OPERATOR.sol
Line 106
if ( configParams[2] > uint32(100_000) || [2] < uint32(10_000)) revert Operator_InvalidParams();
OPERATOR.sol
Line 535
if (debtBuffer_ > uint32(100_000) || debtBuffer_ < uint32(10_000)) revert Operator_InvalidParams();
The constructor did not check whether or not the first elements of configParams is valid. Although it could be set later in function setCushionFactor just like all other params, the following code line should be inserted at line 102 or anywhere deemed appropriate in the constructor:
if (configParams[0] > 10000 || configParams[0]< 100) revert Operator_InvalidParams();
#0 - ind-igo
2022-09-09T05:01:19Z
good report, thank you
🌟 Selected for report: pfapostol
Also found by: 0x040, 0x1f8b, 0x85102, 0xDjango, 0xNazgul, 0xNineDec, 0xSmartContract, 0xkatana, Amithuddar, Aymen0909, Bnke0x0, CertoraInc, Chandr, CodingNameKiki, Deivitto, Dionysus, Diraco, ElKu, Fitraldys, Funen, GalloDaSballo, Guardian, IllIllI, JC, JansenC, Jeiwan, LeoS, Metatron, Noah3o6, RaymondFam, ReyAdmirado, Rohan16, RoiEvenHaim, Rolezn, Ruhum, Saintcode_, Shishigami, Sm4rty, SooYa, StevenL, Tagir2003, The_GUILD, TomJ, Tomo, Waze, __141345__, ajtra, apostle0x01, aviggiano, bobirichman, brgltd, c3phas, cRat1st0s, carlitox477, cccz, ch0bu, chrisdior4, d3e4, delfin454000, djxploit, durianSausage, erictee, exolorkistis, fatherOfBlocks, gogo, grGred, hyh, ignacio, jag, karanctf, kris, ladboy233, lukris02, m_Rassska, martin, medikko, natzuu, ne0n, newfork01, oyc_109, peiw, rbserver, ret2basic, robee, rokinot, rvierdiiev, sikorico, simon135, tnevler, zishansami
32.5835 DAI - $32.58
https://github.com/code-423n4/2022-08-olympus/blob/main/src/utils/KernelUtils.sol#L49 https://github.com/code-423n4/2022-08-olympus/blob/main/src/utils/KernelUtils.sol#L64 https://github.com/code-423n4/2022-08-olympus/blob/main/src/policies/Operator.sol#L488 https://github.com/code-423n4/2022-08-olympus/blob/main/src/policies/Operator.sol#L670 https://github.com/code-423n4/2022-08-olympus/blob/main/src/policies/Operator.sol#L686
The above code lines should adopt ++i instead of i++. The post-increment (i++) operation costs more (about 5 GAS per iteration), because the compiler typically has to create a temporary variable for returning the initial value of i when incrementing i . In contrast, the pre-increment (++i) operation simply returns the actual incremented value of i without the need for a temporary variable. The saving impact is particularly prominent when dealing with loops.
Instead of using the && operator in a single if statement to check multiple conditions, using multiple if statements with 1 condition per if statement will save 3 GAS per &&. For instance, the following block of codes could be rewritten as follows:
https://github.com/code-423n4/2022-08-olympus/blob/main/src/modules/RANGE.sol#L133-L139
if (capacity_ < _range.high.threshold) { if (_range.high.active) { // Set wall to inactive _range.high.active = false; _range.high.lastActive = uint48(block.timestamp); emit WallDown(true, block.timestamp, capacity_); } }
https://github.com/code-423n4/2022-08-olympus/blob/main/src/Kernel.sol#L439 https://github.com/code-423n4/2022-08-olympus/blob/main/src/Kernel.sol#L451 https://github.com/code-423n4/2022-08-olympus/blob/main/src/modules/TRSRY.sol#L75 https://github.com/code-423n4/2022-08-olympus/blob/main/src/modules/MINTR.sol#L33 https://github.com/code-423n4/2022-08-olympus/blob/main/src/modules/MINTR.sol#L37 https://github.com/code-423n4/2022-08-olympus/blob/main/src/modules/RANGE.sol#L219 https://github.com/code-423n4/2022-08-olympus/blob/main/src/modules/VOTES.sol#L45 https://github.com/code-423n4/2022-08-olympus/blob/main/src/modules/VOTES.sol#L55 https://github.com/code-423n4/2022-08-olympus/blob/main/src/modules/INSTR.sol#L37 https://github.com/code-423n4/2022-08-olympus/blob/main/src/policies/Governance.sol#L145 https://github.com/code-423n4/2022-08-olympus/blob/main/src/policies/Governance.sol#L151
The above above function not internally called may have its visibility changed to external.
The contract in PRICE.sol packs multiple types into one storage slot (lines 44 - 62). However, if you are not reading or writing all the values at the same time, this can have the opposite effect. 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 to properly enforce the limits of this smaller type.
https://github.com/code-423n4/2022-08-olympus/blob/main/src/Kernel.sol#L397
In the example code line above, initializing i by assigning zero to it, i = 0, is unnecessary as it has been set to zeros by default. Doing this costs extra gas.