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: 53/96
Findings: 2
Award: $45.51
🌟 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
28.2829 USDC - $28.28
tokens.length
== _tokenIds.length
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L41
We should've check that every token withdraw has tokenId and token address in pair for batch ERC721 batch transfer to prevent 0 tokenId or address(0) token transfer
require(_tokens.length == _tokenId.length);
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L80
The transfer function has a tight gas restriction and might fail if GAS costs change in the future or if a smart contract's fallback function handler is complex. I recommend to use address.call()
https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/
Use address.call()
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L87 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L94
Apart from synthetic tokens which have been engineered to always return true, consider using OpenZeppelin's SafeERC20 library for transferring ERC20 token. Some token won't return bool value (USDT for example)
#0 - HardlyDifficult
2022-07-04T18:57:27Z
Good suggestions to consider.
🌟 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
17.2302 USDC - $17.23
Occurrences: https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L71-L73 https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/Basket.sol#L44-L45
Instead of calling array value by assign its key every call, we can cache it for gas saving Change to:
for (uint256 i = 0; i < _tokens.length; i++) { address _token = _tokens[i]; uint _tokenId = _tokenIds[i] uint256 _balance = IERC1155(_token).balanceOf(address(this), _tokenId); IERC1155(_token).safeTransferFrom(address(this), _to, _tokenId, _balance, "0"); emit WithdrawERC1155(_token, _tokenId, _balance, _to); }
By doing this way we can save 48 gas per call
i
Occurrences: 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
Best practice for doing increment is using prefix increment and unchecked for i
var inside for():
Change to:
for (uint256 i = 0; i < _tokens.length;) { IERC721(_tokens[i]).safeTransferFrom(address(this), _to, _tokenId[i]); emit WithdrawERC721(_tokens[i], _tokenId[i], _to); unchecked{++i;} }
Occurrences: 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
We can store _tokens
and _tokenIds
read only parameter with calldata instead of using memory.
Change to:
function withdrawMultipleERC721(address[] calldata _tokens, uint256[] calldata _tokenId, address _to) external override {
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L147
By using < operator to validate we can save 3 gas per call. The 1 second difference can be ignore
https://github.com/code-423n4/2022-06-nibbl/blob/main/contracts/NibblVault.sol#L477
Using delete statement to set value to 0 can save 8 gas per execution
delete feeAccruedCurator;