Juicebox V2 contest - cRat1st0s'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: 83/105

Findings: 1

Award: $38.83

🌟 Selected for report: 0

🚀 Solo Findings: 0

juice-contracts-v2-code4rena Report

Gas Optimizations

Table of Contents

Files Description Table

File NameSHA-1 Hash
juice-contracts-v2-code4rena/contracts/JBController.solc5960f87c250fe3c23c2d1bc3e5af1fe92df0c93
juice-contracts-v2-code4rena/contracts/JBDirectory.sol366c0456a93cb33810bd51e4e19619b00e69cb95
juice-contracts-v2-code4rena/contracts/JBFundingCycleStore.sol0c2234d2f6dd49808c2e97d660cd5c1b1f6d7e29
juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol113adeb8f54af7cad12173e59a712d953b00c026
juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol93d8e77bd32261e14e79f1a6e1790f515d9058e2
juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol05d0633d4ca9bf92d16a61d112a38377a365ff86
juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sold3cd0735082037a1249606c06514b3f4a52b5153

[G-01]: For-Loops: Pre-increments cost less gas compared to post-increments

Impact

Pre-increments cost less gas compared to post-increments.

Code Affected:

juice-contracts-v2-code4rena/contracts/JBController.sol::913 => for (uint256 _i = 0; _i < _splits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBController.sol::1014 => for (uint256 _i; _i < _fundAccessConstraints.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::139 => for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::167 => for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::275 => for (uint256 _i; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::276 => for (uint256 _j = _i + 1; _j < _terminals.length; _j++)

juice-contracts-v2-code4rena/contracts/JBFundingCycleStore.sol::724 => for (uint256 i = 0; i < _discountMultiple; i++) {

juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol::85 => for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol::135 => for (uint256 _i = 0; _i < _operatorData.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol::862 => for (uint256 _i = 0; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::165 => for (uint256 _i = 0; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::204 => for (uint256 _i = 0; _i < _currentSplits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::211 => for (uint256 _j = 0; _j < _splits.length; _j++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::229 => for (uint256 _i = 0; _i < _splits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::304 => for (uint256 _i = 0; _i < _splitCount; _i++) {

Mitigation

Change i++ to ++i.

Tools used

VS Code

[G-02]: For-Loops: Increments can be unchecked

Impact

In Solidity 0.8+, there’s a default overflow check on unsigned integers.

Code Affected:

juice-contracts-v2-code4rena/contracts/JBController.sol::913 => for (uint256 _i = 0; _i < _splits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBController.sol::1014 => for (uint256 _i; _i < _fundAccessConstraints.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::139 => for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::167 => for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::275 => for (uint256 _i; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::276 => for (uint256 _j = _i + 1; _j < _terminals.length; _j++)

juice-contracts-v2-code4rena/contracts/JBFundingCycleStore.sol::724 => for (uint256 i = 0; i < _discountMultiple; i++) {

juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol::85 => for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol::135 => for (uint256 _i = 0; _i < _operatorData.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol::862 => for (uint256 _i = 0; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::165 => for (uint256 _i = 0; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::204 => for (uint256 _i = 0; _i < _currentSplits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::211 => for (uint256 _j = 0; _j < _splits.length; _j++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::229 => for (uint256 _i = 0; _i < _splits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::304 => for (uint256 _i = 0; _i < _splitCount; _i++) {

Mitigation

One example is the code would go from:

for (uint i = 0; i < _prices.length; i++) { priceAverageCumulative += _prices[i]; }

to:

for (uint i = 0; i < _prices.length;) { priceAverageCumulative += _prices[i]; unchecked { i++; } }
Tools used

VS Code

[G-03]: For-Loops: No need to explicitly initialize variables with default values

Impact

If a variable is not set/initialized, it is assumed to have the default value (0, false, 0x0 etc depending on the data type). If you explicitly initialize it with its default value, you are just wasting gas.

Code Affected:

juice-contracts-v2-code4rena/contracts/JBController.sol::913 => for (uint256 _i = 0; _i < _splits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBFundingCycleStore.sol::724 => for (uint256 i = 0; i < _discountMultiple; i++) {

juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol::85 => for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol::135 => for (uint256 _i = 0; _i < _operatorData.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol::862 => for (uint256 _i = 0; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::165 => for (uint256 _i = 0; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::204 => for (uint256 _i = 0; _i < _currentSplits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::211 => for (uint256 _j = 0; _j < _splits.length; _j++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::229 => for (uint256 _i = 0; _i < _splits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::304 => for (uint256 _i = 0; _i < _splitCount; _i++) {

juice-contracts-v2-code4rena/contracts/JBPayoutRedemptionPaymentTerminal.sol::594 => for (uint256 _i = 0; _i < _heldFeeLength; ) {

juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol::1008 => for (uint256 _i = 0; _i < _splits.length; ) {

juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol::1396 => for (uint256 _i = 0; _i < _heldFeesLength; ) {

Mitigation

Do not initialize variables with default values.

Tools used

VS Code

[G-04]: For-Loops: Cache Array Length Outside of Loop

Impact

Reading array length at each iteration of the loop takes 6 gas (3 for mload and 3 to place memory_offset) in the stack. Caching the array length in the stack saves around 3 gas per iteration.

Code Affected:

juice-contracts-v2-code4rena/contracts/JBController.sol::913 => for (uint256 _i = 0; _i < _splits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBController.sol::1014 => for (uint256 _i; _i < _fundAccessConstraints.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::139 => for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::167 => for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::275 => for (uint256 _i; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBDirectory.sol::276 => for (uint256 _j = _i + 1; _j < _terminals.length; _j++)

juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol::85 => for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBOperatorStore.sol::135 => for (uint256 _i = 0; _i < _operatorData.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol::862 => for (uint256 _i = 0; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::165 => for (uint256 _i = 0; _i < _terminals.length; _i++)

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::204 => for (uint256 _i = 0; _i < _currentSplits.length; _i++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::211 => for (uint256 _j = 0; _j < _splits.length; _j++) {

juice-contracts-v2-code4rena/contracts/JBSplitsStore.sol::229 => for (uint256 _i = 0; _i < _splits.length; _i++) {

juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol::1008 => for (uint256 _i = 0; _i < _splits.length; ) {

Mitigation

Storing the array's length in a variable before the for-loop, and use it instead.

Tools used

VS Code

[G-05]: variable1 += variable2

Impact

variable1 += variable2 costs more gas than variable1 = variable1 + variable2

Code Affected:

juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol::860 => _feeEligibleDistributionAmount += _leftoverDistributionAmount;

juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol::1038 => feeEligibleDistributionAmount += _payoutAmount;

juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol::1103 => feeEligibleDistributionAmount += _payoutAmount;

juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol::1145 => feeEligibleDistributionAmount += _payoutAmount;

juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol::1401 => refundedFees += _feeAmount(

juice-contracts-v2-code4rena/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol::1417 => refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);

Mitigation

Use variable1 = variable1 + variable2 instead.

Tools used

VS Code

[G-06]: 10e18 instead of 10**18

Impact

10e18 is more gas efficient than 10**18

Code Affected:

juice-contracts-v2-code4rena/contracts/JBSingleTokenPaymentTerminalStore.sol ::868 => : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));_leftoverDistributionAmount;

Mitigation

Use 10e18 instead.

Tools used

VS Code

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