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: 41/96
Findings: 2
Award: $45.83
🌟 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.6142 USDC - $28.61
INibblVaultFactory.sol
Fractionalise
event parameters are not declared as indexed
Some events are missing the indexed
keyword on addresses.
Using the indexed
parameters allow external monitoring tool to filter those logs and monitor events in a better way.
Fractionalise
can declare assetAddress
and proxyVault
as indexed
Consider declaring those event parameters as indexed
to better monitor/filter those events.
NibblVaultFactoryData.sol
All the state variables declared inside NibblVaultFactoryData
contract are missing natspec documentation.
Natspec documentation are useful for internal developers that need to work on the project, external developers that need to integrate with the project, auditors that have to review it but also for end users given that Etherscan has officially integrated the support for it directly on their site.
Consider adding the missing natspec documentation.
Basket.sol
Some functions are missing at all the natspec documentation or have partially implemented it.
Natspec documentation are useful for internal developers that need to work on the project, external developers that have to integrate with the project, auditors that have to review it but also for end users given that Etherscan has officially integrated the support for it directly on their site.
The following functions are missing at all the natspec documentation or have partially implemented it:
initialise
miss all natspecwithdrawERC721
missing natspec for @param _to
withdrawMultipleERC721
missing all natspecwithdrawERC721Unsafe
missing natspec for @param _to
withdrawERC1155
missing natspec for @param _to
withdrawMultipleERC1155
miss all natspecwithdrawETH
missing natspec for @param _to
withdrawERC20
missing natspec for @param _token
withdrawMultipleERC20
missing all natspeconERC721Received
missing all natspeconERC1155Received
missing all natspeconERC1155BatchReceived
missing all natspecConsider adding the missing natspec documentation.
initialize
initialization functionThe "standard" and official name for the initialization method is initialize
(implemented by correctly by NibblVault
).
The current name used by the Basket
contract is initialise
.
Consider renaming the initialization function to initialize
.
withdrawETH
is not checking the amount of ETH to withdrawThe current implementation of withdrawETH
is not checking the amount of ETH present in the Basket contract.
Without any check, it allows the Basket owner / spender to withdraw 0 ETH
and waste gas by doing so.
Consider implementing a check that performs the operation only when address(this).balance > 0
withdrawERC20
, withdrawMultipleERC20
, withdrawERC1155
, withdrawMultipleERC1155
are not checking the amount of tokens to withdrawSimilar to the previous problem for withdrawETH
, those functions are not checking if the contract has at some amount to transfer.
The transfer should happen only if the amount of the token is > 0
to not waste gas.
Consider implementing a check that performs the operation only when
TOKEN_INTERFACE(_tokens[i]).balanceOf(address(this) > 0
where the TOKEN_INTERFACE
is IERC20
or IERC1155
depending on the function called.
Twav.sol
Some functions are missing at all the natspec documentation or have partially implemented it.
Natspec documentation are useful for internal developers that need to work on the project, external developers that have to integrate with the project, auditors that have to review it but also for end users given that Etherscan has officially integrated the support for it directly on their site.
The following functions are missing at all the natspec documentation or have partially implemented it:
getTwavObservations
miss all natspecConsider adding the missing natspec documentation.
twavObservations
and all _getTwav
comments could be improvedCurrently, the code has this natspec/dev comment
twavObservations
→ //TWAV of last 4 Blocks
_getTwav
/// @notice returns the TWAV of the last 4 blocks /// @return _twav TWAV of the last 4 blocks
Interpreting from the comment, it seems that prices in that array are from the last 4 consecutive blocks. In reality, those are prices from different blocks (the TWAV is updated only when _blockTimestamp != lastBlockTimeStamp
and buyout is not active or when buyout process is initialized) but not consecutive because the functions that trigger the update could be called in blocks with a block number not consecutive.
Recommendation: update the comment, clarifying that those prices could not be from consecutive blocks.
NibblVault.sol
_chargeFee
should use _feeAdmin
and not _adminFeeAmt
to decide if safeTransferETH
should be called_adminFeeAmt
is the admin fee % and _feeAdmin
is the amount of fee to be sent to the admin calculated from _adminFeeAmt
.
The _feeAdmin
could be 0 (rounding) even if the _adminFeeAmt
is greater than 0.
Recommendation: use _feeAdmin
instead of _adminFeeAmt
in
if(_adminFeeAmt > 0) { safeTransferETH(_factory, _feeAdmin); }
_chargeFeeSecondaryCurve
should use _feeAdmin
and not _adminFeeAmt
to decide if safeTransferETH
should be called_adminFeeAmt
is the admin fee % and _feeAdmin
is the amount of fee to be sent to the admin calculated from _adminFeeAmt
.
The _feeAdmin
could be 0 (rounding) even if the _adminFeeAmt
is greater than 0.
Recommendation: use _feeAdmin
instead of _adminFeeAmt
in
if(_adminFeeAmt > 0) { safeTransferETH(_factory, _feeAdmin); }
Some functions are missing at all the natspec documentation or have partially implemented it.
Natspec documentation are useful for internal developers that need to work on the project, external developers that have to integrate with the project, auditors that have to review it but also for end users given that Etherscan has officially integrated the support for it directly on their site.
The following functions are missing at all the natspec documentation or have partially implemented it:
getMaxSecondaryCurveBalance
missing natspec for @return_buyPrimaryCurve
missing natspec for @param _totalSupply
_buySecondaryCurve
missing natspec for @param _totalSupply
buy
missing natspec for @return_sellPrimaryCurve
missing natspec for @param _totalSupply
sell
missing natspec for @returninitiateBuyout
missing natspec for @returnredeem
missing natspec for @return and @param _to
redeemCuratorFee
missing natspec for @returnpermit
missing all natspecsafeTransferETH
missing all natspeconERC721Received
missing all natspeconERC1155Received
missing all natspeconERC1155BatchReceived
missing all natspecConsider adding the missing natspec documentation.
NibblVaultFactory.sol
Some functions are missing at all the natspec documentation or have partially implemented it.
Natspec documentation are useful for internal developers that need to work on the project, external developers that have to integrate with the project, auditors that have to review it but also for end users given that Etherscan has officially integrated the support for it directly on their site.
The following functions are missing at all the natspec documentation or have partially implemented it:
createBasket
missing all natspecgetBasketAddress
missing all natspecConsider adding the missing natspec documentation.
constructor
is not checking user inputThe constructor
is not checking the user input value for the following inputs:
_vaultImplementation
should be != address(0)
_feeTo
should be != address(0)
_basketImplementation
should be != address(0)
Consider adding checks on those inputs.
proposeNewBasketImplementation
miss event emission and input value checkThe proposeNewBasketImplementation
function is missing a check on _newBasketImplementation
that should be != address(0)
and is not emitting an event when the value has changed.
updateBasketImplementation
miss event emissionThe updateBasketImplementation
function should emit an event when the value has changed.
withdrawAdminFee
miss event emission and check on ETH amountThe withdrawAdminFee
function should emit an event when the value has changed.
The low level call
should be made only when address(this).balance
to not waste gas.
proposeNewAdminFeeAddress
miss event emission and input value checkThe proposeNewAdminFeeAddress
function is missing a check on _newFeeAddress
that should be != address(0)
and is not emitting an event when the value has changed.
updateNewAdminFeeAddress
miss event emissionThe updateNewAdminFeeAddress
function should emit an event when the value has changed.
proposeNewAdminFee
miss event emissionThe proposeNewAdminFee
function should emit an event when the value has changed.
updateNewAdminFee
miss event emissionThe updateNewAdminFee
function should emit an event when the value has changed.
proposeNewVaultImplementation
miss event emission and input value checkThe proposeNewVaultImplementation
function is missing a check on _newFeeAddress
that should be != address(0)
and is not emitting an event when the value has changed.
updateVaultImplementation
miss event emissionThe updateVaultImplementation
function should emit an event when the value has changed.
BancorFormula.sol
SafeMath
but the solidity compiler is 0.8.10
I couldn't find the official link for the original contract, but seeing the usage of SafeMath
I would assume that the BancorFormula
contract was created before Solidity 0.8.10
(version used by the project).
With Solidity 0.8.x
they implemented
Arithmetic operations revert on underflow and overflow. You can useÂ
unchecked { ... }
 to use the previous wrapping behaviour. Checks for overflow are very common, so we made them the default to increase readability of code, even if it comes at a slight increase of gas costs.
This means that all the operations inside the contract that do not use the SafeMath
functions will revert in case of an underflow/overflow instead of under/overflowing like they would have done before Solidity 0.8
.
Recommendation: be sure to check all the math operations of the contract.
#0 - HardlyDifficult
2022-07-04T13:34:32Z
#1 - HardlyDifficult
2022-07-04T13:44:15Z
#2 - HardlyDifficult
2022-07-04T19:18:16Z
The primary report has lots of good NC improvements
🌟 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.2243 USDC - $17.22
Twav.sol
timestamp
in TwavObservation
is declared as uint32
but cannot be packed with other variablesUsually, it makes sense to try to follow a Tight Variable Packing approach to not waste gas, but in this case, it's useless and will only cost more gas.
The timestamp
variable inside the struct will anyway take a whole slot because after it's declaration we have cumulativeValuation
that is a uint256
.
Declaring timestamp
as a uint256
will allow NibblVault
to waste less gas because there is no more need to perform all the math + cast operations done on the timestamp (example: uint32 _blockTimestamp = uint32(block.timestamp % 2**32);
).
Consider change the type of timestamp
to a uint256