Olympus DAO contest - lukris02's results

Version 3 of Olympus protocol, a decentralized floating currency.

General Information

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

Olympus DAO

Findings Distribution

Researcher Performance

Rank: 75/147

Findings: 2

Award: $86.97

๐ŸŒŸ Selected for report: 0

๐Ÿš€ Solo Findings: 0

QA Report for Olympus DAO contest

Overview

During the audit, 6 low and 13 non-critical issues were found.

Low Risk Findings (6)

L-1. Storage variables can be packed tightly

Description

According to docs, multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible. It might be beneficial to use reduced-size types if you are dealing with storage values because the compiler will pack multiple elements into one storage slot, and thus, combine multiple reads or writes into a single operation.

Instances

Link to code

/// Tokens /// @notice OHM token contract ERC20 public immutable ohm; uint8 public immutable ohmDecimals; /// @notice Reserve token contract ERC20 public immutable reserve; uint8 public immutable reserveDecimals; /// Constants uint32 public constant FACTOR_SCALE = 1e4;
Recommendation

Consider changing order of variables to:

/// Tokens /// @notice OHM token contract ERC20 public immutable ohm; /// @notice Reserve token contract ERC20 public immutable reserve; //PACKED uint8 public immutable ohmDecimals; uint8 public immutable reserveDecimals; /// Constants uint32 public constant FACTOR_SCALE = 1e4;

L-2. Missing check

Description

No check that observationFrequency not equal to zero (like here). Without check, constructor call will fail not indicating Price_InvalidParams() error.

Instances

if (movingAverageDuration_ == 0 || movingAverageDuration_ % observationFrequency_ != 0)

Recommendation

Change to:
if (observationFrequency_ == 0 || movingAverageDuration_ == 0 || movingAverageDuration_ % observationFrequency_ != 0)

L-3. Large number of observations may cause out-of-gas error

Description

Loops that do not have a fixed number of iterations, for example, loops that depend on storage values, have to be used carefully: Due to the block gas limit, transactions can only consume a certain amount of gas. Either explicitly or just due to normal operation, the number of iterations in a loop can grow beyond the block gas limit, which can cause the complete contract to be stalled at a certain point.

Instances

Link to code

uint256 numObs = observations.length; // Check that the number of start observations matches the number expected if (startObservations_.length != numObs || lastObservationTime_ > uint48(block.timestamp)) revert Price_InvalidParams(); // Push start observations into storage and total up observations uint256 total; for (uint256 i; i < numObs; ) { if (startObservations_[i] == 0) revert Price_InvalidParams(); total += startObservations_[i]; observations[i] = startObservations_[i]; unchecked { ++i; } }
Recommendation

Restrict the maximum number of observations.

L-4. Incorrect code or comment

Description

Comment says that the variable numObservations should be cached but there is a call to the length of the observations array.

Instances

Link to code:

// Cache numObservations to save gas. uint256 numObs = observations.length;
Recommendation

Consider changing the code or comment. The contract has similar part of the code, so it seems preferable to change the code to:

// Cache number of observations to save gas. uint32 numObs = numObservations;

The code will become more consistent.

L-5. Misleading comments

Description

After /* ========== INTERNAL FUNCTIONS ========== */ comment, not all internal functions are placed. There are other internal functions in the contract, and they are located in other places in the code. The same with /* ========== VIEW FUNCTIONS ========== */ comment.

Instances
Recommendation

Regroup functions or formulate more specific comments.

L-6. Check zero denominator

Description

range.cushion.low.price and range.wall.low.price may be equal to zero, since they are initialized to zero here.

Recommendation

Add the check to prevent function call failure.

Non-Critical Risk Findings (13)

NC-1. Constructor before modifiers

Description

According to Order of Layout, modifiers should be declared before constructor.

Instances
Recommendation

Place modifiers before constructor.

NC-2. Events before state variables

Description

According to Order of Layout, state variables should be declared before events.

Instances
Recommendation

Place state variables before events.

NC-3. State variables after constructor

Description

According to Order of Layout, constructor should be declared before state variables.

Instances

Governance.sol: 93 - 137

Recommendation

Place constructor before state variables.

NC-4. Public functions before external

Description

According to Order of Functions, external functions should be declared before public.

Instances
Recommendation

Place external functions before public.

NC-5. Comment in the wrong place

Description

Messed up comments.

Instances

Link

/* ========== STATE VARIABLES ========== */ event ApprovalRevoked(address indexed policy_, ERC20[] tokens_); // Modules OlympusTreasury internal TRSRY;
Recommendation

Change to:

/* ========== EVENTS =========== */ event ApprovalRevoked(address indexed policy_, ERC20[] tokens_); /* ========== STATE VARIABLES ========== */ // Modules OlympusTreasury internal TRSRY;

NC-6. EVENTS, STATE VARIABLES, ERRORS comments not everywhere

Description

Some contracts (for example, this) have /* ========== EVENTS =========== */ and /* ========== STATE VARIABLES ========== */ comments and some do not. Only one contract has /* ========== ERRORS =========== */ comment, although others also declares errors.

Instances

Contracts without /* ========== EVENTS =========== */ and /* ========== STATE VARIABLES ========== */ comments:

Contracts without /* ========== ERRORS =========== */ comment:

Recommendation

Add missing comments.

NC-7. No function visibility

Description

No visibility specified.

Instances

All 7 functions in KernelUtils.sol

Recommendation

Declare functions visibility.

NC-8. Typo

Description

Typo in comment.

Instances

// Cache numbe of observations to save gas.

Recommendation

Change to:
// Cache number of observations to save gas.

NC-9. Scientific notation may be used

Description

For readability, it is better to use scientific notation.

Instances
Recommendation

Replace, for example, 10000 with 10e4.

NC-10. Constants may be used

Description

Constants may be used instead of literal values.

Instances
Recommendation

Define constant variables, especially, for repeated values.

NC-11. Open TODOs

Description

Operator.sol has 1 open TODO, TreasuryCustodian.sol has 3 open TODO.

Instances
Recommendation

Resolve issues.

NC-12. Missing NatSpec

Description

NatSpec is missing for 32 functions in 9 contracts.

Instances
Recommendation

Add NatSpec for all functions.

NC-13. Public functions can be external

Description

If functions are not called by the contract where they are defined, they can be declared external.

Instances

All 7 functions from KernelUtils.sol.

Recommendation

Make public functions external, where possible.

Gas Optimizations Report for Olympus DAO contest

Overview

During the audit, 6 gas issues were found.

Gas Optimizations Findings (6)

G-1. Postfix increment and decrement

Description

Prefix increment and decrement cost less gas than postfix.

Instances
Recommendation

Consider using prefix increment and decrement where it is relevant.

G-2. <>.length in loops

Description

Reading the length of an array at each iteration of the loop consumes extra gas.

Instances

for (uint256 step; step < instructions.length; ) {

Recommendation

Store the length of an array in a variable before the loop, and use it.

G-3. Initializing variables with default value

Description

It costs gas to initialize integer variables with 0 or bool variables with false but it is not necessary.

Instances
Recommendation

Remove initialization for default values.
For example: for (uint256 i; i < reqLength; ) {

G-4. Some variables can be immutable

Description

Using immutables is cheaper than storage-writing operations.

Instances

ERC20 public ohm;

Recommendation

Use immutables where possible. Change to ERC20 public immutable ohm;

G-5. > 0 is more expensive than =! 0

Instances

if (userVotesForProposal[activeProposal.proposalId][msg.sender] > 0) {

Recommendation

Use =! 0 instead of > 0, where possible.

G-6. x += y is more expensive than x = x + y

Instances
Recommendation

Use x = x + y instead of x += y. Use x = x - y instead of x -= y.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax ยฉ 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter