Juicebox V2 contest - Bnke0x0's results

The decentralized fundraising and treasury protocol.

General Information

Platform: Code4rena

Start Date: 01/07/2022

Pot Size: $75,000 USDC

Total HM: 17

Participants: 105

Period: 7 days

Judge: Jack the Pug

Total Solo HM: 5

Id: 143

League: ETH

Juicebox

Findings Distribution

Researcher Performance

Rank: 54/105

Findings: 2

Award: $128.10

🌟 Selected for report: 0

🚀 Solo Findings: 0

[L-01] Insufficient input validation (Checking for length greater than one is useless because the caller can just pass a weighting of zero for the second asset in order to exclude it):-

1. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 274): `_terminals.length > 1`

[L-02] Adding a return statement when the function defines a named return variable, is redundant:-

1. File: juice-contracts-v2-code4rena/contracts/JBController.sol (line 246): `return _totalSupply + _reservedTokenAmount;` 2. File: juice-contracts-v2-code4rena/contracts/JBController.sol (line 1056): `return _fundingCycle.configuration;` 3. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 337): `return _splits;`

[L-03] Missing checks for approve()’s return status (Some tokens, such as Tether (USDT) return false rather than reverting if the approval fails. Use OpenZeppelin’s safeApprove(), which reverts if there’s a failure, instead):-

1. File: juice-contracts-v2-code4rena/contracts/JBERC20PaymentTerminal.sol (line 99): `IERC20(token).approve(_to, _amount);`

[L-04] Unused receive() function will lock Ether in contract (If the intention is for the Ether to be used, the function should call another function, otherwise it should revert) :-

1. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBProjectPayer.sol (line 62): `receive() external payable;`

[L-05] public functions not called by the contract should be declared external instead :-

1. File: juice-contracts-v2-code4rena/contracts/JBToken.sol (line 207-211): `function transferOwnership(uint256 _projectId, address _newOwner) public virtual override onlyOwner

{`

[N-01] Use a more recent version of solidity (Use a solidity version of at least 0.8.15 to get string.concat() to be used instead of abi.encodePacked(<str>,<str>)) :-

1. File: juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol (line 2): `pragma solidity 0.8.6;`

[N-02] Event is missing indexed fields (Each event should use three indexed fields if there are three or more fields) :-

1. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBController.so (line 19-78): ` event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);

event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);

event ReconfigureFundingCycles( uint256 configuration, uint256 projectId, string memo, address caller );

event SetFundAccessConstraints( uint256 indexed fundingCycleConfiguration, uint256 indexed fundingCycleNumber, uint256 indexed projectId, JBFundAccessConstraints constraints, address caller );

event DistributeReservedTokens( uint256 indexed fundingCycleConfiguration, uint256 indexed fundingCycleNumber, uint256 indexed projectId, address beneficiary, uint256 tokenCount, uint256 beneficiaryTokenCount, string memo, address caller );

event DistributeToReservedTokenSplit( uint256 indexed projectId, uint256 indexed domain, uint256 indexed group, JBSplit split, uint256 tokenCount, address caller );

event MintTokens( address indexed beneficiary, uint256 indexed projectId, uint256 tokenCount, uint256 beneficiaryTokenCount, string memo, uint256 reservedRate, address caller );

event BurnTokens( address indexed holder, uint256 indexed projectId, uint256 tokenCount, string memo, address caller );

event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);

event PrepMigration(uint256 indexed projectId, address from, address caller); `

2. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBDirectory.sol (line 9-22): ` event SetController(uint256 indexed projectId, address indexed controller, address caller);

event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);

event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);

event SetPrimaryTerminal( uint256 indexed projectId, address indexed token, IJBPaymentTerminal indexed terminal, address caller );

event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);`

3. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol (line 8-19): `event DeployProjectPayer( IJBProjectPayer indexed projectPayer, uint256 defaultProjectId, address defaultBeneficiary, bool defaultPreferClaimedTokens, string defaultMemo, bytes defaultMetadata, bool preferAddToBalance, IJBDirectory directory, address owner, address caller

);`

4. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol (line 8-22): `event DeploySplitsPayer( IJBSplitsPayer indexed splitsPayer, uint256 defaultSplitsProjectId, uint256 defaultSplitsDomain, uint256 defaultSplitsGroup, IJBSplitsStore splitsStore, uint256 defaultProjectId, address defaultBeneficiary, bool defaultPreferClaimedTokens, string defaultMemo, bytes defaultMetadata, bool preferAddToBalance, address owner, address caller

);`

5. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBFundingCycleStore.sol (line 9-16): `event Configure( uint256 indexed configuration, uint256 indexed projectId, JBFundingCycleData data, uint256 metadata, uint256 mustStartAtOrAfter, address caller

);`

6. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPrices.sol (line 7): `event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);` 7. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol (line 121-124): `event DelegateDidRedeem( IJBRedemptionDelegate indexed delegate, JBDidRedeemData data, address caller

);`

8. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBProjectPayer.sol (line 8-16): `event SetDefaultValues( uint256 indexed projectId, address indexed beneficiary, bool preferClaimedTokens, string memo, bytes metadata, bool preferAddToBalance, address caller

); `

9. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSplitsPayer.sol (line 15-39): `event Pay( uint256 indexed projectId, address beneficiary, address token, uint256 amount, uint256 decimals, uint256 leftoverAmount, uint256 minReturnedTokens, bool preferClaimedTokens, string memo, bytes metadata, address caller

);

event AddToBalance( uint256 indexed projectId, address beneficiary, address token, uint256 amount, uint256 decimals, uint256 leftoverAmount, string memo, bytes metadata, address caller );`

10. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBTokenStore.sol (line 8-41): ` event Issue( uint256 indexed projectId, IJBToken indexed token, string name, string symbol, address caller

);

event Mint( address indexed holder, uint256 indexed projectId, uint256 amount, bool tokensWereClaimed, bool preferClaimedTokens, address caller );

event Burn( address indexed holder, uint256 indexed projectId, uint256 amount, uint256 initialUnclaimedBalance, uint256 initialClaimedBalance, bool preferClaimedTokens, address caller );

event Claim( address indexed holder, uint256 indexed projectId, uint256 initialUnclaimedBalance, uint256 amount, address caller );`

[N-02] File is missing NatSpec :-

1. File: juice-contracts-v2-code4rena/contracts/libraries/JBConstants.sol (line 1): `// SPDX-License-Identifier: MIT` 2. File: juice-contracts-v2-code4rena/contracts/libraries/JBCurrencies.sol (line 1): `// SPDX-License-Identifier: MIT` 3. File: juice-contracts-v2-code4rena/contracts/libraries/JBFixedPointNumber.sol (line 1): `// SPDX-License-Identifier: MIT` 4. File: juice-contracts-v2-code4rena/contracts/libraries/JBFundingCycleMetadataResolver.sol (line 1): `// SPDX-License-Identifier: MIT` 5. File: juice-contracts-v2-code4rena/contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol (line 1): `// SPDX-License-Identifier: MIT` 6. File: juice-contracts-v2-code4rena/contracts/libraries/JBOperations.sol (line 1): `// SPDX-License-Identifier: MIT` 7. File: juice-contracts-v2-code4rena/contracts/libraries/JBSplitsGroups.sol (line 1): `// SPDX-License-Identifier: MIT` 8. File: juice-contracts-v2-code4rena/contracts/libraries/JBTokens.sol (line 1): `// SPDX-License-Identifier: MIT` 9. File: juice-contracts-v2-code4rena/contracts/structs/JBDidPayData.sol (line 1): `// SPDX-License-Identifier: MIT` 10. File: juice-contracts-v2-code4rena/contracts/structs/JBDidRedeemData.sol (line 1): `// SPDX-License-Identifier: MIT` 11. File: juice-contracts-v2-code4rena/contracts/structs/JBFee.sol (line 1): `// SPDX-License-Identifier: MIT` 12. File: juice-contracts-v2-code4rena/contracts/structs/JBFundAccessConstraints.sol (line 1): `// SPDX-License-Identifier: MIT` 13. File: juice-contracts-v2-code4rena/contracts/structs/JBFundingCycle.sol (line 1): `// SPDX-License-Identifier: MIT` 14. File: juice-contracts-v2-code4rena/contracts/structs/JBFundingCycleData.sol (line 1): `// SPDX-License-Identifier: MIT` 15. File: juice-contracts-v2-code4rena/contracts/structs/JBFundingCycleMetadata.sol (line 1): `// SPDX-License-Identifier: MIT` 16. File: juice-contracts-v2-code4rena/contracts/structs/JBGlobalFundingCycleMetadata.sol (line 1): `// SPDX-License-Identifier: MIT` 17. File: juice-contracts-v2-code4rena/contracts/structs/JBGroupedSplits.sol (line 1): `// SPDX-License-Identifier: MIT` 18. File: juice-contracts-v2-code4rena/contracts/structs/JBOperatorData.sol (line 1): `// SPDX-License-Identifier: MIT` 19. File: juice-contracts-v2-code4rena/contracts/structs/JBPayParamsData.sol (line 1): `// SPDX-License-Identifier: MIT` 20. File: juice-contracts-v2-code4rena/contracts/structs/JBProjectMetadata.sol (line 1): `// SPDX-License-Identifier: MIT` 21. File: juice-contracts-v2-code4rena/contracts/structs/JBRedeemParamsData.sol (line 1): `// SPDX-License-Identifier: MIT` 22. File: juice-contracts-v2-code4rena/contracts/structs/JBSplit.sol (line 1): `// SPDX-License-Identifier: MIT` 23. File: juice-contracts-v2-code4rena/contracts/structs/JBSplitAllocationData.sol (line 1): `// SPDX-License-Identifier: MIT` 24. File: juice-contracts-v2-code4rena/contracts/structs/JBTokenAmount.sol (line 1): `// SPDX-License-Identifier: MIT` 25. File: juice-contracts-v2-code4rena/contracts/JBChainlinkV3PriceFeed.sol (line 1): `// SPDX-License-Identifier: MIT` 26. File: juice-contracts-v2-code4rena/contracts/JBController.sol (line 1): `// SPDX-License-Identifier: MIT` 27. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 1): `// SPDX-License-Identifier: MIT` 28. File: juice-contracts-v2-code4rena/contracts/JBERC20PaymentTerminal.sol (line 1): `// SPDX-License-Identifier: MIT` 29. File: juice-contracts-v2-code4rena/contracts/JBETHPaymentTerminal.sol (line 1): `// SPDX-License-Identifier: MIT` 30. File: juice-contracts-v2-code4rena/contracts/JBFundingCycleStore.sol (line 1): `// SPDX-License-Identifier: MIT` 31. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 1): `// SPDX-License-Identifier: MIT` 32. File: juice-contracts-v2-code4rena/contracts/JBPrices.sol (line 1): `// SPDX-License-Identifier: MIT` 33. File: juice-contracts-v2-code4rena/contracts/JBProjects.sol (line 1): `// SPDX-License-Identifier: MIT` 34. File: juice-contracts-v2-code4rena/contracts/JBReconfigurationBufferBallot.sol (line 1): `// SPDX-License-Identifier: MIT` 35. File: juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol (line 1): `// SPDX-License-Identifier: MIT` 36. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 1): `// SPDX-License-Identifier: MIT` 37. File: juice-contracts-v2-code4rena/contracts/JBToken.sol (line 1): `// SPDX-License-Identifier: MIT` 38. File: juice-contracts-v2-code4rena/contracts/JBTokenStore.sol (line 1): `// SPDX-License-Identifier: MIT` 39. File: juice-contracts-v2-code4rena/contracts/abstract/JBControllerUtility.sol (line 1): `// SPDX-License-Identifier: MIT` 40. File: juice-contracts-v2-code4rena/contracts/abstract/JBOperatable.sol (line 1): `// SPDX-License-Identifier: MIT` 41. File: juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol (line 1): `// SPDX-License-Identifier: MIT` 42. File: juice-contracts-v2-code4rena/contracts/abstract/JBSingleTokenPaymentTerminal.sol (line 1): `// SPDX-License-Identifier: MIT` 43. File: juice-contracts-v2-code4rena/contracts/enums/JBBallotState.sol (line 1): `// SPDX-License-Identifier: MIT` 44. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBAllowanceTerminal.sol (line 1): `// SPDX-License-Identifier: MIT` 45. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBController.sol (line 1): `// SPDX-License-Identifier: MIT` 46. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBControllerUtility.sol (line 1): `// SPDX-License-Identifier: MIT` 47. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBDirectory.sol (line 1): `// SPDX-License-Identifier: MIT` 48. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol (line 1): `// SPDX-License-Identifier: MIT` 49. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol (line 1): `// SPDX-License-Identifier: MIT` 50. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBFeeGauge.sol (line 1): `// SPDX-License-Identifier: MIT` 51. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBFundingCycleBallot.sol (line 1): `// SPDX-License-Identifier: MIT` 52. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBFundingCycleDataSource.sol (line 1): `// SPDX-License-Identifier: MIT` 53. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBFundingCycleStore.sol (line 1): `// SPDX-License-Identifier: MIT` 54. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBMigratable.sol (line 1): `// SPDX-License-Identifier: MIT` 55. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBOperatable.sol (line 1): `// SPDX-License-Identifier: MIT` 56. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBOperatorStore.sol (line 1): `// SPDX-License-Identifier: MIT` 57. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPayDelegate.sol (line 1): `// SPDX-License-Identifier: MIT` 58. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPaymentTerminal.sol (line 1): `// SPDX-License-Identifier: MIT` 59. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol (line 1): `// SPDX-License-Identifier: MIT` 60. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPayoutTerminal.sol (line 1): `// SPDX-License-Identifier: MIT` 61. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPriceFeed.sol (line 1): `// SPDX-License-Identifier: MIT` 62. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPrices.sol (line 1): `// SPDX-License-Identifier: MIT` 63. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBProjectPayer.sol (line 1): `// SPDX-License-Identifier: MIT` 64. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBProjects.sol (line 1): `// SPDX-License-Identifier: MIT` 65. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBReconfigurationBufferBallot.sol (line 1): `// SPDX-License-Identifier: MIT` 66. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBRedemptionDelegate.sol (line 1): `// SPDX-License-Identifier: MIT` 67. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBRedemptionTerminal.sol (line 1): `// SPDX-License-Identifier: MIT` 68. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSingleTokenPaymentTerminal.sol (line 1): `// SPDX-License-Identifier: MIT` 69. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol (line 1): `// SPDX-License-Identifier: MIT` 70. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSplitAllocator.sol (line 1): `// SPDX-License-Identifier: MIT` 71. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSplitsPayer.sol (line 1): `// SPDX-License-Identifier: MIT` 72. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSplitsStore.sol (line 1): `// SPDX-License-Identifier: MIT` 73. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBTerminalUtility.sol (line 1): `// SPDX-License-Identifier: MIT` 74. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBToken.sol (line 1): `// SPDX-License-Identifier: MIT` 75. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBTokenStore.sol (line 1): `// SPDX-License-Identifier: MIT` 76. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBTokenUriResolver.sol (line 1): `// SPDX-License-Identifier: MIT`

[G-01] <array>.length should not be looked up in every loop of a for-loop (Even memory arrays incur the overhead of bit tests and bit shifts to calculate the array length. Storage array length checks incur an extra Gwarmaccess (100 gas) PER-LOOP.):-

1. File: juice-contracts-v2-code4rena/contracts/JBController.sol (line 913): `for (uint256 _i = 0; _i < _splits.length; _i++) {` 2. File: juice-contracts-v2-code4rena/contracts/JBController.sol (line 1014): `for (uint256 _i; _i < _fundAccessConstraints.length; _i++) {` 3. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 139): `for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {` 4. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 167): `for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)` 5. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 275): `for (uint256 _i; _i < _terminals.length; _i++)` 6. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 276): `for (uint256 _j = _i + 1; _j < _terminals.length; _j++)` 7. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 85): `for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) {` 8. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 135): `for (uint256 _i = 0; _i < _operatorData.length; _i++) {` 9. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 165): `for (uint256 _i = 0; _i < _indexes.length; _i++) {` 10. File: juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol (line 862): `for (uint256 _i = 0; _i < _terminals.length; _i++)` 11. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 204): `for (uint256 _i = 0; _i < _currentSplits.length; _i++) {` 12. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 211): `for (uint256 _j = 0; _j < _splits.length; _j++) {` 13. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 229): `for (uint256 _i = 0; _i < _splits.length; _i++) {` 14. File: juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol (line 1008): `for (uint256 _i = 0; _i < _splits.length; ) {`

[G-02] It costs more gas to initialize variables to zero than to let the default of zero be applied:-

1. File: juice-contracts-v2-code4rena/contracts/JBController.sol (line 913): `for (uint256 _i = 0; _i < _splits.length; _i++) {` 2. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 85): `for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) {` 3. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 135): `for (uint256 _i = 0; _i < _operatorData.length; _i++) {` 4. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 165): `for (uint256 _i = 0; _i < _indexes.length; _i++) {` 5. File: juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol (line 862): `for (uint256 _i = 0; _i < _terminals.length; _i++)` 6. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 204): `for (uint256 _i = 0; _i < _currentSplits.length; _i++) {` 7. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 211): `for (uint256 _j = 0; _j < _splits.length; _j++) {` 8. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 229): `for (uint256 _i = 0; _i < _splits.length; _i++) {` 9. File: juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol (line 1008): `for (uint256 _i = 0; _i < _splits.length; ) {`

[G-03] ++i costs less gas than i++, especially when it’s used in for-loops (--i/i-- too):-

1. File: juice-contracts-v2-code4rena/contracts/JBController.sol (line 913): `for (uint256 _i = 0; _i < _splits.length; _i++) {` 2. File: juice-contracts-v2-code4rena/contracts/JBController.sol (line 1014): `for (uint256 _i; _i < _fundAccessConstraints.length; _i++) {` 3. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 139): `for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {` 4. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 167): `for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)` 5. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 275): `for (uint256 _i; _i < _terminals.length; _i++)` 6. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 276): `for (uint256 _j = _i + 1; _j < _terminals.length; _j++)` 7. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 85): `for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) {` 8. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 135): `for (uint256 _i = 0; _i < _operatorData.length; _i++) {` 9. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 165): `for (uint256 _i = 0; _i < _indexes.length; _i++) {` 10. File: juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol (line 862): `for (uint256 _i = 0; _i < _terminals.length; _i++)` 11. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 204): `for (uint256 _i = 0; _i < _currentSplits.length; _i++) {` 12. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 211): `for (uint256 _j = 0; _j < _splits.length; _j++) {` 13. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 229): `for (uint256 _i = 0; _i < _splits.length; _i++) {`

[G-04] Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead :-

1. File: juice-contracts-v2-code4rena/contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol (line 9): `function setTerminalsAllowed(uint8 _data) internal pure returns (bool)` 2. File: juice-contracts-v2-code4rena/contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol (line 13): `function setControllerAllowed(uint8 _data) internal pure returns (bool)` 3. File: juice-contracts-v2-code4rena/contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol (line 44): `function expandMetadata(uint8 _packedMetadata)` 4. File: juice-contracts-v2-code4rena/contracts/structs/JBFee.sol (line 12): `uint32 fee;` 5. File: juice-contracts-v2-code4rena/contracts/structs/JBFee.sol (line 13): `uint32 feeDiscount;` 6. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 25): `using JBGlobalFundingCycleMetadataResolver for uint8;` 7. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 232): `!uint8(_fundingCycle.metadata >> 8).setControllerAllowed()` 8. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 276): `!uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()` 9. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 365): `!uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()` 10. File: juice-contracts-v2-code4rena/contracts/JBFundingCycleStore.sol (line 318): `uint32 _size;` 11. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBToken.sol (line 5): `function decimals() external view returns (uint8);`

[G-05] Use a more recent version of solidity (Use a solidity version of at least 0.8.15 to have external calls skip contract existence checks if the external call has a return value):-

1. File: juice-contracts-v2-code4rena/contracts/libraries/JBConstants.sol (line 2): `pragma solidity 0.8.6;` 2. File: juice-contracts-v2-code4rena/contracts/libraries/JBCurrencies.sol (line 2): `pragma solidity 0.8.6;` 3. File: juice-contracts-v2-code4rena/contracts/libraries/JBFixedPointNumber.sol (line 2): `pragma solidity 0.8.6;` 4. File: juice-contracts-v2-code4rena/contracts/libraries/JBFundingCycleMetadataResolver.sol (line 2): `pragma solidity 0.8.6;` 5. File: juice-contracts-v2-code4rena/contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol (line 2): `pragma solidity 0.8.6;` 6. File: juice-contracts-v2-code4rena/contracts/libraries/JBOperations.sol (line 2): `pragma solidity 0.8.6;` 7. File: juice-contracts-v2-code4rena/contracts/libraries/JBSplitsGroups.sol (line 2): `pragma solidity 0.8.6;` 8. File: juice-contracts-v2-code4rena/contracts/libraries/JBTokens.sol (line 2): `pragma solidity 0.8.6;` 9. File: juice-contracts-v2-code4rena/contracts/structs/JBDidPayData.sol (line 2): `pragma solidity 0.8.6;` 10. File: juice-contracts-v2-code4rena/contracts/structs/JBDidRedeemData.sol (line 2): `pragma solidity 0.8.6;` 11. File: juice-contracts-v2-code4rena/contracts/structs/JBFee.sol (line 2): `pragma solidity 0.8.6;` 12. File: juice-contracts-v2-code4rena/contracts/structs/JBFundAccessConstraints.sol (line 2): `pragma solidity 0.8.6;` 13. File: juice-contracts-v2-code4rena/contracts/structs/JBFundingCycle.sol (line 2): `pragma solidity 0.8.6;` 14. File: juice-contracts-v2-code4rena/contracts/structs/JBFundingCycleData.sol (line 2): `pragma solidity 0.8.6;` 15. File: juice-contracts-v2-code4rena/contracts/structs/JBFundingCycleMetadata.sol (line 2): `pragma solidity 0.8.6;` 16. File: juice-contracts-v2-code4rena/contracts/structs/JBGlobalFundingCycleMetadata.sol (line 2): `pragma solidity 0.8.6;` 17. File: juice-contracts-v2-code4rena/contracts/structs/JBGroupedSplits.sol (line 2): `pragma solidity 0.8.6;` 18. File: juice-contracts-v2-code4rena/contracts/structs/JBOperatorData.sol (line 2): `pragma solidity 0.8.6;` 19. File: juice-contracts-v2-code4rena/contracts/structs/JBPayParamsData.sol (line 2): `pragma solidity 0.8.6;` 20. File: juice-contracts-v2-code4rena/contracts/structs/JBProjectMetadata.sol (line 2): `pragma solidity 0.8.6;` 21. File: juice-contracts-v2-code4rena/contracts/structs/JBRedeemParamsData.sol (line 2): `pragma solidity 0.8.6;` 22. File: juice-contracts-v2-code4rena/contracts/structs/JBSplit.sol (line 2): `pragma solidity 0.8.6;` 23. File: juice-contracts-v2-code4rena/contracts/structs/JBSplitAllocationData.sol (line 2): `pragma solidity 0.8.6;` 24. File: juice-contracts-v2-code4rena/contracts/structs/JBTokenAmount.sol (line 2): `pragma solidity 0.8.6;` 25. File: juice-contracts-v2-code4rena/contracts/JBChainlinkV3PriceFeed.sol (line 2): `pragma solidity 0.8.6;` 26. File: juice-contracts-v2-code4rena/contracts/JBController.sol (line 2): `pragma solidity 0.8.6;` 27. File: juice-contracts-v2-code4rena/contracts/JBDirectory.sol (line 2): `pragma solidity 0.8.6;` 28. File: juice-contracts-v2-code4rena/contracts/JBERC20PaymentTerminal.sol (line 2): `pragma solidity 0.8.6;` 29. File: juice-contracts-v2-code4rena/contracts/JBETHPaymentTerminal.sol (line 2): `pragma solidity 0.8.6;` 30. File: juice-contracts-v2-code4rena/contracts/JBFundingCycleStore.sol (line 2): `pragma solidity 0.8.6;` 31. File: juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol (line 2): `pragma solidity 0.8.6;` 32. File: juice-contracts-v2-code4rena/contracts/JBPrices.sol (line 2): `pragma solidity 0.8.6;` 33. File: juice-contracts-v2-code4rena/contracts/JBProjects.sol (line 2): `pragma solidity 0.8.6;` 34. File: juice-contracts-v2-code4rena/contracts/JBReconfigurationBufferBallot.sol (line 2): `pragma solidity 0.8.6;` 35. File: juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol (line 2): `pragma solidity 0.8.6;` 36. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 2): `pragma solidity 0.8.6;` 37. File: juice-contracts-v2-code4rena/contracts/JBToken.sol (line 2): `pragma solidity 0.8.6;` 38. File: juice-contracts-v2-code4rena/contracts/JBTokenStore.sol (line 2): `pragma solidity 0.8.6;` 39. File: juice-contracts-v2-code4rena/contracts/abstract/JBControllerUtility.sol (line 2): `pragma solidity 0.8.6;` 40. File: juice-contracts-v2-code4rena/contracts/abstract/JBOperatable.sol (line 2): `pragma solidity 0.8.6;` 41. File: juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol (line 2): `pragma solidity 0.8.6;` 42. File: juice-contracts-v2-code4rena/contracts/abstract/JBSingleTokenPaymentTerminal.sol (line 2): `pragma solidity 0.8.6;` 43. File: juice-contracts-v2-code4rena/contracts/enums/JBBallotState.sol (line 2): `pragma solidity 0.8.6;` 44. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBAllowanceTerminal.sol (line 2): `pragma solidity 0.8.6;` 45. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBController.sol (line 2): `pragma solidity 0.8.6;` 46. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBControllerUtility.sol (line 2): `pragma solidity 0.8.6;` 47. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBDirectory.sol (line 2): `pragma solidity 0.8.6;` 48. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol (line 2): `pragma solidity 0.8.6;` 49. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol (line 2): `pragma solidity 0.8.6;` 50. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBFeeGauge.sol (line 2): `pragma solidity 0.8.6;` 51. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBFundingCycleBallot.sol (line 2): `pragma solidity 0.8.6;` 52. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBFundingCycleDataSource.sol (line 2): `pragma solidity 0.8.6;` 53. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBFundingCycleStore.sol (line 2): `pragma solidity 0.8.6;` 54. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBMigratable.sol (line 2): `pragma solidity 0.8.6;` 55. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBOperatable.sol (line 2): `pragma solidity 0.8.6;` 56. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBOperatorStore.sol (line 2): `pragma solidity 0.8.6;` 57. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPayDelegate.sol (line 2): `pragma solidity 0.8.6;` 58. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPaymentTerminal.sol (line 2): `pragma solidity 0.8.6;` 59. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol (line 2): `pragma solidity 0.8.6;` 60. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPayoutTerminal.sol (line 2): `pragma solidity 0.8.6;` 61. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPriceFeed.sol (line 2): `pragma solidity 0.8.6;` 62. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBPrices.sol (line 2): `pragma solidity 0.8.6;` 63. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBProjectPayer.sol (line 2): `pragma solidity 0.8.6;` 64. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBProjects.sol (line 2): `pragma solidity 0.8.6;` 65. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBReconfigurationBufferBallot.sol (line 2): `pragma solidity 0.8.6;` 66. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBRedemptionDelegate.sol (line 2): `pragma solidity 0.8.6;` 67. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBRedemptionTerminal.sol (line 2): `pragma solidity 0.8.6;` 68. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSingleTokenPaymentTerminal.sol (line 2): `pragma solidity 0.8.6;` 69. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol (line 2): `pragma solidity 0.8.6;` 70. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSplitAllocator.sol (line 2): `pragma solidity 0.8.6;` 71. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSplitsPayer.sol (line 2): `pragma solidity 0.8.6;` 72. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBSplitsStore.sol (line 2): `pragma solidity 0.8.6;` 73. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBTerminalUtility.sol (line 2): `pragma solidity 0.8.6;` 74. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBToken.sol (line 2): `pragma solidity 0.8.6;` 75. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBTokenStore.sol (line 2): `pragma solidity 0.8.6;` 76. File: juice-contracts-v2-code4rena/contracts/interfaces/IJBTokenUriResolver.sol (line 2): `pragma solidity 0.8.6;`

[G-06] Multiple address mappings can be combined into a single mapping of an uint256 to a struct, where appropriate:-

1. File: juice-contracts-v2-code4rena/contracts/JBFundingCycleStore.sol (line 34-77): ` /** @notice Stores the user defined properties of each funding cycle, packed into one storage slot. _projectId The ID of the project to get properties of. _configuration The funding cycle configuration to get properties of.

*/ mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;

/** @notice Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.

_projectId The ID of the project to get instrinsic properties of. _configuration The funding cycle configuration to get properties of.

*/ mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;

/** @notice Stores the metadata for each funding cycle configuration, packed into one storage slot. _projectId The ID of the project to get metadata of. _configuration The funding cycle configuration to get metadata of. */ mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;

//// // --------------------- public stored properties -------------------- // ////

/** @notice The latest funding cycle configuration for each project. _projectId The ID of the project to get the latest funding cycle configuration of. */ mapping(uint256 => uint256) public override latestConfigurationOf;

//// // ------------------------- external views -------------------------- // ////

/**`

2. File: juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol (line 89-123): `mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;

/** @notice The amount of funds that a project has distributed from its limit during the current funding cycle for each terminal, in terms of the distribution limit's currency. @dev Increases as projects use their preconfigured distribution limits. @dev The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the used distribution limit applies. _projectId The ID of the project to get the used distribution limit of. _fundingCycleNumber The number of the funding cycle during which the distribution limit was used. */ mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256))) public override usedDistributionLimitOf;

/** @notice The amount of funds that a project has used from its allowance during the current funding cycle configuration for each terminal, in terms of the overflow allowance's currency. @dev Increases as projects use their allowance. @dev The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the overflow allowance applies. _projectId The ID of the project to get the used overflow allowance of. _configuration The configuration of the during which the allowance was used. */ mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))`

3. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 44-70): ` mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) private _splitCountOf;

/** @notice Packed data of splits for each project ID's configurations. _projectId The ID of the project to get packed splits data for. _domain An identifier within which the returned splits should be considered active. _group The identifying group of the splits. _index The indexed order that the split was set at. */ mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256)))) private _packedSplitParts1Of;

/** @notice More packed data of splits for each project ID's configurations. @dev This packed data is often 0. _projectId The ID of the project to get packed splits data for. _domain An identifier within which the returned splits should be considered active. _group The identifying group of the splits. _index The indexed order that the split was set at. */ mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))`

[G-07] internal functions not called by the contract should be removed to save deployment gas:-

1. File: juice-contracts-v2-code4rena/contracts/libraries/JBFixedPointNumber.sol (line 5-9): `function adjustDecimals( uint256 _value, uint256 _decimals, uint256 _targetDecimals

) internal pure returns (uint256) {`

2. File: juice-contracts-v2-code4rena/contracts/libraries/JBFundingCycleMetadataResolver.sol : `(line from 11 to 114)` 3. File: juice-contracts-v2-code4rena/contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol : `(line from 9 to 45)` 4. File: juice-contracts-v2-code4rena/contracts/JBERC20PaymentTerminal.sol (line 81-85): `function _transferFrom( address _from, address payable _to, uint256 _amount

) internal override {`

5. File: juice-contracts-v2-code4rena/contracts/JBERC20PaymentTerminal.sol (line 98): `function _beforeTransferTo(address _to, uint256 _amount) internal override {` 6. File: juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol (line 194-199): `function _set( uint256 _projectId, uint256 _domain, uint256 _group, JBSplit[] memory _splits

) internal {`

[G-08] Using private rather than public for constants, saves gas (If needed, the value can be read from the verified contract source code. Savings are due to the compiler not having to create non-payable getter functions for deployment calldata, and not adding another entry to the method ID table):-

1. File: juice-contracts-v2-code4rena/contracts/libraries/JBConstants.sol (line 9-14): ` uint256 public constant MAX_RESERVED_RATE = 10000;

uint256 public constant MAX_REDEMPTION_RATE = 10000; uint256 public constant MAX_DISCOUNT_RATE = 1000000000; uint256 public constant SPLITS_TOTAL_PERCENT = 1000000000; uint256 public constant MAX_FEE = 1000000000; uint256 public constant MAX_FEE_DISCOUNT = 1000000000;`

2. File: juice-contracts-v2-code4rena/contracts/libraries/JBCurrencies.sol (line 5-6): ` uint256 public constant ETH = 1;

uint256 public constant USD = 2;`

3. File: juice-contracts-v2-code4rena/contracts/libraries/JBOperations.sol (line 5-22): ` uint256 public constant RECONFIGURE = 1;

uint256 public constant REDEEM = 2; uint256 public constant MIGRATE_CONTROLLER = 3; uint256 public constant MIGRATE_TERMINAL = 4; uint256 public constant PROCESS_FEES = 5; uint256 public constant SET_METADATA = 6; uint256 public constant ISSUE = 7; uint256 public constant CHANGE_TOKEN = 8; uint256 public constant MINT = 9; uint256 public constant BURN = 10; uint256 public constant CLAIM = 11; uint256 public constant TRANSFER = 12; uint256 public constant REQUIRE_CLAIM = 13; uint256 public constant SET_CONTROLLER = 14; uint256 public constant SET_TERMINALS = 15; uint256 public constant SET_PRIMARY_TERMINAL = 16; uint256 public constant USE_ALLOWANCE = 17; uint256 public constant SET_SPLITS = 18;`

4. File: juice-contracts-v2-code4rena/contracts/libraries/JBSplitsGroups.sol (line 5-6): ` uint256 public constant ETH_PAYOUT = 1;

uint256 public constant RESERVED_TOKENS = 2;`

5. File: juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol (line 51): `uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;` 6. File: juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol (line 87): `uint256 internal constant _FEE_CAP = 50_000_000;` 7. File: juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol (line 93): `uint256 internal constant _PROTOCOL_PROJECT_ID = 1;`

[G-09] Empty blocks should be removed or emit something (The code should be refactored such that they no longer exist, or the block should do something useful, such as emitting an event or reverting. If the contract is meant to be extended, the contract should be abstract and the function signatures be added without any default implementation. If the block is an empty if-statement block to avoid doing subsequent checks in the else-if/else conditions, the else-if/else conditions should be nested under the negation of the if-statement, because they involve different classes of checks, which may lead to the introduction of errors when the code is later modified (if(x){}else if(y){...}else{...} => if(!x){if(y){...}else{...}})):-

1. File: juice-contracts-v2-code4rena/contracts/JBFundingCycleStore.sol (line 279): `constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}`
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