Platform: Code4rena
Start Date: 11/11/2021
Pot Size: $50,000 USDC
Total HM: 9
Participants: 27
Period: 7 days
Judge: alcueca
Total Solo HM: 5
Id: 53
League: ETH
Rank: 12/27
Findings: 2
Award: $1,095.42
🌟 Selected for report: 2
🚀 Solo Findings: 0
🌟 Selected for report: defsec
866.6085 USDC - $866.61
defsec
The current ownership transfer process involves the current owner calling NestedReserve.transferOwnership(). This function checks the new owner is not the zero address and proceeds to write the new owner's address into the owner's state variable. If the nominated EOA account is not a valid account, it is entirely possible the owner may accidentally transfer ownership to an uncontrolled account, breaking all functions with the onlyOwner() modifier. Lack of two-step procedure for critical operations leaves them error-prone if the address is incorrect, the new address will take on the functionality of the new role immediately
for Ex : -Alice deploys a new version of the whitehack group address. When she invokes the whitehack group address setter to replace the address, she accidentally enters the wrong address. The new address now has access to the role immediately and is too late to revert
None
Implement zero address check and Consider implementing a two step process where the owner nominates an account and the nominated account needs to call an acceptOwnership() function for the transfer of ownership to fully succeed. This ensures the nominated EOA account is a valid and active account.
#0 - adrien-supizet
2021-11-19T11:02:46Z
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.
🌟 Selected for report: GiveMeTestEther
Also found by: defsec
47.7068 USDC - $47.71
defsec
This does not directly impact the smart contract in anyway besides cost. This is a gas optimization to reduce cost of smart contract. Calling each function, we can see that the public function uses 496 gas, while the external function uses only 261.
According to Slither Analyzer documentation (https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external), there are functions in the contract that are never called. These functions should be declared as external in order to save gas.
Slither Detector:
external-function:
Slither
#0 - adrien-supizet
2021-11-22T09:51:24Z
duplicate #29
47.7068 USDC - $47.71
defsec
!= 0
is a cheaper operation compared to > 0
, when dealing with uint.
Code Review
Use "!=0" instead of ">0" for the gas optimization.
#0 - adrien-supizet
2021-11-19T16:45:36Z
duplicate #8
🌟 Selected for report: GiveMeTestEther
19.3212 USDC - $19.32
defsec
For the arithmetic operations that will never over/underflow, using the unchecked directive (Solidity v0.8 has default overflow/underflow checks) can save some gas from the unnecessary internal over/underflow checks.
Example Code Location
https://github.com/code-423n4/2021-11-nested/blob/5d113967cdf7c9ee29802e1ecb176c656386fe9b/contracts/FeeSplitter.sol#L85
Code Review
Consider applying 'unchecked' keyword where overflows/underflows are not possible.
#0 - maximebrugel
2021-11-22T16:28:16Z
Duplicated : #46
🌟 Selected for report: defsec
106.015 USDC - $106.02
defsec
The use of _msgSender() when there is no implementation of a meta transaction mechanism that uses it, such as EIP-2771, very slightly increases gas consumption.
"https://github.com/code-423n4/2021-11-nested/blob/5d113967cdf7c9ee29802e1ecb176c656386fe9b/contracts/FeeSplitter.sol#L135" "https://github.com/code-423n4/2021-11-nested/blob/5d113967cdf7c9ee29802e1ecb176c656386fe9b/contracts/NestedFactory.sol#L111" "https://github.com/code-423n4/2021-11-nested/blob/5d113967cdf7c9ee29802e1ecb176c656386fe9b/contracts/NestedReserve.sol#L32"
Code review
Replace _msgSender() with msg.sender if there is no mechanism to support meta-transactions like EIP-2771 implemented.
#0 - maximebrugel
2021-11-23T11:14:37Z
Only agree for :
modifier onlyFactory() { require(_msgSender() == factory, "NestedReserve: UNAUTHORIZED"); _; }
For the others, without support for meta transactions in the recipient contract, an externally owned account can not use meta transactions to interact with releaseETH
and create
defsec
Reading array length at each iteration of the loop takes 6 gas (3 for mload and 3 to place memory_offset) in the stack.
Caching the array length in the stack saves around 3 gas per iteration.
Instances include:
Code Review
Here you could cache uint len = _moduleAddresses.length; and then change the stop criteria to use len instead _moduleAddresses.length to save gas (_moduleAddresses is on memory)
#0 - adrien-supizet
2021-11-19T16:48:09Z
duplicate #7