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: 11/24
Findings: 2
Award: $431.11
🌟 Selected for report: 0
🚀 Solo Findings: 0
309.3509 USDC - $309.35
LOW: 1. Title : ETH may be stuck forever
Impact :
In the https://code4rena.com/reports/2021-11-nested
[M-08] the sponsored stated that this contract should not held any funds, and if there is any erc20 token accidentally send to this contract it is claimable by the owner through https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedFactory.sol#L132
unlockTokens function, since this contract has a receive
https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedFactory.sol#L71
this contract can receive ETH, but there is no function to retrieve the ETH, therefore any ETH that was sent to this contract will be locked forever since the owner can't claim it also.
POC : https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedFactory.sol#L71
Mitigation : Add require to make this contract only receive etc from WETH address.
Title : missing validation between _inputTokenAmount and actual token that was inputed
Impact : The _transferInputTokens
function is handling the token transfer from the user to this contract, however there is missing check whether the _inputTokenAmount
is equal to the actual token that was transfer to this address, In the case AMP token, there is an external call when doing a transfer, an attacker can cause a mismatch when the token was transfer to this address, the attacker transfer the AMP token directly to this contract which inflating the balance of this address, therefore the difference between the _inputTokenAmount
and the actual balance that this contract has, would be massive.
POC :
https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedFactory.sol#L505
Title : There is no limit on how many operator that can be added
Impact : In the https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedFactory.sol#L100
the owner can add an operator, however there is no limit on how many operator can be added by the owner, if the operator inflated to a big value, the removeOperator
would be failing on run out of gas, therefore the operator would be inflated and can't be removed.
POC : https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedFactory.sol#L100
#0 - maximebrugel
2022-02-15T14:59:59Z
https://github.com/code-423n4/2022-02-nested-findings/issues/44
We don’t want to revert if the token has fees on transfers.
#1 - harleythedogC4
2022-02-27T18:44:17Z
The first point is better suited as a duplicate of #37 (low severity), since both do not mention that anyone can actually use the stuck eth to their advantage (which #44 describes). The third point is a valid observation but unlikely to cause any issues since the owner is a multisig behind a timelock.
#2 - harleythedogC4
2022-03-01T02:37:16Z
My personal judgements:
_inputTokenAmount
. Invalid.#3 - harleythedogC4
2022-03-03T02:30:25Z
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 20 points. Thus the final score of this QA report is (20/26)*100 = 77.
🌟 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
121.765 USDC - $121.76
GAS : 1. Title: Unnecessary owner function call
Impact:
In the https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedFactory.sol#L134
it uses owner function call, instead of _owner, using _owner directly can save some gas
POC : https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedFactory.sol#L134
Title: It cheaper to remove the &&
operator and make the 2 different require
POC : https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedAsset.sol#L78
Mitigation :
require(_exists(_replicatedTokenId), "NA: INVALID_REPLICATED_TOKEN_ID"); require(tokenId != _replicatedTokenId, "NA: INVALID_REPLICATED_TOKEN_ID");
Title : It Cheaper to use 0 instead of empty string
Impact : change bytes32("") to bytes32(0) can save +- 3 gas, both check for zero bytes32
POC : https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedFactory.sol#L101
Mitigation :
require(operator != bytes32(0), "NF: INVALID_OPERATOR_NAME");
Title : It cheaper to cached the operators to a memory instead use storage multiple times
Impact : In the removeOperator
function it do the check in the loop by calling the operators storage, instead checking it with memory, multiple storage read is more expansive than doing multiple read from memory therefore saving the operator value to a memory first before checking inside a loop can make this call cheaper, just like addOperator
function do.
POC : https://github.com/code-423n4/2022-02-nested/blob/main/contracts/NestedFactory.sol#L111
Mitigation :
function removeOperator(bytes32 operator) external override onlyOwner { bytes32[] memory operatorsCache = operators; uint256 operatorsLength = operatorsCache.length; for (uint256 i = 0; i < operatorsLength; i++) { if (operatorsCache[i] == operator) { operators[i] = operatorsCache[operatorsLength - 1]; operators.pop(); emit OperatorRemoved(operator); return; } } revert("NF: NON_EXISTENT_OPERATOR"); }
#0 - maximebrugel
2022-02-17T16:52:23Z
https://github.com/code-423n4/2022-02-nested-findings/issues/67
20 unit saved
No impact.
#1 - harleythedogC4
2022-03-13T03:35:28Z
My personal judgments:
#2 - harleythedogC4
2022-03-13T06:21:37Z
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 3 points. Thus the final score of this gas report is (3/10)*100 = 30.