Platform: Code4rena
Start Date: 21/06/2022
Pot Size: $30,000 USDC
Total HM: 12
Participants: 96
Period: 3 days
Judge: HardlyDifficult
Total Solo HM: 5
Id: 140
League: ETH
Rank: 29/96
Findings: 2
Award: $50.13
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, 0x52, 0xNazgul, 0xNineDec, 0xc0ffEE, 0xf15ers, 0xkatana, BowTiedWardens, Chom, ElKu, Funen, GalloDaSballo, JC, JMukesh, JohnSmith, Lambda, Limbooo, MadWookie, MiloTruck, Nethermind, Noah3o6, Nyamcil, Picodes, PwnedNoMore, Randyyy, RoiEvenHaim, SmartSek, StErMi, Tadashi, TerrierLover, TomJ, Tomio, Treasure-Seeker, UnusualTurtle, Varun_Verma, Wayne, Waze, _Adam, apostle0x01, asutorufos, berndartmueller, c3phas, catchup, cccz, cloudjunky, codexploder, cryptphi, defsec, delfin454000, dipp, ellahi, exd0tpy, fatherOfBlocks, hansfriese, hyh, joestakey, kebabsec, kenta, masterchief, minhquanym, naps62, oyc_109, pashov, peritoflores, reassor, rfa, robee, sach1r0, saian, sashik_eth, shenwilly, simon135, slywaters, sorrynotsorry, sseefried, unforgiven, xiaoming90, ych18, zuhaibmohd, zzzitron
30.3481 USDC - $30.35
All the contracts are using fixed 0.8.10 except for AccessControlMechanism.sol which is using floating pragma ^0.8.0. Contracts should be deployed with the same compiler version and flags that they have been tested with thoroughly. Locking the pragma helps to ensure that contracts do not accidentally get deployed using, for example, an outdated compiler version that might introduce bugs that affect the contract system negatively. It is recommended to use the same solidity version for all the contracts.
References: https://swcregistry.io/docs/SWC-103 https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used
Although indexed fields are used widely, still some events have less than 3 indexed fields.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L15-L19
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L100 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L124 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L159 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L176 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L178 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L485
This is one of the best projects I've seen regarding the rich and explanatory natspec comments. There are just a few functions which are missing natspec comments.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L76 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L80 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L88
Some functions have 2 array parameters, length of which must be equal in order for the execution to complete properly. Therefore, these functions should check if the array lengths are equal. For example: withdrawMultipleERC721() function in Basket.sol
function withdrawMultipleERC721(address[] memory _tokens, uint256[] memory _tokenId, address _to) external override { require(_isApprovedOrOwner(msg.sender, 0), "withdraw:not allowed"); require(_tokens.length == _tokenId.length, "array length mismatch"); //@audit array lengths equality check for (uint256 i = 0; i < _tokens.length; i++) { IERC721(_tokens[i]).safeTransferFrom(address(this), _to, _tokenId[i]); emit WithdrawERC721(_tokens[i], _tokenId[i], _to); } }
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L41 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L68 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L504 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L545
NibblVaultFactory.sol imports SafeMath.sol, but it is not used.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L9
Tokens sent to zero address would be burned by mistake. It is a good practice to add non-zero check for the receiver address during token transfers.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L78 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L300 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L362 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L454 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L464 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L474 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L515 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L523 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L523 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L523 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L523
Consider changing the updateCurator() to a 2-step process. First, current curator sets the pending curator, then pending curator claims the curator role. This way, the risk of an accidental wrong assignment can be eliminated.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L485-L488
#0 - HardlyDifficult
2022-07-03T15:43:08Z
#1 - HardlyDifficult
2022-07-04T15:27:06Z
Good suggestions including a few low risk. Report is clean & easy to follow, but in the future including risk ratings is helpful.
🌟 Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0x29A, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, 8olidity, ACai, BowTiedWardens, Chandr, Chom, ElKu, Fitraldys, Funen, IgnacioB, JC, Lambda, Limbooo, MiloTruck, Noah3o6, Nyamcil, Picodes, Randyyy, SmartSek, StErMi, TerrierLover, TomJ, Tomio, UnusualTurtle, Waze, _Adam, ajtra, c3phas, cRat1st0s, catchup, codexploder, cryptphi, defsec, delfin454000, ellahi, exd0tpy, fatherOfBlocks, hansfriese, joestakey, kebabsec, kenta, m_Rassska, minhquanym, oyc_109, pashov, reassor, rfa, robee, sach1r0, saian, sashik_eth, simon135, slywaters, ych18, ynnad, zuhaibmohd
19.7824 USDC - $19.78
1- For loop index increments can be made unchecked for solidity versions > 0.8.0. There is no risk of overflowing the index of the for loops. Therefore, they can be changed to unchecked to save gas. This would save more gas as iterations in the loop increases. 2- Postfix increments can be changed as prefix as it is cheaper. 3- There is no need to set uint variable to 0 since default value is already 0.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L43 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L70 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L93 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L506 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L525 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L547
I suggest to change the original code from this
for (uint256 i = 0; i < _assetAddresses.length; i++) { IERC721(_assetAddresses[i]).safeTransferFrom(address(this), _to, _assetIDs[i]); }
to this
for (uint256 i; i < _assetAddresses.length; ) { IERC721(_assetAddresses[i]).safeTransferFrom(address(this), _to, _assetIDs[i]); unchecked { ++i; } }
Error reason strings take space in the deployed bytecode. Every reason string takes at least 32 bytes so make sure your string fits in 32 bytes or it will become more expensive.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L48 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L49 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L107 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L131 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L141 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L149 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L166
Read-only reference type function parameters can be made calldata rather than memory. Calldata is more gas efficient since it avoids copying the parameters.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L41 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L68 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L91 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L109 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L174-L175 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L504 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L523 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L545 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L80
basketUpdateTime is used twice in the require statement. It can be cached before the require and used from stack to save an SLOAD.
function updateBasketImplementation() external override { uint256 _basketUpdateTime = basketUpdateTime; require(_basketUpdateTime != 0 && block.timestamp >= _basketUpdateTime, "NibblVaultFactory: UPDATE_TIME has not passed"); basketImplementation = pendingBasketImplementation; delete basketUpdateTime; }
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L107
feeToUpdateTime is used twice in the require statement. It can be cached before the require and used from stack to save an SLOAD.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L131
feeAdminUpdateTime is used twice in the require statement. It can be cached before the require and used from stack to save an SLOAD.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L149
vaultUpdateTime is used twice in the require statement. It can be cached before the require and used from stack to save an SLOAD.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L166
When variables are defined as constant, keccak operation will be performed whenever the variable is used. However, if they are immutable, keccak hashing would be performed only during deployment. If the variable is going to be used within the constructor, the value assignment of the immutable variable should be executed within the constructor as well. See below for previous findings. https://github.com/code-423n4/2021-10-slingshot-findings/issues/3 https://github.com/code-423n4/2022-01-livepeer-findings/issues/172
nonces[owner]++ can be changed to postfix increment ++nonces[owner]. Same goes for all of the for loop index increments.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L562
It is a good practice to apply non-zero amount checks for token transactions to avoid unnecessary executions.
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L213 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L237 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L275 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L287 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L362
In the EVM, there is no opcode for >= or <=. When using greater than or equal, two operations are performed: > and =. Therefore it is more efficient to change this:
require(msg.value >= MIN_INITIAL_RESERVE_BALANCE)
to this:
require(msg.value > MIN_INITIAL_RESERVE_BALANCE)
and change the definition of MIN_INITIAL_RESERVE_BALANCE to: uint256 private constant MIN_INITIAL_RESERVE_BALANCE = 1e9 - 1;
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L48 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L107 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L131 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L141 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L149 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVaultFactory.sol#L166