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
Rank: 56/105
Findings: 2
Award: $128.02
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0x29A, 0xDjango, 0xNazgul, 0xNineDec, 0xdanial, 0xf15ers, Bnke0x0, Ch_301, Chandr, Chom, Funen, GimelSec, Hawkeye, JC, Kaiziron, Lambda, Meera, MiloTruck, Noah3o6, Picodes, ReyAdmirado, Rohan16, Sm4rty, TerrierLover, TomJ, Waze, _Adam, __141345__, asutorufos, aysha, berndartmueller, brgltd, cccz, codexploder, defsec, delfin454000, djxploit, durianSausage, fatherOfBlocks, hake, horsefacts, hubble, jayfromthe13th, joestakey, jonatascm, m_Rassska, oyc_109, pashov, rajatbeladiya, rbserver, robee, sach1r0, sahar, samruna, simon135, svskaushik, zzzitron
89.1918 USDC - $89.19
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
🌟 Selected for report: 0xA5DF
Also found by: 0v3rf10w, 0x09GTO, 0x1f8b, 0x29A, 0xDjango, 0xKitsune, 0xNazgul, 0xdanial, 0xf15ers, Aymen0909, Bnke0x0, Ch_301, Cheeezzyyyy, Chom, ElKu, Funen, Hawkeye, IllIllI, JC, JohnSmith, Kaiziron, Lambda, Limbooo, Meera, Metatron, MiloTruck, Noah3o6, Picodes, Randyyy, RedOneN, ReyAdmirado, Rohan16, Saintcode_, Sm4rty, TomJ, Tomio, Tutturu, UnusualTurtle, Waze, _Adam, __141345__, ajtra, apostle0x01, asutorufos, brgltd, c3phas, cRat1st0s, codexploder, defsec, delfin454000, djxploit, durianSausage, exd0tpy, fatherOfBlocks, hake, horsefacts, ignacio, jayfromthe13th, joestakey, jonatascm, kaden, kebabsec, m_Rassska, mektigboy, mrpathfindr, oyc_109, rajatbeladiya, rbserver, rfa, robee, sach1r0, sashik_eth, simon135
38.8282 USDC - $38.83
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++) {
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++)
File: JBFundingCycleStore.sol 724: for (uint256 i = 0; i < _discountMultiple; i++) {
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++) {
File: JBSingleTokenPaymentTerminalStore.sol 862: for (uint256 _i = 0; _i < _terminals.length; _i++)
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++) {
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++) {
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++)
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++) {
File: JBSingleTokenPaymentTerminalStore.sol 862: for (uint256 _i = 0; _i < _terminals.length; _i++)
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++) {
File JBPayoutRedemptionPaymentTerminal.sol 1008: for (uint256 _i = 0; _i < _splits.length; ) {
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.
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++) {
File: JBFundingCycleStore.sol 724: for (uint256 i = 0; i < _discountMultiple; i++) {
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++) {
File: JBSingleTokenPaymentTerminalStore.sol 862: for (uint256 _i = 0; _i < _terminals.length; _i++)
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++) {
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; ) {