Juicebox V2 contest - brgltd'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: 56/105

Findings: 2

Award: $128.02

🌟 Selected for report: 0

🚀 Solo Findings: 0

USE SAFETRANSFER/SAFETRANSFERFROM INSTEAD OF TRANSFER/TRANSFERFROM

Using transfer/transferFrom instead of safeTransfer/safeTransferFrom may cause silent failures when interacting with existing tokens and could affect token accounting in the contract.

There are 2 instances of this issue

File: contracts/JBERC20PaymentTerminal.sol 87: ? IERC20(token).transfer(_to, _amount) 88: : IERC20(token).transferFrom(_from, _to, _amount);

Consider using safeTransfer and safeTransfer from openzeppelin SafeERC20 library.

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; using SafeERC20 for ERC20

[G-01] ++I AND ++J COSTS LESS GAS THAN I++ AND J++, ESPECIALLY IN LOOPS

Saves about 5 gas per loop.

There are 15 instances of this issue:

File: contracts/JBController.sol 913: for (uint256 _i = 0; _i < _splits.length; _i++) { 1014 for (uint256 _i; _i < _fundAccessConstraints.length; _i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBController.sol

File: contracts/JBDirectory.sol 139: for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) { 167: for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) 275: for (uint256 _i; _i < _terminals.length; _i++) 276: for (uint256 _j = _i + 1; _j < _terminals.length; _j++)

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBDirectory.sol

File: JBFundingCycleStore.sol 724: for (uint256 i = 0; i < _discountMultiple; i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBFundingCycleStore.sol

File: JBOperatorStore.sol 85: for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) { 135: for (uint256 _i = 0; _i < _operatorData.length; _i++) { 165: for (uint256 _i = 0; _i < _indexes.length; _i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBOperatorStore.sol

File: JBSingleTokenPaymentTerminalStore.sol 862: for (uint256 _i = 0; _i < _terminals.length; _i++)

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBSingleTokenPaymentTerminalStore.sol

File: JBSplitsStore.sol 204: for (uint256 _i = 0; _i < _currentSplits.length; _i++) { 211: for (uint256 _j = 0; _j < _splits.length; _j++) { 229: for (uint256 _i = 0; _i < _splits.length; _i++) { 304: for (uint256 _i = 0; _i < _splitCount; _i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBSplitsStore.sol

[G-02] ARRAY.LENGTH SHOULD NOT BE COMPUTED ON EVERY INTERATION DURING A LOOP

Instead of computing array.length for every iteration, the value for array.length should be cached before the loop to save gas.

There are 14 instances of this issue:

File: contracts/JBController.sol 913: for (uint256 _i = 0; _i < _splits.length; _i++) { 1014 for (uint256 _i; _i < _fundAccessConstraints.length; _i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBController.sol

File: contracts/JBDirectory.sol 139: for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) { 167: for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) 275: for (uint256 _i; _i < _terminals.length; _i++) 276: for (uint256 _j = _i + 1; _j < _terminals.length; _j++)

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBDirectory.sol

File: JBOperatorStore.sol 85: for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) { 135: for (uint256 _i = 0; _i < _operatorData.length; _i++) { 165: for (uint256 _i = 0; _i < _indexes.length; _i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBOperatorStore.sol

File: JBSingleTokenPaymentTerminalStore.sol 862: for (uint256 _i = 0; _i < _terminals.length; _i++)

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBSingleTokenPaymentTerminalStore.sol

File: JBSplitsStore.sol 204: for (uint256 _i = 0; _i < _currentSplits.length; _i++) { 211: for (uint256 _j = 0; _j < _splits.length; _j++) { 229: for (uint256 _i = 0; _i < _splits.length; _i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBSplitsStore.sol

File JBPayoutRedemptionPaymentTerminal.sol 1008: for (uint256 _i = 0; _i < _splits.length; ) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol

[G-03] USE VERSION 0.8.15 OF SOLIDITY

The solidity documentation recommends using the latest version of the compiler.

"When deploying contracts, you should use the latest released version of Solidity". https://docs.soliditylang.org/en/v0.8.15/

"Always use the latest version of the compiler to be notified about all recently introduced warnings." https://docs.soliditylang.org/en/v0.8.15/security-considerations.html

Using the latest version can ensure improvements on bytecode size, deployment gas, and runtime gas.

All the contracts in the audit scope are using version 0.8.6 and latest patch version of solidity, at the time of this contest, is 0.8.15.

[G-04] INITIALIZING UINT256 TO ZERO CAN WASTE GAS

Variables of type uint already default to zero if no value is declared. Manually assigning these variables to zero can waste gas.

There are 14 instances of this issue:

File: contracts/JBController.sol 913: for (uint256 _i = 0; _i < _splits.length; _i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBController.sol

File: JBFundingCycleStore.sol 724: for (uint256 i = 0; i < _discountMultiple; i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBFundingCycleStore.sol

File: JBOperatorStore.sol 85: for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) { 135: for (uint256 _i = 0; _i < _operatorData.length; _i++) { 165: for (uint256 _i = 0; _i < _indexes.length; _i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBOperatorStore.sol

File: JBSingleTokenPaymentTerminalStore.sol 862: for (uint256 _i = 0; _i < _terminals.length; _i++)

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBSingleTokenPaymentTerminalStore.sol

File: JBSplitsStore.sol 165: for (uint256 _i = 0; _i < _groupedSplitsLength; ) { 204: for (uint256 _i = 0; _i < _currentSplits.length; _i++) { 211: for (uint256 _j = 0; _j < _splits.length; _j++) { 229: for (uint256 _i = 0; _i < _splits.length; _i++) { 304: for (uint256 _i = 0; _i < _splitCount; _i++) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/JBSplitsStore.sol

File: JBPayoutRedemptionPaymentTerminal.sol 594: for (uint256 _i = 0; _i < _heldFeeLength; ) { 1008: for (uint256 _i = 0; _i < _splits.length; ) { 1396: for (uint256 _i = 0; _i < _heldFeesLength; ) {

https://github.com/jbx-protocol/juice-contracts-v2-code4rena/blob/828bf2f3e719873daa08081cfa0d0a6deaa5ace5/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol

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