Popcorn contest - lukris02's results

A multi-chain regenerative yield-optimizing protocol.

General Information

Platform: Code4rena

Start Date: 31/01/2023

Pot Size: $90,500 USDC

Total HM: 47

Participants: 169

Period: 7 days

Judge: LSDan

Total Solo HM: 9

Id: 211

League: ETH

Popcorn

Findings Distribution

Researcher Performance

Rank: 44/169

Findings: 2

Award: $375.62

QA:
grade-a
Gas:
grade-b

๐ŸŒŸ Selected for report: 0

๐Ÿš€ Solo Findings: 0

QA Report for Popcorn contest

Overview

During the audit, 1 low and 8 non-critical issues were found.

โ„–TitleRisk RatingInstance Count
L-1No way to remove elements from rewardTokens arrayLow1
NC-1Order of FunctionsNon-Critical16
NC-2Order of LayoutNon-Critical5
NC-3Visibility is not setNon-Critical2
NC-4TyposNon-Critical6
NC-5Missing leading underscoresNon-Critical5
NC-6Unused variableNon-Critical2
NC-7Missing NatSpecNon-Critical18
NC-8Maximum line length exceededNon-Critical17

Low Risk Findings(1)

L-1. No way to remove elements from rewardTokens array

Description

There is no way to remove items from the rewardTokens array. Over time, some rewardTokens may become irrelevant, or, accidentally, an incorrect rewardToken may be added to the array. In the best case, all functions that use the accrueRewards modifier will consume more gas, and in the worst case, due to one small mistake, all these functions may become unavailable.

Instances

Functions affected by modifier accrueRewards :

Recommendation

Implement function for deleting elements from the rewardTokens array.

Non-Critical Risk Findings(8)

NC-1. Order of Functions

Description

According to Style Guide, ordering helps readers identify which functions they can call and to find the constructor and fallback definitions easier.
Functions should be grouped according to their visibility and ordered:

  1. constructor
  2. receive function (if exists)
  3. fallback function (if exists)
  4. external
  5. public
  6. internal
  7. private
Instances

Public functions should be placed before internal:

External function should be placed before internal:

Public functions should be placed after external:

Public functions should be placed before internal:

It is better to place initialize() function before other functions:

Recommendation

Reorder functions where possible.

NC-2. Order of Layout

Description

According to Order of Layout, inside each contract, library or interface, use the following order:

  1. Type declarations
  2. State variables
  3. Events
  4. Modifiers
  5. Functions
Instances

Modifiers should be placed before functions:

Recommendation

Place modifiers before functions.

NC-3. Visibility is not set

Instances
Recommendation

It is better to specify visibility explicitly.

NC-4. Typos

Instances

NC-5. Missing leading underscores

Description

Internal constants and state variables should have a leading underscore.

Instances
Recommendation

Add leading underscores where needed.

NC-6. Unused variable

Description

Some variables declared but not used.

Instances

NC-7. Missing NatSpec

Description

NatSpec is missing for 18 functions in 6 contracts.

Instances
Recommendation

Add NatSpec for all functions.

NC-8. Maximum line length exceeded

Description

According to Style Guide, maximum suggested line length is 120 characters. Longer lines make the code harder to read.

Instances
Recommendation

Make the lines shorter.

#0 - c4-judge

2023-02-28T17:43:19Z

dmvt marked the issue as grade-a

Awards

69.8247 USDC - $69.82

Labels

bug
G (Gas Optimization)
grade-b
G-09

External Links

Gas Optimizations Report for Popcorn contest

Overview

During the audit, 4 gas issues were found.
Total savings ~7145.

โ„–TitleInstance CountSaved
G-1Use unchecked blocks for incrementing22770
G-2Use unchecked blocks for subtractions where underflow is impossible5175
G-3Cached variable is not used1200
G-4Using storage pointer to struct/array/mapping is cheaper than using memory86000

Gas Optimizations Findings(4)

G-1. Use unchecked blocks for incrementing

Description

In Solidity 0.8+, thereโ€™s a default overflow and underflow check on unsigned integers. In the loops or similar cases, "i" will not overflow because the loop will run out of gas before that or max value never be reached.

Instances
Recommendation

Change:

for (uint256 i; i < n; ++i) { // ... }

to:

for (uint256 i; i < n;) { // ... unchecked { ++i; } }
Saved

This saves ~30-40 gas per iteration.
So, ~35*22 = 770

G-2. Use unchecked blocks for subtractions where underflow is impossible

Description

In Solidity 0.8+, thereโ€™s a default overflow and underflow check on unsigned integers. When an overflow or underflow isnโ€™t possible (after require or if-statement), some gas can be saved by using unchecked blocks.

Instances
Saved

This saves ~35.
So, ~35*5 = 175

G-3. Cached variable is not used

Description

The variable highWaterMark_ was meant to be used, but highWaterMark was used.

Instances
Saved

This saves 100*2 = 200.

G-4. Using storage pointer to struct/array/mapping is cheaper than using memory

Description

When you copy a storage struct/array/mapping to a memory variable, you are copying each member by reading it from the storage, which is expensive, but when you use the storage keyword, you are just storing a pointer to the storage, which is much cheaper.

Instances
Recommendation

For example, change:

Escrow memory escrow = escrows[escrowId];

to:

Escrow storage escrow = escrows[escrowId];
Saved

This saves ~6000.

#0 - c4-judge

2023-02-28T14:52:19Z

dmvt marked the issue as grade-b

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