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: 51/96
Findings: 2
Award: $45.56
π 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.323 USDC - $28.32
nibblVaultFactory.sol
is already importing everything from
NibblVault.sol
which has Ierc20.sol
,Ierc1155.sol
,IERC721.sol
already imported from it .
Remove Ierc20.sol
and Ierc1155.sol
,IERC721.sol
from nibblVaultFactory.sol
.
instances include:
nibblVaultFactory.sol
:4,5,6
nibblVaultFactory.sol
:102,109,125,143,160,168
nibblVaultFactory.sol
:100,123,140,158
if it gets upgraded and cause weird logic nibblvault:1
instead of seconday
use:secondary
https://github.com/NibblNFT/nibbl-smartcontracts/blob/49bf364d9e81a554cfdf47ae5cfc3daf52a54ad6/contracts/NibblVault.sol#L263
instead of continous
use: continuos
https://github.com/NibblNFT/nibbl-smartcontracts/blob/49bf364d9e81a554cfdf47ae5cfc3daf52a54ad6/contracts/NibblVault.sol#L282
instead of : recieve
use: receive
https://github.com/NibblNFT/nibbl-smartcontracts/blob/49bf364d9e81a554cfdf47ae5cfc3daf52a54ad6/contracts/NibblVault.sol#L361
Discalimer i dint know if this was an exploit so its in qa
_minAmtOut
dosent have to fail if you supply zero becaue anything
in purchaseReturn
is greater or equal to it. attacker can take advangate to this possibly steal tokens or brake logic and maybe even mint tokens for himself if attacker dosnt pay the fees and if purchaseReturn
is more than zero lets say 1 wei
then no check for such a small amount that he is going to work and possible get through alot of bypass of your contract.
buy()
function and _minAmtOut=0
and _to=AttackerADDRERESS
require (_minAmtOut>0);
#0 - HardlyDifficult
2022-07-04T01:33:02Z
#1 - HardlyDifficult
2022-07-04T19:08:34Z
Good suggestions, very succinct
π 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.2412 USDC - $17.24
nibblVaultFactory.sol
is already importing everything from
NibblVault.sol
which has Ierc20.sol
,Ierc1155.sol
,IERC721.sol
already imported from it .
Remove Ierc20.sol
and Ierc1155.sol
,IERC721.sol
from nibblVaultFactory.sol
.
instances include:
nibblVaultFactory.sol
:4,5,6
Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met) Source Custom Errors in Solidity: Starting from Solidity v0.8.4, there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. Until now, you could already use strings to give more information about failures (e.g., revert("Insufficient funds.");), but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them. Custom errors are defined using the error statement, which can be used inside and outside of contracts (including interfaces and libraries).
instances include:
nibblVaultFactory.sol
: 48,49,107,131,141,149,166
nibblVault.sol
:139,129,146,147,154,184,185,
Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition is met. Revert strings that are longer than 32 bytes require at least one additional mstore, along with additional overhead for computing memory offset, etc. 1 byte for character
nibblVaultFactory.sol
: 48,49,107,131,141,149,166,325,351,387,399,400,404,444,475,486,496,505,516,524,536,546,561,570,
Make functions with governance modifier payable saves gas because payable function dont have to check msg.value ==0
and since it doesn't affect the function because governance is only people to call the function it saves gas.
nibblVaultFactory.sol
: 99,123,140,158,173,179
Basket.sol
: almost the whole contract is approve by owner
AccessControlMechanism.sol
:32,40,47
nibblVaultFactory.sol
:107,131,149,166
Basket.sol
:36,42,53,62,69,79,86,93
because variables uninitlized in evm is still 0 and saves 3 gas
nibblVault.sol
:506,525,547
Basket.sol
::43,70,93
++i costs less gas compared to i++ or i += 1 for unsigned integer, as pre-increment is cheaper (about 5 gas per iteration). This statement is true even with the optimizer enabled. i++ increments i and returns the initial value of i. Which means:
uint i = 1; i++; // == 1 but i == 2
But ++i returns the actual incremented value:
uint i = 1; ++i; // == 2 and i == 2 too, so no need for a temporary variable In the first case, the compiler has to create a temporary variable (when used) for returning 1 instead of 2
instances include:
nibblVault.sol
:506,525,547,561
Basket.sol
::43,70,93
nibblVault.sol
:506,525,547
Basket.sol
::43,70,93
Solidity version 0.8+ comes with implicit overflow and underflow checks on unsigned integers. When an overflow or an underflow isnβt possible (as an example, when a comparison is made before the arithmetic operation), some gas can be saved by using an unchecked block: Checked or Unchecked Arithmetic. I suggest wrapping with an unchecked block:
Same thing with second unchecked because total can't overflow amount cant overflow
nibblVault.sol
:506,525,547
Basket.sol
::43,70,93
nibblVault.sol
:126
nibblVault.sol
:51
AccessControlMechanism.sol
:12,13,14
nibblVault.sol
:51
AccessControlMechanism.sol
:12,13,14
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
AccessControlMechanism.sol
:16
abi.encodepacked dosnt pad zeros EIP721Base.sol#L16