Nibbl contest - ajtra's results

NFT fractionalization protocol with guaranteed liquidity and price based buyout.

General Information

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

Nibbl

Findings Distribution

Researcher Performance

Rank: 89/96

Findings: 1

Award: $17.26

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

  1. Expressions for constant values such as a call to KECCAK256(), should use IMMUTABLE rather than constant

NibblVault.sol Line 51. bytes32 private constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

EIP712Base.sol Line 7 bytes32 internal constant EIP712_DOMAIN_TYPEHASH = keccak256(

AccessControlMechanism.sol Line 12 bytes32 public constant FEE_ROLE = keccak256("FEE_ROLE");

AccessControlMechanism.sol Line 13 bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

AccessControlMechanism.sol Line 14 bytes32 public constant IMPLEMENTER_ROLE = keccak256("IMPLEMENTER_ROLE");

  1. Reordering variables save slots. NibblVault.sol Line 28. Move the sentence uint32 private constant primaryReserveRatio = 200_000; and uint32 public secondaryReserveRatio; after the sentence address public curator; allow to save 2 slots.

  2. Operators <= or >= cost more gas than operator < or >. Change all <= / >= operators for < / > and remember to increse / decrese in consecuence to maintain the logic (example, a <= b for a < b+1).

NibblVault.sol Line 184 require(_secondaryReserveRatio <= primaryReserveRatio, "NibblVault: Excess initial funds");

NibblVault.sol Line 185 require(_secondaryReserveRatio >= MIN_SECONDARY_RESERVE_RATIO, "NibblVault: secResRatio too low");

NibblVault.sol Line 325 require(_minAmtOut <= _purchaseReturn, "NibblVault: Return too low");

NibblVault.sol Line 351 require(_secondaryReserveBalance - _saleReturn >= MIN_SECONDARY_RESERVE_BALANCE, "NibblVault: Excess sell");

NibblVault.sol Linea 387 require(_saleReturn >= _minAmtOut, "NibblVault: Return too low");

NibblVault.sol Line 404 require(_buyoutBid >= _currentValuation, "NibblVault: Bid too low");

  1. i++ cost more gas than ++i. Change in for-loops i++ for ++i

NibblVault.sol Line 506 for (uint256 i = 0; i < _assetAddresses.length; i++) {

NibblVault.sol Line 525 for (uint256 i = 0; i < _assets.length; i++) {

NibblVault.sol Line 547 for (uint256 i = 0; i < _assets.length; i++) {

  1. Array length should not be looked up in every loop of a for-loop. Storage array length checks incur an extra Gwarmaccess (100 gas) PER-LOOP. Store the array length in a variable and use it in the for loop

NibblVault.sol Line 507. for (uint256 i = 0; i < _assetAddresses.length; i++) NibblVault.sol Line 525. for (uint256 i = 0; i < _assets.length; i++) NibblVault.sol Line 547. for (uint256 i = 0; i < _assets.length; i++) Basket.sol Line 43 for (uint256 i = 0; i < _tokens.length; i++) Basket.sol Line 70 for (uint256 i = 0; i < _tokens.length; i++) Basket.sol Line 93 for (uint256 i = 0; i < _tokens.length; i++)

  1. Require strings longer than 32 bytes cost extra gas. Shorten the size of the following strings.

NibblVaultFactory.sol line 48 require(msg.value >= MIN_INITIAL_RESERVE_BALANCE, "NibblVaultFactory: Initial reserve balance too low");

NibblVaultFactory.sol line 49 require(IERC721(_assetAddress).ownerOf(_assetTokenID) == msg.sender, "NibblVaultFactory: Invalid sender");

NibblVaultFactory.sol line 131 require(feeToUpdateTime != 0 && block.timestamp >= feeToUpdateTime, "NibblVaultFactory: UPDATE_TIME has not passed");

NibblVaultFactory.sol line 141 require(_newFee <= MAX_ADMIN_FEE, "NibblVaultFactory: Fee value greater than MAX_ADMIN_FEE");

NibblVaultFactory.sol line 149 require(feeAdminUpdateTime != 0 && block.timestamp >= feeAdminUpdateTime, "NibblVaultFactory: UPDATE_TIME has not passed");

NibblVaultFactory.sol line 166 require(vaultUpdateTime != 0 && block.timestamp >= vaultUpdateTime, "NibblVaultFactory: UPDATE_TIME has not passed");

  1. Require instead of &&. Split of conditions of an require sentence in different requires sentences can save gas.

NibblVaultFactory.sol Line 107 require(basketUpdateTime != 0 && block.timestamp >= basketUpdateTime, "NibblVaultFactory: UPDATE_TIME has not passed");

NibblVaultFactory.sol Line 131 require(feeToUpdateTime != 0 && block.timestamp >= feeToUpdateTime, "NibblVaultFactory: UPDATE_TIME has not passed");

NibblVaultFactory.sol Line 149 require(feeAdminUpdateTime != 0 && block.timestamp >= feeAdminUpdateTime, "NibblVaultFactory: UPDATE_TIME has not passed");

NibblVaultFactory.sol Line 166 require(vaultUpdateTime != 0 && block.timestamp >= vaultUpdateTime, "NibblVaultFactory: UPDATE_TIME has not passed");

  1. VAR1 += VAR2 is more expensive than VAR1 = VAR1 + VAR2

NibblVault.sol Line 219 feeAccruedCurator += _feeCurator;

NibblVault.sol Line 225 secondaryReserveBalance += _feeCurve;

NibblVault.sol Line 242 feeAccruedCurator += _feeCurator;

NibblVault.sol Line 320 secondaryReserveBalance += _lowerCurveDiff;

NibblVault.sol Line 322 _purchaseReturn += _buyPrimaryCurve(msg.value - _lowerCurveDiff, _totalSupply + _purchaseReturn);

NibblVault.sol Line 383 _saleReturn += _sellSecondaryCurve(_amtIn - _tokensPrimaryCurve, _initialTokenSupply);

NibblVault.sol Line 428 unsettledBids[bidder] += _buyoutValuationDeposit;

NibblVault.sol Line 429 totalUnsettledBids += _buyoutValuationDeposit;

  1. Default value initialization. If a variable is not initialized, it’s assumed to have the default value. Explicity initializing with its default value waste gas.

NibblVault.sol line 506 for (uint256 i = 0; i < _assetAddresses.length; i++) NibblVault.sol line 525 for (uint256 i = 0; i < _assets.length; i++) NibblVault.sol line 547 for (uint256 i = 0; i < _assets.length; i++) Basket.sol line 43 for (uint256 i = 0; i < _tokens.length; i++) Basket.sol line 70 for (uint256 i = 0; i < _tokens.length; i++) Basket.sol line 93 for (uint256 i = 0; i < _tokens.length; i++)

  1. i++ should be unchecked when it’s not possible for then to overflow, as is the case for for-loops

NibblVault.sol Line 415 due to condition of 414 NibblVault.sol Line 319 due to condition of 311 NibblVault.sol Line 378 due to condition of 373 NibblVault.sol Line 506 (for statement) NibblVault.sol Line 525 (for statement) NibblVault.sol Line 547 (for statement) Basket.sol line 43 (for statement) Basket.sol line 70 (for statement) Basket.sol line 93 (for statement)

#0 - mundhrakeshav

2022-06-26T09:04:41Z

Duplicate #2, #3, #6, #7, #8, #82

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax Β© 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter