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: 27/105
Findings: 1
Award: $374.22
🌟 Selected for report: 1
🚀 Solo Findings: 0
🌟 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
374.2153 USDC - $374.22
Running checks before doing other operations can save gas in case the checks don't pass (since less operations were done before the revert).
Lines: JBDirectory.sol#L270-L278
Gas saved: Not measured by tests, can be a few dozen of thousands in case of revert (tested with a contract mocking the same behavior and 3 terminals)
- // Delete the stored terminals for the project. - _terminalsOf[_projectId] = _terminals; - // Make sure duplicates were not added. + // @audit run checks before assigning, to save gas in case of revert if (_terminals.length > 1) for (uint256 _i; _i < _terminals.length; _i++) for (uint256 _j = _i + 1; _j < _terminals.length; _j++) if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS(); + // Delete the stored terminals for the project. + _terminalsOf[_projectId] = _terminals; + emit SetTerminals(_projectId, _terminals, msg.sender);
<sup>^ back to top ^</sup>
When the same array/mapping element is accessed more than once at the same block (without being modified) - it's cheaper to store the element as a var and access that var every time.
Lines: JBDirectory.sol#L227-L234
Gas saved: up to 2K units
+ address currentController = controllerOf[_projectId]; // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise. if ( - msg.sender != address(controllerOf[_projectId]) && - controllerOf[_projectId] != address(0) && + msg.sender != currentController && + currentController != address(0) && !uint8(_fundingCycle.metadata >> 8).setControllerAllowed()
// Check to see if all locked splits are included. for (uint256 _i = 0; _i < _currentSplits.length; _i++) { + JBSplit memory _currentSplit_i = _currentSplits[_i]; // If not locked, continue. - if (block.timestamp >= _currentSplits[_i].lockedUntil) continue; + if (block.timestamp >= _currentSplit_i.lockedUntil) continue; // Keep a reference to whether or not the locked split being iterated on is included. bool _includesLocked = false; for (uint256 _j = 0; _j < _splits.length; _j++) { // Check for sameness. + JBSplit memory _split_j = _splits[_j]; if ( - _splits[_j].percent == _currentSplits[_i].percent && - _splits[_j].beneficiary == _currentSplits[_i].beneficiary && - _splits[_j].allocator == _currentSplits[_i].allocator && - _splits[_j].projectId == _currentSplits[_i].projectId && + _split_j.percent == _currentSplit_i.percent && + _split_j.beneficiary == _currentSplit_i.beneficiary && + _split_j.allocator == _currentSplit_i.allocator && + _split_j.projectId == _currentSplit_i.projectId && // Allow lock extention. - _splits[_j].lockedUntil >= _currentSplits[_i].lockedUntil + _split_j.lockedUntil >= _currentSplit_i.lockedUntil ) _includesLocked = true; } @@ -227,14 +229,15 @@ contract JBSplitsStore is IJBSplitsStore, JBOperatable { uint256 _percentTotal = 0; for (uint256 _i = 0; _i < _splits.length; _i++) { + JBSplit memory _splits_i = _splits[_i]; // The percent should be greater than 0. - if (_splits[_i].percent == 0) revert INVALID_SPLIT_PERCENT(); + if (_splits_i.percent == 0) revert INVALID_SPLIT_PERCENT(); // ProjectId should be within a uint56 - if (_splits[_i].projectId > type(uint56).max) revert INVALID_PROJECT_ID(); + if (_splits_i.projectId > type(uint56).max) revert INVALID_PROJECT_ID(); // Add to the total percents. - _percentTotal = _percentTotal + _splits[_i].percent; + _percentTotal = _percentTotal + _splits_i.percent; // Validate the total does not exceed the expected value. if (_percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) revert INVALID_TOTAL_PERCENT(); @@ -242,28 +245,28 @@ contract JBSplitsStore is IJBSplitsStore, JBOperatable { uint256 _packedSplitParts1; // prefer claimed in bit 0. - if (_splits[_i].preferClaimed) _packedSplitParts1 = 1; + if (_splits_i.preferClaimed) _packedSplitParts1 = 1; // prefer add to balance in bit 1. - if (_splits[_i].preferAddToBalance) _packedSplitParts1 |= 1 << 1; + if (_splits_i.preferAddToBalance) _packedSplitParts1 |= 1 << 1; // percent in bits 2-33. - _packedSplitParts1 |= _splits[_i].percent << 2; + _packedSplitParts1 |= _splits_i.percent << 2; // projectId in bits 32-89. - _packedSplitParts1 |= _splits[_i].projectId << 34; + _packedSplitParts1 |= _splits_i.projectId << 34; // beneficiary in bits 90-249. - _packedSplitParts1 |= uint256(uint160(address(_splits[_i].beneficiary))) << 90; + _packedSplitParts1 |= uint256(uint160(address(_splits_i.beneficiary))) << 90; // Store the first spit part. _packedSplitParts1Of[_projectId][_domain][_group][_i] = _packedSplitParts1; // If there's data to store in the second packed split part, pack and store. - if (_splits[_i].lockedUntil > 0 || _splits[_i].allocator != IJBSplitAllocator(address(0))) { + if (_splits_i.lockedUntil > 0 || _splits_i.allocator != IJBSplitAllocator(address(0))) { // Locked until should be within a uint48 - if (_splits[_i].lockedUntil > type(uint48).max) revert INVALID_LOCKED_UNTIL(); + if (_splits_i.lockedUntil > type(uint48).max) revert INVALID_LOCKED_UNTIL(); // lockedUntil in bits 0-47. - uint256 _packedSplitParts2 = uint48(_splits[_i].lockedUntil); + uint256 _packedSplitParts2 = uint48(_splits_i.lockedUntil); // allocator in bits 48-207. - _packedSplitParts2 |= uint256(uint160(address(_splits[_i].allocator))) << 48; + _packedSplitParts2 |= uint256(uint160(address(_splits_i.allocator))) << 48; // Store the second split part. _packedSplitParts2Of[_projectId][_domain][_group][_i] = _packedSplitParts2; @@ -272,7 +275,7 @@ contract JBSplitsStore is IJBSplitsStore, JBOperatable { } else if (_packedSplitParts2Of[_projectId][_domain][_group][_i] > 0) delete _packedSplitParts2Of[_projectId][_domain][_group][_i]; - emit SetSplit(_projectId, _domain, _group, _splits[_i], msg.sender); + emit SetSplit(_projectId, _domain, _group, _splits_i, msg.sender); } // Set the new length of the splits. diff --git a/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol b/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol index 83c7066..334f005 100644
abstract/JBPayoutRedemptionPaymentTerminal.sol#L594-L603
--- a/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol +++ b/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol @@ -592,17 +592,14 @@ abstract contract JBPayoutRedemptionPaymentTerminal is // Process each fee. for (uint256 _i = 0; _i < _heldFeeLength; ) { + JBFee memory _heldFees_i = _heldFees[_i]; // Get the fee amount. - uint256 _amount = _feeAmount( - _heldFees[_i].amount, - _heldFees[_i].fee, - _heldFees[_i].feeDiscount - ); + uint256 _amount = _feeAmount(_heldFees_i.amount, _heldFees_i.fee, _heldFees_i.feeDiscount); // Process the fee. - _processFee(_amount, _heldFees[_i].beneficiary); + _processFee(_amount, _heldFees_i.beneficiary); - emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender); + emit ProcessFee(_projectId, _amount, true, _heldFees_i.beneficiary, msg.sender); unchecked { ++_i; @@ -1394,27 +1391,25 @@ abstract contract JBPayoutRedemptionPaymentTerminal is
abstract/JBPayoutRedemptionPaymentTerminal.sol#L1393-L1415
// Process each fee. for (uint256 _i = 0; _i < _heldFeesLength; ) { - if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]); - else if (leftoverAmount >= _heldFees[_i].amount) { + JBFee memory _heldFees_i = _heldFees[_i]; + + if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees_i); + else if (leftoverAmount >= _heldFees_i.amount) { unchecked { - leftoverAmount = leftoverAmount - _heldFees[_i].amount; - refundedFees += _feeAmount( - _heldFees[_i].amount, - _heldFees[_i].fee, - _heldFees[_i].feeDiscount - ); + leftoverAmount = leftoverAmount - _heldFees_i.amount; + refundedFees += _feeAmount(_heldFees_i.amount, _heldFees_i.fee, _heldFees_i.feeDiscount); } } else { _heldFeesOf[_projectId].push( JBFee( - _heldFees[_i].amount - leftoverAmount, - _heldFees[_i].fee, - _heldFees[_i].feeDiscount, - _heldFees[_i].beneficiary + _heldFees_i.amount - leftoverAmount, + _heldFees_i.fee, + _heldFees_i.feeDiscount, + _heldFees_i.beneficiary ) ); unchecked { - refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount); + refundedFees += _feeAmount(leftoverAmount, _heldFees_i.fee, _heldFees_i.feeDiscount); }
+ IJBPaymentTerminal[] storage _terminalOf_projectId = _terminalsOf[_projectId]; // Return the first terminal which accepts the specified token. - for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) { - IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i]; + for (uint256 _i; _i < _terminalOf_projectId.length; _i++) { + IJBPaymentTerminal _terminal = _terminalOf_projectId[_i]; if (_terminal.acceptsToken(_token, _projectId)) return _terminal; }
Gas diff:
╭──────────────────────────────────────────────────┬─────────────────┬─────────┬─────────┬─────────┬─────────╮ │ contracts/JBController.sol:JBController contract ┆ ┆ ┆ ┆ ┆ │ ╞══════════════════════════════════════════════════╪═════════════════╪═════════╪═════════╪═════════╪═════════╡ @@ -155,7 +155,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.47s ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ launchProjectFor ┆ 287999 ┆ 365217 ┆ 364031 ┆ 523893 ┆ 14 │ +│ launchProjectFor ┆ 287838 ┆ 365019 ┆ 363870 ┆ 523212 ┆ 14 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -172,7 +172,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.47s ╞════════════════════════════════════════════════╪═════════════════╪═══════╪════════╪═══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ 1250080 ┆ 6710 ┆ ┆ ┆ ┆ │ +│ 1247680 ┆ 6698 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -180,9 +180,9 @@ Test result: ok. 1 passed; 0 failed; finished in 14.47s ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ isTerminalOf ┆ 633 ┆ 1508 ┆ 1065 ┆ 5065 ┆ 26 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ primaryTerminalOf ┆ 2356 ┆ 3304 ┆ 2356 ┆ 6046 ┆ 12 │ +│ primaryTerminalOf ┆ 2295 ┆ 3221 ┆ 2295 ┆ 5853 ┆ 12 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ setControllerOf ┆ 31973 ┆ 34544 ┆ 36473 ┆ 36473 ┆ 14 │ +│ setControllerOf ┆ 31812 ┆ 34383 ┆ 36312 ┆ 36312 ┆ 14 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ setIsAllowedToSetFirstController ┆ 24668 ┆ 24668 ┆ 24668 ┆ 24668 ┆ 25 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -195,7 +195,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.47s ╞══════════════════════════════════════════════════════════════════════╪═════════════════╪════════╪════════╪════════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ 4138839 ┆ 22186 ┆ ┆ ┆ ┆ │ +│ 4072954 ┆ 21857 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -207,7 +207,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.47s ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ distributePayoutsOf ┆ 99235 ┆ 99235 ┆ 99235 ┆ 99235 ┆ 1 │ +│ distributePayoutsOf ┆ 99113 ┆ 99113 ┆ 99113 ┆ 99113 ┆ 1 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -219,7 +219,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.47s ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ useAllowanceOf ┆ 154127 ┆ 157264 ┆ 157264 ┆ 160402 ┆ 2 │ +│ useAllowanceOf ┆ 154005 ┆ 157142 ┆ 157142 ┆ 160280 ┆ 2 │ ╰──────────────────────────────────────────────────────────────────────┴─────────────────┴────────┴────────┴────────┴─────────╯ ╭────────────────────────────────────────────────────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ │ contracts/JBETHERC20SplitsPayer.sol:JBETHERC20SplitsPayer contract ┆ ┆ ┆ ┆ ┆ │ @@ -237,7 +237,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.47s ╞══════════════════════════════════════════════════════════════════╪═════════════════╪════════╪════════╪════════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ 4084203 ┆ 21595 ┆ ┆ ┆ ┆ │ +│ 4018311 ┆ 21266 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -249,7 +249,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.47s ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ distributePayoutsOf ┆ 102362 ┆ 129157 ┆ 129157 ┆ 155953 ┆ 2 │ +│ distributePayoutsOf ┆ 102240 ┆ 128903 ┆ 128903 ┆ 155567 ┆ 2 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -261,7 +261,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.47s ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ useAllowanceOf ┆ 164853 ┆ 164853 ┆ 164853 ┆ 164853 ┆ 1 │ +│ useAllowanceOf ┆ 164731 ┆ 164731 ┆ 164731 ┆ 164731 ┆ 1 │ ╰──────────────────────────────────────────────────────────────────┴─────────────────┴────────┴────────┴────────┴─────────╯ ╭────────────────────────────────────────────────────────────────┬─────────────────┬───────┬────────┬────────┬─────────╮ │ contracts/JBFundingCycleStore.sol:JBFundingCycleStore contract ┆ ┆ ┆ ┆ ┆ │ @@ -353,13 +353,13 @@ Test result: ok. 1 passed; 0 failed; finished in 14.47s ╞════════════════════════════════════════════════════╪═════════════════╪══════╪════════╪═══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ 862721 ┆ 4670 ┆ ┆ ┆ ┆ │ +│ 751811 ┆ 4116 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ set ┆ 2998 ┆ 5867 ┆ 2998 ┆ 57527 ┆ 19 │ +│ set ┆ 2998 ┆ 5840 ┆ 2998 ┆ 57007 ┆ 19 │ ╰────────────────────────────────────────────────────┴─────────────────┴──────┴────────┴───────┴─────────╯
<sup>^ back to top ^</sup>
Overflowing loop index is virtually impossible, therefore it's cheaper to make the increment unchecked. It's also a bit cheaper to use ++i instead of i++.
Gas saved: up to 300 units
Lines:
diff --git a/contracts/JBController.sol b/contracts/JBController.sol index 26cd238..475a35a 100644 --- a/contracts/JBController.sol +++ b/contracts/JBController.sol @@ -910,7 +910,7 @@ contract JBController is IJBController, IJBMigratable, JBOperatable, ERC165 { JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group); //Transfer between all splits. - for (uint256 _i = 0; _i < _splits.length; _i++) { + for (uint256 _i = 0; _i < _splits.length; ) { // Get a reference to the split being iterated on. JBSplit memory _split = _splits[_i]; @@ -964,6 +964,9 @@ contract JBController is IJBController, IJBMigratable, JBOperatable, ERC165 { _tokenCount, msg.sender ); + unchecked { + ++_i; + } } } @@ -1011,7 +1014,7 @@ contract JBController is IJBController, IJBMigratable, JBOperatable, ERC165 { splitsStore.set(_projectId, _fundingCycle.configuration, _groupedSplits); // Set distribution limits if there are any. - for (uint256 _i; _i < _fundAccessConstraints.length; _i++) { + for (uint256 _i; _i < _fundAccessConstraints.length; ) { JBFundAccessConstraints memory _constraints = _fundAccessConstraints[_i]; // If distribution limit value is larger than 232 bits, revert. @@ -1051,6 +1054,9 @@ contract JBController is IJBController, IJBMigratable, JBOperatable, ERC165 { _constraints, msg.sender ); + unchecked { + ++_i; + } } return _fundingCycle.configuration; diff --git a/contracts/JBDirectory.sol b/contracts/JBDirectory.sol index 865c719..442e704 100644 --- a/contracts/JBDirectory.sol +++ b/contracts/JBDirectory.sol @@ -137,9 +137,12 @@ contract JBDirectory is IJBDirectory, JBOperatable, Ownable { IJBPaymentTerminal[] storage _terminalOf_projectId = _terminalsOf[_projectId]; // Return the first terminal which accepts the specified token. - for (uint256 _i; _i < _terminalOf_projectId.length; _i++) { + for (uint256 _i; _i < _terminalOf_projectId.length; ) { IJBPaymentTerminal _terminal = _terminalOf_projectId[_i]; if (_terminal.acceptsToken(_token, _projectId)) return _terminal; + unchecked { + ++_i; + } } // Not found. @@ -165,8 +168,12 @@ contract JBDirectory is IJBDirectory, JBOperatable, Ownable { override returns (bool) { - for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) + for (uint256 _i; _i < _terminalsOf[_projectId].length; ) { if (_terminalsOf[_projectId][_i] == _terminal) return true; + unchecked { + ++_i; + } + } return false; } @@ -272,9 +279,17 @@ contract JBDirectory is IJBDirectory, JBOperatable, Ownable { // Make sure duplicates were not added. // @audit run checks before assigning, to save gas in case of revert if (_terminals.length > 1) - for (uint256 _i; _i < _terminals.length; _i++) - for (uint256 _j = _i + 1; _j < _terminals.length; _j++) + for (uint256 _i; _i < _terminals.length; ) { + for (uint256 _j = _i + 1; _j < _terminals.length; ) { if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS(); + unchecked { + ++_j; + } + } + unchecked { + ++_i; + } + } // Delete the stored terminals for the project. _terminalsOf[_projectId] = _terminals; diff --git a/contracts/JBETHERC20SplitsPayer.sol b/contracts/JBETHERC20SplitsPayer.sol index 97a6517..6c344bd 100644 --- a/contracts/JBETHERC20SplitsPayer.sol +++ b/contracts/JBETHERC20SplitsPayer.sol @@ -463,7 +463,7 @@ contract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, Reentr leftoverAmount = _amount; // Settle between all splits. - for (uint256 i = 0; i < _splits.length; i++) { + for (uint256 i = 0; i < _splits.length; ) { // Get a reference to the split being iterated on. JBSplit memory _split = _splits[i]; @@ -544,6 +544,9 @@ contract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, Reentr } emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender); + unchecked { + ++i; + } } } } diff --git a/contracts/JBFundingCycleStore.sol b/contracts/JBFundingCycleStore.sol index 13fe9e6..79d16c3 100644 --- a/contracts/JBFundingCycleStore.sol +++ b/contracts/JBFundingCycleStore.sol @@ -312,8 +312,7 @@ contract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility { if (_data.weight > type(uint88).max) revert INVALID_WEIGHT(); // Ballot should be a valid contract, supporting the correct interface - if(_data.ballot != IJBFundingCycleBallot(address(0))) { - + if (_data.ballot != IJBFundingCycleBallot(address(0))) { address _ballot = address(_data.ballot); uint32 _size; assembly { @@ -721,7 +722,7 @@ contract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility { // Apply the base funding cycle's discount rate for each cycle that has passed. uint256 _discountMultiple = _startDistance / _baseFundingCycle.duration; - for (uint256 i = 0; i < _discountMultiple; i++) { + for (uint256 i = 0; i < _discountMultiple; ) { // The number of times to apply the discount rate. // Base the new weight on the specified funding cycle's weight. weight = PRBMath.mulDiv( @@ -731,6 +732,9 @@ contract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility { ); // The calculation doesn't need to continue if the weight is 0. if (weight == 0) break; + unchecked { + ++i; + } } } diff --git a/contracts/JBOperatorStore.sol b/contracts/JBOperatorStore.sol index e1e0241..e67f97d 100644 --- a/contracts/JBOperatorStore.sol +++ b/contracts/JBOperatorStore.sol @@ -82,13 +82,16 @@ contract JBOperatorStore is IJBOperatorStore { uint256 _domain, uint256[] calldata _permissionIndexes ) external view override returns (bool) { - for (uint256 _i = 0; _i < _permissionIndexes.length; _i++) { + for (uint256 _i = 0; _i < _permissionIndexes.length; ) { uint256 _permissionIndex = _permissionIndexes[_i]; if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS(); if (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 0) return false; + unchecked { + ++_i; + } } return true; } @@ -132,7 +135,7 @@ contract JBOperatorStore is IJBOperatorStore { @param _operatorData The data that specify the params for each operator being set. */ function setOperators(JBOperatorData[] calldata _operatorData) external override { - for (uint256 _i = 0; _i < _operatorData.length; _i++) { + for (uint256 _i = 0; _i < _operatorData.length; ) { // Pack the indexes into a uint256. uint256 _packed = _packedPermissions(_operatorData[_i].permissionIndexes); @@ -146,6 +149,9 @@ contract JBOperatorStore is IJBOperatorStore { _operatorData[_i].permissionIndexes, _packed ); + unchecked { + ++_i; + } } } @@ -162,13 +168,16 @@ contract JBOperatorStore is IJBOperatorStore { @return packed The packed value. */ function _packedPermissions(uint256[] calldata _indexes) private pure returns (uint256 packed) { - for (uint256 _i = 0; _i < _indexes.length; _i++) { + for (uint256 _i = 0; _i < _indexes.length; ) { uint256 _index = _indexes[_i]; if (_index > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS(); // Turn the bit at the index on. packed |= 1 << _index; + unchecked { + ++_i; + } } } } diff --git a/contracts/JBSingleTokenPaymentTerminalStore.sol b/contracts/JBSingleTokenPaymentTerminalStore.sol index 4fc5d46..21be5ff 100644 --- a/contracts/JBSingleTokenPaymentTerminalStore.sol +++ b/contracts/JBSingleTokenPaymentTerminalStore.sol @@ -859,8 +859,12 @@ contract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore uint256 _ethOverflow; // Add the current ETH overflow for each terminal. - for (uint256 _i = 0; _i < _terminals.length; _i++) + for (uint256 _i = 0; _i < _terminals.length; ) { _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId); + unchecked { + ++_i; + } + } // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals. uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH diff --git a/contracts/JBSplitsStore.sol b/contracts/JBSplitsStore.sol index be0d17b..2c9d371 100644 --- a/contracts/JBSplitsStore.sol +++ b/contracts/JBSplitsStore.sol @@ -201,7 +201,7 @@ contract JBSplitsStore is IJBSplitsStore, JBOperatable { JBSplit[] memory _currentSplits = _getStructsFor(_projectId, _domain, _group); // Check to see if all locked splits are included. - for (uint256 _i = 0; _i < _currentSplits.length; _i++) { + for (uint256 _i = 0; _i < _currentSplits.length; ) { JBSplit memory _currentSplit_i = _currentSplits[_i]; // If not locked, continue. if (block.timestamp >= _currentSplit_i.lockedUntil) continue; @@ -209,7 +209,7 @@ contract JBSplitsStore is IJBSplitsStore, JBOperatable { // Keep a reference to whether or not the locked split being iterated on is included. bool _includesLocked = false; - for (uint256 _j = 0; _j < _splits.length; _j++) { + for (uint256 _j = 0; _j < _splits.length; ) { // Check for sameness. JBSplit memory _split_j = _splits[_j]; if ( @@ -220,15 +220,22 @@ contract JBSplitsStore is IJBSplitsStore, JBOperatable { // Allow lock extention. _split_j.lockedUntil >= _currentSplit_i.lockedUntil ) _includesLocked = true; + unchecked { + ++_j; + } } if (!_includesLocked) revert PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED(); + + unchecked { + ++_i; + } } // Add up all the percents to make sure they cumulative are under 100%. uint256 _percentTotal = 0; - for (uint256 _i = 0; _i < _splits.length; _i++) { + for (uint256 _i = 0; _i < _splits.length; ) { JBSplit memory _splits_i = _splits[_i]; // The percent should be greater than 0. if (_splits_i.percent == 0) revert INVALID_SPLIT_PERCENT(); @@ -276,6 +283,9 @@ contract JBSplitsStore is IJBSplitsStore, JBOperatable { delete _packedSplitParts2Of[_projectId][_domain][_group][_i]; emit SetSplit(_projectId, _domain, _group, _splits_i, msg.sender); + unchecked { + ++_i; + } } // Set the new length of the splits. @@ -304,7 +314,7 @@ contract JBSplitsStore is IJBSplitsStore, JBOperatable { JBSplit[] memory _splits = new JBSplit[](_splitCount); // Loop through each split and unpack the values into structs. - for (uint256 _i = 0; _i < _splitCount; _i++) { + for (uint256 _i = 0; _i < _splitCount; ) { // Get a reference to the fist packed data. uint256 _packedSplitPart1 = _packedSplitParts1Of[_projectId][_domain][_group][_i]; @@ -335,6 +345,9 @@ contract JBSplitsStore is IJBSplitsStore, JBOperatable { // Add the split to the value being returned. _splits[_i] = _split; + unchecked { + ++_i; + } } return _splits;
Gas diff:
╭──────────────────────────────────────────────────┬─────────────────┬─────────┬─────────┬─────────┬─────────╮ │ contracts/JBController.sol:JBController contract ┆ ┆ ┆ ┆ ┆ │ ╞══════════════════════════════════════════════════╪═════════════════╪═════════╪═════════╪═════════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ 3979659 ┆ 20791 ┆ ┆ ┆ ┆ │ +│ 3970050 ┆ 20743 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ burnTokensOf ┆ 30462 ┆ 33235 ┆ 30462 ┆ 38783 ┆ 3 │ +│ burnTokensOf ┆ 30462 ┆ 33211 ┆ 30462 ┆ 38709 ┆ 3 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -155,9 +155,9 @@ Test result: ok. 1 passed; 0 failed; finished in 14.33s ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ launchProjectFor ┆ 287838 ┆ 365019 ┆ 363870 ┆ 523212 ┆ 14 │ +│ launchProjectFor ┆ 287838 ┆ 364965 ┆ 363870 ┆ 522765 ┆ 14 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ mintTokensOf ┆ 20132 ┆ 55030 ┆ 42967 ┆ 102610 ┆ 13 │ +│ mintTokensOf ┆ 20058 ┆ 55019 ┆ 42967 ┆ 102610 ┆ 13 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -172,21 +172,21 @@ Test result: ok. 1 passed; 0 failed; finished in 14.33s ╞════════════════════════════════════════════════╪═════════════════╪═══════╪════════╪═══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ 1247680 ┆ 6698 ┆ ┆ ┆ ┆ │ +│ 1232666 ┆ 6623 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ isTerminalOf ┆ 633 ┆ 1508 ┆ 1065 ┆ 5065 ┆ 26 │ +│ isTerminalOf ┆ 633 ┆ 1497 ┆ 1065 ┆ 5065 ┆ 26 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ primaryTerminalOf ┆ 2295 ┆ 3221 ┆ 2295 ┆ 5853 ┆ 12 │ +│ primaryTerminalOf ┆ 2295 ┆ 3209 ┆ 2295 ┆ 5779 ┆ 12 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ setTerminalsOf ┆ 54817 ┆ 57189 ┆ 54817 ┆ 78546 ┆ 10 │ +│ setTerminalsOf ┆ 54817 ┆ 57167 ┆ 54817 ┆ 78324 ┆ 10 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ terminalsOf ┆ 1389 ┆ 1389 ┆ 1389 ┆ 1389 ┆ 2 │ ╰────────────────────────────────────────────────┴─────────────────┴───────┴────────┴───────┴─────────╯ @@ -226,7 +226,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.33s ╞════════════════════════════════════════════════════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ 2292746 ┆ 12218 ┆ ┆ ┆ ┆ │ +│ 2283531 ┆ 12172 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -249,13 +249,13 @@ Test result: ok. 1 passed; 0 failed; finished in 14.33s ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ distributePayoutsOf ┆ 102240 ┆ 128903 ┆ 128903 ┆ 155567 ┆ 2 │ +│ distributePayoutsOf ┆ 102240 ┆ 128758 ┆ 128758 ┆ 155276 ┆ 2 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ pay ┆ 89467 ┆ 105031 ┆ 105031 ┆ 120596 ┆ 2 │ +│ pay ┆ 89319 ┆ 104957 ┆ 104957 ┆ 120596 ┆ 2 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ redeemTokensOf ┆ 68162 ┆ 87607 ┆ 87607 ┆ 107052 ┆ 2 │ +│ redeemTokensOf ┆ 68162 ┆ 87496 ┆ 87496 ┆ 106830 ┆ 2 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ supportsInterface ┆ 503 ┆ 685 ┆ 655 ┆ 853 ┆ 9 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -268,7 +268,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.33s ╞════════════════════════════════════════════════════════════════╪═════════════════╪═══════╪════════╪════════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ 1055746 ┆ 5457 ┆ ┆ ┆ ┆ │ +│ 1048339 ┆ 5420 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -330,7 +330,7 @@ Test result: ok. 1 passed; 0 failed; finished in 14.33s ╞════════════════════════════════════════════════════════════════════════════════════════════╪═════════════════╪═══════╪════════╪═══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ 2551081 ┆ 13119 ┆ ┆ ┆ ┆ │ +│ 2543674 ┆ 13082 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ @@ -338,13 +338,13 @@ Test result: ok. 1 passed; 0 failed; finished in 14.33s ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ currentTotalOverflowOf ┆ 31426 ┆ 31426 ┆ 31426 ┆ 31426 ┆ 1 │ +│ currentTotalOverflowOf ┆ 31278 ┆ 31278 ┆ 31278 ┆ 31278 ┆ 1 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ recordRedemptionFor ┆ 25847 ┆ 33828 ┆ 25847 ┆ 49791 ┆ 3 │ +│ recordRedemptionFor ┆ 25847 ┆ 33779 ┆ 25847 ┆ 49643 ┆ 3 │ ╰────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────┴───────┴────────┴───────┴─────────╯ @@ -353,15 +353,15 @@ Test result: ok. 1 passed; 0 failed; finished in 14.33s ╞════════════════════════════════════════════════════╪═════════════════╪══════╪════════╪═══════╪═════════╡ │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ 751811 ┆ 4116 ┆ ┆ ┆ ┆ │ +│ 736791 ┆ 4041 ┆ ┆ ┆ ┆ │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ set ┆ 2998 ┆ 5840 ┆ 2998 ┆ 57007 ┆ 19 │ +│ set ┆ 2998 ┆ 5836 ┆ 2998 ┆ 56930 ┆ 19 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ -│ splitsOf ┆ 2941 ┆ 4853 ┆ 2941 ┆ 8679 ┆ 3 │ +│ splitsOf ┆ 2941 ┆ 4830 ┆ 2941 ┆ 8610 ┆ 3 │
#0 - drgorillamd
2022-07-13T13:09:29Z
Really nice PoC/gas analysis, thank you