GoGoPool contest - lukris02's results

Liquid staking for Avalanche.

General Information

Platform: Code4rena

Start Date: 15/12/2022

Pot Size: $128,000 USDC

Total HM: 28

Participants: 111

Period: 19 days

Judge: GalloDaSballo

Total Solo HM: 1

Id: 194

League: ETH

GoGoPool

Findings Distribution

Researcher Performance

Rank: 58/111

Findings: 1

Award: $122.82

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Labels

bug
grade-b
QA (Quality Assurance)
Q-03

Awards

122.8177 USDC - $122.82

External Links

QA Report for GoGoPool contest

Overview

During the audit, 4 low and 12 non-critical issues were found.

â„–TitleRisk RatingInstance Count
L-1The recordStakingEnd() function does not match the documentation exactlyLow1
L-2getMinipools() function may unexpectedly revertLow1
L-3getStakers() function may unexpectedly revertLow1
L-4"Dirty hack"Low3
NC-1Open TODOsNon-Critical3
NC-2Order of FunctionsNon-Critical13
NC-3Order of LayoutNon-Critical7
NC-4Empty function bodyNon-Critical1
NC-5Typos in event namesNon-Critical3
NC-6Typos in commentsNon-Critical22
NC-7Missing NatSpecNon-Critical16
NC-8Unused named return variablesNon-Critical2
NC-9Maximum line length exceededNon-Critical25
NC-10Use Checks Effects Interactions patternNon-Critical1
NC-11Code can be made more consistentNon-Critical1
NC-12Move the function for clarityNon-Critical1

Low Risk Findings(4)

L-1. The recordStakingEnd() function does not match the documentation exactly

Description

Docs says:
"Staking rewards are split between Node Operators and Liquid Stakers with Node Operators getting 50% + a variable commission fee, and Liquid Stakers receiving the remainder."
But the Lines 417-418 are:

uint256 avaxLiquidStakerRewardAmt = avaxHalfRewards - avaxHalfRewards.mulWadDown(dao.getMinipoolNodeCommissionFeePct()); uint256 avaxNodeOpRewardAmt = avaxTotalRewardAmt - avaxLiquidStakerRewardAmt;

Thus, even if the rewards are calculated correctly, the mismatch between code and documentation can be misleading.

Instances
Recommendation

Change the documentation to:
"Staking rewards are split between Node Operators and Liquid Stakers with Liquid Stakers getting 50% - a variable commission fee, and Node Operators receiving the remainder." or Change the code to:

uint256 avaxNodeOpRewardAmt = avaxHalfRewards + avaxHalfRewards.mulWadDown(dao.getMinipoolNodeCommissionFeePct()); uint256 avaxLiquidStakerRewardAmt = avaxTotalRewardAmt - avaxNodeOpRewardAmt;

L-2. getMinipools() function may unexpectedly revert

Description

In function getMinipools(), if parameter offset is bigger than totalMinipools, this line causes revert():

minipools = new Minipool[](max - offset);

It may be not obvious what the cause of the error is, so it is better to handle this case.

Instances
Recommendation

Before L617 in MinipoolManager.sol add the check:

if (offset > max) { //or if (offset > totalMinipools) revert OffsetIsBiggerThanMinipoolsAmount(); }

L-3. getStakers() function may unexpectedly revert

Description

In function getStakers(), if parameter offset is bigger than totalStakers, this line causes revert():

stakers = new Staker[](max - offset);

It may be not obvious what the cause of the error is, so it is better to handle this case.

Instances
Recommendation

Before L426 in Staking.sol add the check:

if (offset > max) { //or if (offset > totalStakers) revert OffsetIsBiggerThanStakersAmount(); }

L-4. "Dirty hack"

Description

The code contains a comment "// Dirty hack to cut unused elements off end of return value (from RP)", which gives the impression that something bad is being done and can cause mistrust.

Instances
Recommendation

Consider reformulating the comment.

Non-Critical Risk Findings(12)

NC-1. Open TODOs

Instances
Recommendation

Resolve issues.

NC-2. 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 after external:

External functions should be placed before public:

Private functions should be placed at the end of the contract:

Constructor should be placed before all functions:

Internal functions should be placed after public:

Recommendation

Reorder functions where possible.

NC-3. 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

Events should be placed after state variables:

Recommendation

Place events after state variables.

NC-4. Empty function body

Description

The function has no comments and no code.

Instances
Recommendation

Consider adding a comment to clarify the purpose of the function.

NC-5. Typos in event names

Instances

NC-6. Typos in comments

Instances

NC-7. Missing NatSpec

Description

NatSpec is missing for 16 functions in 2 contracts.

Instances

and 14 out of 18 functions in TokenggAVAX.sol

Recommendation

Add NatSpec for all functions.

NC-8. Unused named return variables

Description

Both named return variable(s) and return statement are used.

Instances
Recommendation

To improve clarity use only named return variables.
For example, change:

function functionName() returns (uint id) { return x;

to

function functionName() returns (uint id) { id = x;

NC-9. Maximum line length exceeded

Description

According to Style Guide, maximum suggested line length is 120 characters.

Instances
Recommendation

Make the lines shorter.

NC-10. Use Checks Effects Interactions pattern

Description

It is best practice to use this pattern.

Instances

Link:

// Send tokens to this address now, safeTransfer will revert if it fails tokenContract.safeTransferFrom(msg.sender, address(this), amount); // Update balances tokenBalances[contractKey] = tokenBalances[contractKey] + amount;
Recommendation

Swap these lines of code

NC-11. Code can be made more consistent

Description

There are two functions that behave similarly, and in a similar part of the code, one uses getUint(keccak256("minipool.count")); , and the other one calls the function getStakerCount();.

Instances

function getMinipools: uint256 totalMinipools = getUint(keccak256("minipool.count"));

function getStakers: uint256 totalStakers = getStakerCount();

Recommendation

To make code more consistent and clear:

  1. Change MinipoolManager.sol#L612 to uint256 totalMinipools = getMinipoolCount(); or
  2. Change Staking.sol#L421 to uint256 totalStakers = getUint(keccak256("staker.count"));

NC-12. Move the function for clarity

Description

For clarity, it is better to place function getMinipoolCount() before function getMinipools().

Instances

#0 - GalloDaSballo

2023-01-24T20:24:48Z

L-1 The recordStakingEnd() function does not match the documentation exactly Low 1 L

L-2 getMinipools() function may unexpectedly revert Low 1 R

L-3 getStakers() function may unexpectedly revert Low 1 R

L-4 "Dirty hack" Low 3 Invalid, for lack of proof

NC-1 Open TODOs Non-Critical 3 NC

NC-2 Order of Functions Non-Critical 13 NC

NC-3 Order of Layout Non-Critical 7 NC

NC-4 Empty function body Non-Critical 1 Nc

NC-5 Typos in event names Non-Critical 3 NC

NC-6 Typos in comments Non-Critical 22 NC

NC-7 Missing NatSpec Non-Critical 16 NC

NC-8 Unused named return variables Non-Critical 2 R

NC-9 Maximum line length exceeded Non-Critical 25 NC

NC-10 Use Checks Effects Interactions pattern Non-Critical 1 L

NC-11 Code can be made more consistent Non-Critical 1 R

NC-12 Move the function for clarity NC

#1 - GalloDaSballo

2023-02-03T13:26:53Z

2L 4R 9NC

#2 - c4-judge

2023-02-03T22:09:43Z

GalloDaSballo 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