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: 82/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.3128 DAI - $54.31
First QA issue - Non-assembly method available
assembly { size := extcodesize() } => uint256 size = address().code.length
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/utils/KernelUtils.sol 34: size := extcodesize(target_)
Second QA issue - Constant redefined elsewhere
Consider defining in only one contract so that values cannot become out of sync when only one location is updated. A cheap way to store constants in a single location is to create an internal constant in a library. If the variable is a local cache of another contract's value, consider making the cache variable internal or private, which will require external users to query the contract with the source of truth, so that callers don't get out of sync.
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/modules/PRICE.sol 59: uint8 public constant decimals = 18;
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Governance.sol 121: uint256 public constant SUBMISSION_REQUIREMENT = 100; 130: uint256 public constant ENDORSEMENT_THRESHOLD = 20; 133: uint256 public constant EXECUTION_THRESHOLD = 33;
Third QA issue - Variable names that consist of all capital letters should be reserved for constant/immutable variables
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Operator.sol 69: OlympusPrice internal PRICE; 70: OlympusRange internal RANGE; 71: OlympusTreasury internal TRSRY; 72: OlympusMinter internal MINTR;
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/BondCallback.sol 29: OlympusTreasury public TRSRY; 30: OlympusMinter public MINTR;
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Heart.sol 45: OlympusPrice internal PRICE;
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Governance.sol 56: OlympusInstructions public INSTR; 57: OlympusVotes public VOTES;
๐ 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.5921 DAI - $32.59
First gas optimization - OR (||) conditions cost less than their equivalent AND (&&) conditions ("not(something is false) cost less than ("everything is true")
Remember that the equivalent of (a && b) is !(!a || !b), even with the 10k Optimizer enabled: OR (||) (conditions cost less than their equivalent AND (&&) conditions.
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/modules/INSTR.sol 61: -} else if (instruction.action == Actions.ChangeExecutor && i != length - 1) { 61: +} } else if (!(instruction.action != Actions.ChangeExecutor || i = length - 1) {
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/modules/RANGE.sol 133: -if (capacity_ < _range.high.threshold && range.high.active) { 133: +if !(!(capacity < _range.high.threshold) || !_range.high.active) {
145: -if (capacity_ < _range.low.threshold && range.low.active) { 145: +if !(!(capacity < _range.low.threshold) || !_range.low.active) {
221: -if (market_ == type(uint256).max && marketCapacity_ != 0) revert RANGE_InvalidParams(); 221: +if (!(market_ != type(uint256).max || marketCapacity_ = 0) revert RANGE_InvalidParams();
Second gas optimization - ++ should be unchecked, when it is not possible for them to overflow
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/modules/INSTR.sol it's hardly to believe that a cache for storing a list of instructions to be executed in the future, can get greater than uint256 and overflow. 44: -uint256 instructionsId = ++totalInstructions; 44: +unchecked { uint256 instructionsId = ++totalInstructions; }
Third gas optimization - Usage of uints/ints smaller than 32 bytes (256 bits) incurs in overhead
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/modules/PRICE.sol 44: uint32 public nextObsIndex; 47: uint32 public numObservations; 50: uint48 public observationFrequency; 53: uint48 public movingAverageDuration; 56: uint48 public lastObservationTime;
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Operator.sol 83: uint8 public immutable ohmDecimals; 86: uint8 public immutable reserveDecimals;
Fourth gas optimization - No need to explicitly initialize variables with default values
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โฆ). Explicitly initializing it with its default value is an anti-pattern and wastes gas.
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/utils/KernelUtils.sol 43: -for (uint256 i = 0; i < 5; ) { 43: +for (uint256 i; i < 5; ) {
58: -for (uint256 i = 0; i < 32; ) { 58: +for (uint256 i; i < 32; ) {
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/Kernel.sol 397: -for (uint256 i = 0; i < reqLength; ) { 397: +for (uint256 i; i < reqLength; ) {
Fifth gas optimization - <=/>= cost less gas than </>
https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/utils/KernelUtils.sol 43: -for (uint256 i = 0; i < 5; ) { 43: +for (uint256 i = 0; i <= 4; ) {
58: -for (uint256 i = 0; i < 32; ) { 58: +for (uint256 i = 0; i <= 31; ) {