Nested Finance contest - kenzo's results

The one-stop Defi app to build, manage and monetize your portfolio.

General Information

Platform: Code4rena

Start Date: 10/02/2022

Pot Size: $30,000 USDC

Total HM: 5

Participants: 24

Period: 3 days

Judge: harleythedog

Total Solo HM: 3

Id: 86

League: ETH

Nested Finance

Findings Distribution

Researcher Performance

Rank: 5/24

Findings: 3

Award: $1,908.87

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: pauliax

Also found by: 0xliumin, Dravee, GreyArt, IllIllI, Omik, ShippooorDAO, WatchPug, bobi, csanuragjain, gzeon, kenzo, rfa, robee, samruna

Labels

bug
QA (Quality Assurance)
sponsor acknowledged

Awards

183.0209 USDC - $183.02

External Links

Few small issues:

Wrong implementation of OperatorResolver::areOperatorsImported

The function as implemented will return true if the operators have same implementation but different selector, or different implementation but same selector. This might cause users/admins to think an upgrade has happened successfully when it fact it was not. Code ref:

if ( operators[names[i]].implementation != destinations[i].implementation && operators[names[i]].selector != destinations[i].selector ) { return false; }

The condition should be ||, not &&.

Wrong revert reason in MixinOperatorResolver::callOperator

The second line should probably be "OH: INVALID_INPUT_TOKEN". Code ref:

require(tokens[0] == _outputToken, "OH: INVALID_OUTPUT_TOKEN"); require(tokens[1] == _inputToken, "OH: INVALID_OUTPUT_TOKEN");

Ether can be locked in NestedFactory

NestedFactory contains a general receive function, probably to facilitate unwrapping of WETH.

receive() external payable {}

The function does not verify that the ETH sender is WETH contract. This means that ETH accidently sent from users will get locked in the contract. Consider adding an ETH rescue function, or verify that msg.sender == weth.

Two-step transferring of ownership

During the previous C4 audit, it was suggested that the ownership transferal could be changed to be two-step to insure no irreversible damage. Adrien responded "This is interesting. We will use this in the future but we're not ready to do our own implementation of the ownable library post-audit". As now you are using your own implementation of an ownable library, you can reconsider changing transferOwnership to be a two-step process. (although you've missed the audit, it's not complex functionality to add 🙂)

Remove unused ETH variable from FeeSplitter

FeeSplitter contains an ETH variable:

address private constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

It is unused and can be removed for cleanliness and for ~500 gas saved at deployment.

Some good words for the coding

I'd like to say that I'm quite impressed with the codebase. I don't know if I missed any big issues, but my impression of it is that the code is clean, clear and seems extra safe, even unusually so. You've taken precautions and I think that can pay off. A few times I would start thinking about a vector of attack to quickly discover that you have a require statement to account for that. So would just like to give a general thumbs up. 👍

#0 - CloudEllie

2022-02-14T15:07:51Z

Warden requested to add the following to this QA report:

Additional finding: Unused transfer function in NestedReserve: The transfer function in NestedReserve can be only called by the factory, yet the factory doesn't use it. There are specific unit tests for this function but it is not used in the protocol. Removing it will promote cleanliness and save 61414 gas on deployment costs. Note: it is possible you are leaving it there for the future in case NestedFactory will be upgraded and you want this functionality to be possible. If so, this issue is invalid. But maybe it's just an old leftover.

#1 - maximebrugel

2022-02-15T17:17:39Z

"Wrong implementation of OperatorResolver::areOperatorsImported" (Duplicated)

https://github.com/code-423n4/2022-02-nested-findings/issues/17

"Wrong revert reason in MixinOperatorResolver::callOperator" (Duplicated)

https://github.com/code-423n4/2022-02-nested-findings/issues/9

"Ether can be locked in NestedFactory" (Duplicated)

https://github.com/code-423n4/2022-02-nested-findings/issues/37

"Two-step transferring of ownership" (Disputed)

Already in first audit. But we prefer to keep it simple :) https://github.com/code-423n4/2021-11-nested-findings/issues/101

"Remove unused ETH variable from FeeSplitter" (Acknowledged)

We don't know if we will remove this function. I can't be very useful to migrate funds (if needed, not used for the moment). We will think about it. Maybe only use the transfer function.

#2 - harleythedogC4

2022-03-03T01:48:33Z

My personal judgements:

  1. "Wrong implementation of OperatorResolver::areOperatorsImported". This has been upgraded to medium severity in #78. Will not contribute to the QA score here.
  2. "Wrong revert reason in MixinOperatorResolver::callOperator". Valid and non-critical.
  3. "Ether can be locked in NestedFactory". Valid and low-critical.
  4. "Two-step transferring of ownership". As stated, this was already raised in the last audit. Invalid.
  5. "Remove unused ETH variable from FeeSplitter". This is a gas optimization and it already appears in the warden's gas report. Invalid.
  6. "Remove unused ETH variable from FeeSplitter". This is a gas optimization and it already appears in the warden's gas report. Invalid.

#3 - harleythedogC4

2022-03-03T02:31:50Z

Now, here is the methodology I used for calculating a score for each QA report. I first assigned each submission to be either non-critical (1 point), very-low-critical (5 points) or low-critical (10 points), depending on how severe/useful the issue is. The score of a QA report is the sum of these points, divided by the maximum number of points achieved by a QA report. This maximum number was 26 points, achieved by https://github.com/code-423n4/2022-02-nested-findings/issues/66.

The number of points achieved by this report is 11points. Thus the final score of this QA report is (11/26)*100 = 42.

Findings Information

Awards

207.5708 USDC - $207.57

Labels

bug
duplicate
G (Gas Optimization)

External Links

Unused transfer function in NestedReserve

The transfer function in NestedReserve can be only called by NestedFactory, yet the factory doesn't use it. There are specific unit tests for this function but it is not used in the protocol. Removing it will save 61414 gas on deployment costs. Note: it is possible you are leaving it there for the future in case NestedFactory will be upgraded and you want this functionality to be possible. If so, this issue is invalid. But maybe it's just an old leftover.

Unused ETH variable in FeeSplitter

FeeSplitter contains an unused ETH variable:

address private constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

You can remove it for cleanliness and to save 500 gas at deployment.

Change NestedFactory's ETH variable to be immutable

By changing this variable in NestedFactory to immutable instead of constant:

address private constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

You will save 30-70 gas on various calls.

#0 - adrien-supizet

2022-02-16T09:43:37Z

Unused transfer function in NestedReserve

We want to keep it for use cases such as migration or staking of deposited tokens.

Unused ETH variable in FeeSplitter

duplicate #25

Change NestedFactory's ETH variable to be immutable

Duplicated https://github.com/code-423n4/2022-02-nested-findings/issues/15

#1 - harleythedogC4

2022-03-13T03:37:51Z

My personal judgments:

  1. "Unused transfer function in NestedReserve". Valid and medium-optimization.
  2. "Unused ETH variable in FeeSplitter". Valid and small-optimization.
  3. "Change NestedFactory's ETH variable to be immutable". Valid and small-optimization.

#2 - harleythedogC4

2022-03-13T06:21:56Z

Now, here is the methodology I used for calculating a score for each gas report. I first assigned each submission to be either small-optimization (1 point), medium-optimization (5 points) or large-optimization (10 points), depending on how useful the optimization is. The score of a gas report is the sum of these points, divided by the maximum number of points achieved by a gas report. This maximum number was 10 points, achieved by #67.

The number of points achieved by this report is 7 points. Thus the final score of this gas report is (7/10)*100 = 70.

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