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
Rank: 5/24
Findings: 3
Award: $1,908.87
🌟 Selected for report: 0
🚀 Solo Findings: 0
183.0209 USDC - $183.02
Few small issues:
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 &&
.
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");
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
.
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 🙂)
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.
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 inNestedReserve
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 caseNestedFactory
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
https://github.com/code-423n4/2022-02-nested-findings/issues/17
https://github.com/code-423n4/2022-02-nested-findings/issues/9
https://github.com/code-423n4/2022-02-nested-findings/issues/37
Already in first audit. But we prefer to keep it simple :) https://github.com/code-423n4/2021-11-nested-findings/issues/101
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:
#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.
🌟 Selected for report: pauliax
Also found by: 0x1f8b, Dravee, GreyArt, Omik, ShippooorDAO, Tomio, bobi, cmichel, csanuragjain, defsec, gzeon, kenta, kenzo, m_smirnova2020, rfa, robee, sirhashalot, ye0lde
207.5708 USDC - $207.57
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.
FeeSplitter contains an unused ETH variable:
address private constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
You can remove it for cleanliness and to save 500 gas at deployment.
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:
#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.