@bananapus/core-v6 0.0.41 → 0.0.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -64,7 +64,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
64
64
  //*********************************************************************//
65
65
 
66
66
  error JBMultiTerminal_FeeTerminalNotFound(address token);
67
- error JBMultiTerminal_MintNotAllowed();
67
+ error JBMultiTerminal_MintNotAllowed(uint256 projectId, uint256 splitProjectId, address terminal);
68
68
  error JBMultiTerminal_NoMsgValueAllowed(uint256 value);
69
69
  error JBMultiTerminal_OverflowAlert(uint256 value, uint256 limit);
70
70
  error JBMultiTerminal_PermitAllowanceNotEnough(uint256 amount, uint256 allowance);
@@ -88,9 +88,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
88
88
  // ------------------------ internal constants ----------------------- //
89
89
  //*********************************************************************//
90
90
 
91
- /// @notice Denominator for forward-calculating this terminal's fee from a pre-fee amount.
92
- uint256 internal constant _FEE_AMOUNT_FROM_DENOMINATOR = JBConstants.MAX_FEE / FEE;
93
-
94
91
  /// @notice Project ID #1 receives fees. It should be the first project launched during the deployment process.
95
92
  uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;
96
93
 
@@ -216,7 +213,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
216
213
 
217
214
  // Emit an event for each accounting context.
218
215
  for (uint256 i; i < accountingContexts.length;) {
219
- // slither-disable-next-line reentrancy-events
220
216
  emit SetAccountingContext({projectId: projectId, context: accountingContexts[i], caller: _msgSender()});
221
217
  unchecked {
222
218
  ++i;
@@ -251,15 +247,15 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
251
247
  _addToBalanceOf({
252
248
  projectId: projectId,
253
249
  token: token,
254
- amount: _acceptFundsFor(projectId, token, amount, metadata),
250
+ amount: _acceptFundsFor({projectId: projectId, token: token, amount: amount, metadata: metadata}),
255
251
  shouldReturnHeldFees: shouldReturnHeldFees,
256
252
  memo: memo,
257
253
  metadata: metadata
258
254
  });
259
255
  }
260
256
 
261
- /// @notice Burns project tokens to reclaim a share of the project's surplus (determined by the bonding curve) or
262
- /// to trigger custom logic through the ruleset's data hook and cash out hook.
257
+ /// @notice Cash out project tokens. The project's current ruleset determines the reclaimed surplus and any data
258
+ /// hook or cash out hook behavior.
263
259
  /// @dev Only the token holder or an operator with `CASH_OUT_TOKENS` permission from that holder can call this.
264
260
  /// @param holder The account cashing out tokens.
265
261
  /// @param projectId The ID of the project the project tokens belong to.
@@ -333,7 +329,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
333
329
  if (split.hook != IJBSplitHook(address(0))) {
334
330
  // Make sure that the address supports the split hook interface.
335
331
  if (!split.hook.supportsInterface(type(IJBSplitHook).interfaceId)) {
336
- revert JBMultiTerminal_SplitHookInvalid(split.hook);
332
+ revert JBMultiTerminal_SplitHookInvalid({hook: split.hook});
337
333
  }
338
334
 
339
335
  // This payout is eligible for a fee since the funds are leaving this contract and the split hook isn't a
@@ -373,7 +369,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
373
369
 
374
370
  // The project must have a terminal to send funds to.
375
371
  if (terminal == IJBTerminal(address(0))) {
376
- revert JBMultiTerminal_RecipientProjectTerminalNotFound(split.projectId, token);
372
+ revert JBMultiTerminal_RecipientProjectTerminalNotFound({projectId: split.projectId, token: token});
377
373
  }
378
374
 
379
375
  // Fees apply to fund egress, not intra-terminal accounting. When both projects share this terminal,
@@ -412,7 +408,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
412
408
  // Cross-project pay splits on the same terminal are allowed (different project receives the funds).
413
409
  // The try-catch in the split group lib catches this revert and restores the balance.
414
410
  if (terminal == this && split.projectId == projectId) {
415
- revert JBMultiTerminal_MintNotAllowed();
411
+ revert JBMultiTerminal_MintNotAllowed({
412
+ projectId: projectId, splitProjectId: split.projectId, terminal: address(terminal)
413
+ });
416
414
  }
417
415
 
418
416
  // Keep a reference to the beneficiary of the payment.
@@ -432,7 +430,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
432
430
  // destination project's data hook forwarded part of the payment to pay hooks, the store
433
431
  // only recorded a partial balance increase. Without this cap, _feeFreeSurplusOf can exceed
434
432
  // STORE.balanceOf, causing users to be overcharged fees on zero-tax cashouts.
435
- // slither-disable-next-line reentrancy-eth
436
433
  _capFeeFreeSurplus({projectId: split.projectId, token: token});
437
434
  }
438
435
  } else {
@@ -476,7 +473,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
476
473
  require(msg.sender == address(this));
477
474
 
478
475
  if (address(feeTerminal) == address(0)) {
479
- revert JBMultiTerminal_FeeTerminalNotFound(token);
476
+ revert JBMultiTerminal_FeeTerminalNotFound({token: token});
480
477
  }
481
478
 
482
479
  // Send the projectId in the metadata.
@@ -540,7 +537,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
540
537
  // sends fees to the fee project terminal. The migrated project's balance on this terminal is zero, but held
541
538
  // fees are backed by the terminal's own token balance (not the project's recorded balance).
542
539
  // Record the migration in the store.
543
- // slither-disable-next-line reentrancy-events
544
540
  balance = STORE.recordTerminalMigration({projectId: projectId, token: token});
545
541
 
546
542
  emit MigrateTerminal({projectId: projectId, token: token, to: to, amount: balance, caller: _msgSender()});
@@ -569,8 +565,8 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
569
565
  }
570
566
  }
571
567
 
572
- /// @notice Pay a project with tokens. The project's current ruleset determines how many project tokens the
573
- /// beneficiary will receive.
568
+ /// @notice Pay a project. The project's current ruleset determines how many project tokens the beneficiary receives
569
+ /// and any data hook or pay hook behavior.
574
570
  /// @param projectId The ID of the project to pay.
575
571
  /// @param amount The amount of tokens to send, as a fixed point number with the same number of
576
572
  /// decimals as the token's accounting context. If this terminal's token is native, this is ignored and `msg.value`
@@ -672,7 +668,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
672
668
  _nextHeldFeeIndexOf[projectId][token] = currentIndex + 1;
673
669
 
674
670
  // Process the fee.
675
- // slither-disable-next-line reentrancy-no-eth
676
671
  _processFee({
677
672
  projectId: projectId,
678
673
  token: token,
@@ -1022,7 +1017,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1022
1017
 
1023
1018
  // Make sure the permit allowance is enough for this payment. If not we revert early.
1024
1019
  if (amount > allowance.amount) {
1025
- revert JBMultiTerminal_PermitAllowanceNotEnough(amount, allowance.amount);
1020
+ revert JBMultiTerminal_PermitAllowanceNotEnough({amount: amount, allowance: allowance.amount});
1026
1021
  }
1027
1022
 
1028
1023
  // Keep a reference to the permit rules.
@@ -1037,8 +1032,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1037
1032
  // Set the allowance to `spend` tokens for the user.
1038
1033
  try PERMIT2.permit({owner: _msgSender(), permitSingle: permitSingle, signature: allowance.signature}) {}
1039
1034
  catch (bytes memory reason) {
1040
- // slither-disable-next-line reentrancy-events
1041
- emit Permit2AllowanceFailed(token, _msgSender(), reason);
1035
+ emit Permit2AllowanceFailed({token: token, owner: _msgSender(), reason: reason});
1042
1036
  }
1043
1037
  }
1044
1038
 
@@ -1121,7 +1115,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1121
1115
 
1122
1116
  // Cap fee-free surplus at the remaining balance.
1123
1117
  if (feeFreeSurplus > remainingBalance) {
1124
- // slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
1125
1118
  _feeFreeSurplusOf[projectId][token] = remainingBalance;
1126
1119
  }
1127
1120
  }
@@ -1202,7 +1195,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1202
1195
  uint256 feeFreeSurplus = _feeFreeSurplusOf[projectId][tokenToReclaim];
1203
1196
  if (feeFreeSurplus != 0) {
1204
1197
  uint256 feeableAmount = reclaimAmount < feeFreeSurplus ? reclaimAmount : feeFreeSurplus;
1205
- // slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
1206
1198
  unchecked {
1207
1199
  _feeFreeSurplusOf[projectId][tokenToReclaim] = feeFreeSurplus - feeableAmount;
1208
1200
  }
@@ -1245,7 +1237,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1245
1237
  // balance during a prior inbound payout), overcharging fees on round-trip prevention.
1246
1238
  // Placed after hook fulfillment so any further balance reductions from cashout hooks are
1247
1239
  // also accounted for.
1248
- // slither-disable-next-line reentrancy-eth
1249
1240
  _capFeeFreeSurplus({projectId: projectId, token: tokenToReclaim});
1250
1241
 
1251
1242
  // Take the fee from all outbound reclaimings.
@@ -1347,12 +1338,10 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1347
1338
  } else {
1348
1339
  // Trigger any inherited pre-transfer logic.
1349
1340
  // Keep a reference to the amount that'll be paid as a `msg.value`.
1350
- // slither-disable-next-line reentrancy-events
1351
1341
  uint256 payValue = _beforeTransferTo({to: address(terminal), token: token, amount: amount});
1352
1342
 
1353
1343
  // Send the fee.
1354
1344
  // If this terminal's token is ETH, send it in msg.value.
1355
- // slither-disable-next-line unused-return
1356
1345
  terminal.pay{value: payValue}({
1357
1346
  projectId: projectId,
1358
1347
  token: token,
@@ -1385,7 +1374,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1385
1374
  {
1386
1375
  // Trigger any inherited pre-transfer logic.
1387
1376
  // Keep a reference to the amount that'll be paid as a `msg.value`.
1388
- // slither-disable-next-line reentrancy-events
1389
1377
  uint256 payValue = _beforeTransferTo({to: address(terminal), token: token, amount: amount});
1390
1378
 
1391
1379
  // Add to balance on the recipient terminal.
@@ -1444,7 +1432,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1444
1432
  cashOutMetadata: metadata
1445
1433
  });
1446
1434
 
1447
- // slither-disable-next-line calls-loop
1448
1435
  for (uint256 i; i < specifications.length;) {
1449
1436
  // Set the specification being iterated on.
1450
1437
  JBCashOutHookSpecification memory specification = specifications[i];
@@ -1480,13 +1467,11 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1480
1467
 
1481
1468
  // Trigger any inherited pre-transfer logic.
1482
1469
  // Keep a reference to the amount that'll be paid as a `msg.value`.
1483
- // slither-disable-next-line reentrancy-events
1484
1470
  uint256 payValue = _beforeTransferTo({
1485
1471
  to: address(specification.hook), token: beneficiaryReclaimAmount.token, amount: specification.amount
1486
1472
  });
1487
1473
 
1488
1474
  // Fulfill the specification.
1489
- // slither-disable-next-line reentrancy-events,calls-loop
1490
1475
  specification.hook.afterCashOutRecordedWith{value: payValue}(context);
1491
1476
 
1492
1477
  // Revoke the temporary pull allowance now that the hook call has finished.
@@ -1541,7 +1526,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1541
1526
  });
1542
1527
 
1543
1528
  // Fulfill each specification through their pay hooks.
1544
- // slither-disable-next-line calls-loop
1545
1529
  for (uint256 i; i < specifications.length;) {
1546
1530
  // Set the specification being iterated on.
1547
1531
  JBPayHookSpecification memory specification = specifications[i];
@@ -1567,13 +1551,11 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1567
1551
 
1568
1552
  // Trigger any inherited pre-transfer logic.
1569
1553
  // Keep a reference to the amount that'll be paid as a `msg.value`.
1570
- // slither-disable-next-line reentrancy-events
1571
1554
  uint256 payValue = _beforeTransferTo({
1572
1555
  to: address(specification.hook), token: tokenAmount.token, amount: specification.amount
1573
1556
  });
1574
1557
 
1575
1558
  // Fulfill the specification.
1576
- // slither-disable-next-line reentrancy-events,calls-loop
1577
1559
  specification.hook.afterPayRecordedWith{value: payValue}(context);
1578
1560
 
1579
1561
  // Revoke the temporary pull allowance now that the hook call has finished.
@@ -1621,7 +1603,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1621
1603
  // Keep a reference to the ruleset the payment is being made during.
1622
1604
  // Keep a reference to the pay hook specifications.
1623
1605
  // Keep a reference to the token count that'll be minted as a result of the payment.
1624
- // slither-disable-next-line reentrancy-events
1625
1606
  (JBRuleset memory ruleset, uint256 tokenCount, JBPayHookSpecification[] memory hookSpecifications) = STORE.recordPaymentFrom({
1626
1607
  payer: payer, amount: tokenAmount, projectId: projectId, beneficiary: beneficiary, metadata: metadata
1627
1608
  });
@@ -1633,7 +1614,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1633
1614
  if (tokenCount != 0) {
1634
1615
  // Set the token count to be the number of tokens minted for the beneficiary instead of the total
1635
1616
  // amount.
1636
- // slither-disable-next-line reentrancy-events
1637
1617
  newlyIssuedTokenCount = _controllerOf(projectId)
1638
1618
  .mintTokensOf({
1639
1619
  projectId: projectId,
@@ -1689,7 +1669,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1689
1669
  )
1690
1670
  internal
1691
1671
  {
1692
- // slither-disable-next-line reentrancy-events,calls-loop
1693
1672
  try this.executeProcessFee({
1694
1673
  projectId: projectId, token: token, amount: amount, beneficiary: beneficiary, feeTerminal: feeTerminal
1695
1674
  }) {
@@ -1726,7 +1705,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1726
1705
  /// this
1727
1706
  /// terminal.
1728
1707
  function _recordAddedBalanceFor(uint256 projectId, address token, uint256 amount) internal {
1729
- // slither-disable-next-line calls-loop
1730
1708
  STORE.recordAddedBalanceFor({projectId: projectId, token: token, amount: amount});
1731
1709
  }
1732
1710
 
@@ -1763,7 +1741,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1763
1741
  // Save the fee being iterated on.
1764
1742
  JBFee memory heldFee = _heldFeesOf[projectId][token][startIndex + i];
1765
1743
 
1766
- // slither-disable-next-line incorrect-equality
1767
1744
  if (leftoverAmount == 0) {
1768
1745
  break;
1769
1746
  } else {
@@ -1782,9 +1759,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1782
1759
  // Move the start index forward to the held fee after the current one.
1783
1760
  newStartIndex = startIndex + i + 1;
1784
1761
  } else {
1785
- // Use the floor variant here. The minimum 1-unit fee applies when a fee is created, not while
1786
- // splitting an already-held fee entry across repayments.
1787
- feeAmount = JBFees.feeAmountResultingInFloorForFee25(leftoverAmount);
1762
+ feeAmount = JBFees.feeAmountResultingIn({amountAfterFee: leftoverAmount, feePercent: FEE});
1788
1763
 
1789
1764
  // Get fee from `leftoverAmount`.
1790
1765
  unchecked {
@@ -1883,7 +1858,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1883
1858
  leftoverPayoutAmount = netLeftoverPayoutAmount;
1884
1859
  }
1885
1860
  } catch (bytes memory reason) {
1886
- // slither-disable-next-line reentrancy-events
1887
1861
  emit PayoutTransferReverted({
1888
1862
  projectId: projectId,
1889
1863
  addr: projectOwner,
@@ -1901,7 +1875,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
1901
1875
 
1902
1876
  // Cap fee-free surplus at remaining balance. Non-fee-free funds leave first.
1903
1877
  // Placed after all payouts settle so the cap reflects post-payout state.
1904
- // slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
1905
1878
  _capFeeFreeSurplus({projectId: projectId, token: token});
1906
1879
 
1907
1880
  // Take the fee.
@@ -2047,12 +2020,10 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
2047
2020
  STORE.recordUsedAllowanceOf({projectId: projectId, token: token, amount: amount, currency: currency});
2048
2021
 
2049
2022
  // Cap fee-free surplus at remaining balance. Non-fee-free funds leave first.
2050
- // slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
2051
2023
  _capFeeFreeSurplus({projectId: projectId, token: token});
2052
2024
 
2053
2025
  // Take a fee from the `amountPaidOut`, if needed.
2054
2026
  // The net amount is the final amount withdrawn after the fee has been taken.
2055
- // slither-disable-next-line reentrancy-events
2056
2027
  netAmountPaidOut = amountPaidOut
2057
2028
  - (_isFeeless(owner) || _isFeeless(beneficiary)
2058
2029
  ? 0
@@ -2097,7 +2068,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
2097
2068
  if (token == JBConstants.NATIVE_TOKEN) return;
2098
2069
 
2099
2070
  // Revert if the callee returned without consuming the full forwarded ERC-20 amount.
2100
- // slither-disable-next-line calls-loop
2101
2071
  uint256 allowance = IERC20(token).allowance({owner: address(this), spender: to});
2102
2072
  if (allowance != 0) revert JBMultiTerminal_TemporaryAllowanceNotConsumed(token, to, allowance);
2103
2073
  }
@@ -2202,12 +2172,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
2202
2172
  //*********************************************************************//
2203
2173
 
2204
2174
  /// @notice The terminal fee charged from a pre-fee `amount`.
2205
- /// @dev Returns at least 1 for nonzero feeable amounts so dust payouts cannot bypass protocol fees.
2206
2175
  /// @param amount The amount before the fee is applied.
2207
- /// @return feeAmount The fee amount.
2208
- function _feeAmountFrom(uint256 amount) private pure returns (uint256 feeAmount) {
2209
- feeAmount = amount / _FEE_AMOUNT_FROM_DENOMINATOR;
2210
-
2211
- return feeAmount == 0 && amount != 0 ? 1 : feeAmount;
2176
+ /// @return The fee amount.
2177
+ function _feeAmountFrom(uint256 amount) private pure returns (uint256) {
2178
+ return JBFees.feeAmountFrom({amountBeforeFee: amount, feePercent: FEE});
2212
2179
  }
2213
2180
  }
@@ -17,8 +17,7 @@ contract JBPermissions is ERC2771Context, IJBPermissions {
17
17
  // --------------------------- custom errors ------------------------- //
18
18
  //*********************************************************************//
19
19
 
20
- error JBPermissions_CantSetRootPermissionForWildcardProject();
21
- error JBPermissions_NoZeroPermission();
20
+ error JBPermissions_NoZeroPermission(address account, address operator, uint256 projectId);
22
21
  error JBPermissions_PermissionIdOutOfBounds(uint256 permissionId);
23
22
  error JBPermissions_Unauthorized(address account, address operator, uint256 projectId, uint256 permissionId);
24
23
 
@@ -69,7 +68,11 @@ contract JBPermissions is ERC2771Context, IJBPermissions {
69
68
  uint256 packed = _packedPermissions(permissionsData.permissionIds);
70
69
 
71
70
  // Make sure the 0 permission is not set.
72
- if (_includesPermission({permissions: packed, permissionId: 0})) revert JBPermissions_NoZeroPermission();
71
+ if (_includesPermission({permissions: packed, permissionId: 0})) {
72
+ revert JBPermissions_NoZeroPermission({
73
+ account: account, operator: permissionsData.operator, projectId: permissionsData.projectId
74
+ });
75
+ }
73
76
 
74
77
  // Cache the sender.
75
78
  address msgSender = _msgSender();
package/src/JBPrices.sol CHANGED
@@ -26,9 +26,9 @@ contract JBPrices is JBControlled, JBPermissioned, ERC2771Context, Ownable, IJBP
26
26
  //*********************************************************************//
27
27
 
28
28
  error JBPrices_PriceFeedAlreadyExists(IJBPriceFeed feed);
29
- error JBPrices_PriceFeedNotFound();
30
- error JBPrices_ZeroPricingCurrency();
31
- error JBPrices_ZeroUnitCurrency();
29
+ error JBPrices_PriceFeedNotFound(uint256 projectId, uint256 pricingCurrency, uint256 unitCurrency);
30
+ error JBPrices_ZeroPricingCurrency(uint256 projectId, uint256 pricingCurrency);
31
+ error JBPrices_ZeroUnitCurrency(uint256 projectId, uint256 unitCurrency);
32
32
 
33
33
  //*********************************************************************//
34
34
  // ------------------------- public constants ------------------------ //
@@ -111,20 +111,23 @@ contract JBPrices is JBControlled, JBPermissioned, ERC2771Context, Ownable, IJBP
111
111
  projectId == DEFAULT_PROJECT_ID ? _checkOwner() : _onlyControllerOf(projectId);
112
112
 
113
113
  // Make sure the pricing currency isn't 0.
114
- if (pricingCurrency == 0) revert JBPrices_ZeroPricingCurrency();
114
+ if (pricingCurrency == 0) {
115
+ revert JBPrices_ZeroPricingCurrency({projectId: projectId, pricingCurrency: pricingCurrency});
116
+ }
115
117
 
116
118
  // Make sure the unit currency isn't 0.
117
- if (unitCurrency == 0) revert JBPrices_ZeroUnitCurrency();
119
+ if (unitCurrency == 0) revert JBPrices_ZeroUnitCurrency({projectId: projectId, unitCurrency: unitCurrency});
118
120
 
119
121
  // Make sure there isn't already a default price feed for the pair or its inverse.
120
122
  if (
121
123
  priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
122
124
  || priceFeedFor[DEFAULT_PROJECT_ID][unitCurrency][pricingCurrency] != IJBPriceFeed(address(0))
123
125
  ) {
124
- revert JBPrices_PriceFeedAlreadyExists(priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency]
125
- != IJBPriceFeed(address(0))
126
+ revert JBPrices_PriceFeedAlreadyExists({
127
+ feed: priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
126
128
  ? priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency]
127
- : priceFeedFor[DEFAULT_PROJECT_ID][unitCurrency][pricingCurrency]);
129
+ : priceFeedFor[DEFAULT_PROJECT_ID][unitCurrency][pricingCurrency]
130
+ });
128
131
  }
129
132
 
130
133
  // Make sure this project doesn't already have a price feed for the pair or its inverse.
@@ -132,10 +135,11 @@ contract JBPrices is JBControlled, JBPermissioned, ERC2771Context, Ownable, IJBP
132
135
  priceFeedFor[projectId][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
133
136
  || priceFeedFor[projectId][unitCurrency][pricingCurrency] != IJBPriceFeed(address(0))
134
137
  ) {
135
- revert JBPrices_PriceFeedAlreadyExists(priceFeedFor[projectId][pricingCurrency][unitCurrency]
136
- != IJBPriceFeed(address(0))
138
+ revert JBPrices_PriceFeedAlreadyExists({
139
+ feed: priceFeedFor[projectId][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
137
140
  ? priceFeedFor[projectId][pricingCurrency][unitCurrency]
138
- : priceFeedFor[projectId][unitCurrency][pricingCurrency]);
141
+ : priceFeedFor[projectId][unitCurrency][pricingCurrency]
142
+ });
139
143
  }
140
144
 
141
145
  // Price feed immutability is by design to prevent admin-key attacks on price oracles.
@@ -212,7 +216,9 @@ contract JBPrices is JBControlled, JBPermissioned, ERC2771Context, Ownable, IJBP
212
216
  }
213
217
 
214
218
  // No price feed available, revert.
215
- revert JBPrices_PriceFeedNotFound();
219
+ revert JBPrices_PriceFeedNotFound({
220
+ projectId: projectId, pricingCurrency: pricingCurrency, unitCurrency: unitCurrency
221
+ });
216
222
  }
217
223
 
218
224
  //*********************************************************************//
@@ -123,7 +123,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
123
123
 
124
124
  // Weight cut percent must be less than or equal to 100%.
125
125
  if (weightCutPercent > JBConstants.MAX_WEIGHT_CUT_PERCENT) {
126
- revert JBRulesets_InvalidWeightCutPercent(weightCutPercent);
126
+ revert JBRulesets_InvalidWeightCutPercent({percent: weightCutPercent});
127
127
  }
128
128
 
129
129
  // Weight must fit into a uint112.
@@ -137,7 +137,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
137
137
  // Make sure the min start date fits in a uint48, and that the start date of the following ruleset will also fit
138
138
  // within the max.
139
139
  if (mustStartAtOrAfter + duration > type(uint48).max) {
140
- revert JBRulesets_InvalidRulesetEndTime(mustStartAtOrAfter + duration, type(uint48).max);
140
+ revert JBRulesets_InvalidRulesetEndTime({timestamp: mustStartAtOrAfter + duration, limit: type(uint48).max});
141
141
  }
142
142
 
143
143
  // Approval hook should be a valid contract, supporting the correct interface
@@ -152,7 +152,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
152
152
  // with the
153
153
  // wrong interface
154
154
  } catch {
155
- revert JBRulesets_InvalidRulesetApprovalHook(approvalHook); // No ERC165 support
155
+ revert JBRulesets_InvalidRulesetApprovalHook({hook: approvalHook}); // No ERC165 support
156
156
  }
157
157
  }
158
158
 
@@ -217,7 +217,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
217
217
  _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: false});
218
218
 
219
219
  // Nothing to cache if the target ruleset doesn't have a duration or a weight cut percent.
220
- // slither-disable-next-line incorrect-equality
221
220
  if (targetRuleset.duration == 0 || targetRuleset.weightCutPercent == 0) return;
222
221
 
223
222
  // Get a reference to the current cache.
@@ -356,7 +355,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
356
355
  /// @return ruleset The project's current ruleset.
357
356
  function currentOf(uint256 projectId) external view override returns (JBRuleset memory ruleset) {
358
357
  // If the project does not have a ruleset, return an empty struct.
359
- // slither-disable-next-line incorrect-equality
360
358
  if (latestRulesetIdOf[projectId] == 0) {
361
359
  return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
362
360
  }
@@ -375,7 +373,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
375
373
 
376
374
  // Check to see if this ruleset's approval hook is approved if it exists.
377
375
  // If so, return it.
378
- // slither-disable-next-line incorrect-equality
379
376
  if (approvalStatus == JBApprovalStatus.Approved || approvalStatus == JBApprovalStatus.Empty) {
380
377
  return ruleset;
381
378
  }
@@ -413,7 +410,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
413
410
  }
414
411
 
415
412
  // If the base has no duration, it's still the current one.
416
- // slither-disable-next-line incorrect-equality
417
413
  if (ruleset.duration == 0) return ruleset;
418
414
 
419
415
  // Return a simulation of the current ruleset.
@@ -466,7 +462,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
466
462
  /// @return ruleset The struct for the project's upcoming ruleset.
467
463
  function upcomingOf(uint256 projectId) external view override returns (JBRuleset memory ruleset) {
468
464
  // If the project does not have a latest ruleset, return an empty struct.
469
- // slither-disable-next-line incorrect-equality
470
465
  if (latestRulesetIdOf[projectId] == 0) {
471
466
  return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
472
467
  }
@@ -487,7 +482,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
487
482
 
488
483
  // If the approval hook is empty, expects approval, or has approved the ruleset, return it.
489
484
  if (
490
- // slither-disable-next-line incorrect-equality
491
485
  approvalStatus == JBApprovalStatus.Approved || approvalStatus == JBApprovalStatus.ApprovalExpected
492
486
  || approvalStatus == JBApprovalStatus.Empty
493
487
  ) return ruleset;
@@ -510,7 +504,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
510
504
  }
511
505
 
512
506
  // There's no queued if the current has a duration of 0.
513
- // slither-disable-next-line incorrect-equality
514
507
  if (ruleset.duration == 0) return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
515
508
 
516
509
  // Get a reference to the approval status.
@@ -518,7 +511,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
518
511
 
519
512
  // Check to see if this ruleset's approval hook hasn't failed.
520
513
  // If so, return a ruleset based on it.
521
- // slither-disable-next-line incorrect-equality
522
514
  if (approvalStatus == JBApprovalStatus.Approved || approvalStatus == JBApprovalStatus.Empty) {
523
515
  return _simulateCycledRulesetBasedOn({projectId: projectId, baseRuleset: ruleset, allowMidRuleset: false});
524
516
  }
@@ -528,7 +520,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
528
520
  ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId, withMetadata: true});
529
521
 
530
522
  // There's no queued if the base, which must still be the current, has a duration of 0.
531
- // slither-disable-next-line incorrect-equality
532
523
  if (ruleset.duration == 0) return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
533
524
 
534
525
  // Return a simulated cycled ruleset.
@@ -557,7 +548,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
557
548
  returns (uint256)
558
549
  {
559
550
  // A subsequent ruleset to one with a duration of 0 should be the next number.
560
- // slither-disable-next-line incorrect-equality
561
551
  if (baseRulesetDuration == 0) {
562
552
  return baseRulesetCycleNumber + 1;
563
553
  }
@@ -585,7 +575,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
585
575
  returns (uint256 start)
586
576
  {
587
577
  // A subsequent ruleset to one with a duration of 0 should start as soon as possible.
588
- // slither-disable-next-line incorrect-equality
589
578
  if (baseRulesetDuration == 0) return mustStartAtOrAfter;
590
579
 
591
580
  // The time when the ruleset immediately after the specified ruleset starts.
@@ -598,7 +587,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
598
587
 
599
588
  // The amount of seconds since the `mustStartAtOrAfter` time which results in a start time that might satisfy
600
589
  // the specified limits.
601
- // slither-disable-next-line weak-prng
602
590
  uint256 timeFromImmediateStartMultiple = (mustStartAtOrAfter - nextImmediateStart) % baseRulesetDuration;
603
591
 
604
592
  // A reference to the first possible start timestamp.
@@ -634,7 +622,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
634
622
  returns (uint256 weight)
635
623
  {
636
624
  // A subsequent ruleset to one with a duration of 0 should have the next possible weight.
637
- // slither-disable-next-line incorrect-equality
638
625
  if (baseRulesetDuration == 0) {
639
626
  return mulDiv(
640
627
  baseRulesetWeight,
@@ -647,7 +634,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
647
634
  weight = baseRulesetWeight;
648
635
 
649
636
  // If the weight cut percent is 0, the weight doesn't change.
650
- // slither-disable-next-line incorrect-equality
651
637
  if (baseRulesetWeightCutPercent == 0) return weight;
652
638
 
653
639
  // The difference between the start of the base ruleset and the proposed start.
@@ -678,7 +664,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
678
664
  // If too many iterations remain after cache lookup, require the cache to be populated first.
679
665
  // This prevents gas exhaustion for short-duration rulesets with large cycle counts.
680
666
  if (weightCutMultiple > _WEIGHT_CUT_MULTIPLE_CACHE_LOOKUP_THRESHOLD) {
681
- revert JBRulesets_WeightCacheRequired(projectId);
667
+ revert JBRulesets_WeightCacheRequired({projectId: projectId});
682
668
  }
683
669
 
684
670
  // Cache the cut factor and max percent to avoid recomputing each iteration.
@@ -719,7 +705,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
719
705
  uint256 latestId = latestRulesetIdOf[projectId];
720
706
 
721
707
  // If the project doesn't have a ruleset yet, initialize one.
722
- // slither-disable-next-line incorrect-equality
723
708
  if (latestId == 0) {
724
709
  // Use an empty ruleset as the base.
725
710
  return _initializeRulesetFor({
@@ -807,7 +792,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
807
792
  internal
808
793
  {
809
794
  // If there is no base, initialize a first ruleset.
810
- // slither-disable-next-line incorrect-equality
811
795
  if (baseRuleset.cycleNumber == 0) {
812
796
  // Set fresh intrinsic properties.
813
797
  _packAndStoreIntrinsicPropertiesOf({
@@ -910,7 +894,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
910
894
  /// @return The approval status of the project.
911
895
  function _approvalStatusOf(uint256 projectId, JBRuleset memory ruleset) internal view returns (JBApprovalStatus) {
912
896
  // If there is no ruleset ID to check the approval hook of, the approval hook is empty.
913
- // slither-disable-next-line incorrect-equality
914
897
  if (ruleset.basedOnId == 0) return JBApprovalStatus.Empty;
915
898
 
916
899
  // Read only the packed user properties to extract the approval hook address,
@@ -928,7 +911,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
928
911
  // Wrap in try/catch to prevent a reverting approval hook from permanently freezing the project.
929
912
  // Note: A malicious hook that consumes all gas (e.g. infinite loop) could still DoS via gas exhaustion.
930
913
  // This is accepted risk since the project owner chose their own approval hook.
931
- // slither-disable-next-line calls-loop
932
914
  try approvalHook.approvalStatusOf({projectId: projectId, ruleset: ruleset}) returns (JBApprovalStatus status) {
933
915
  return status;
934
916
  } catch {
@@ -988,7 +970,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
988
970
  returns (JBRuleset memory ruleset)
989
971
  {
990
972
  // Return an empty ruleset if the specified `rulesetId` is 0.
991
- // slither-disable-next-line incorrect-equality
992
973
  if (rulesetId == 0) return ruleset;
993
974
 
994
975
  // forge-lint: disable-next-line(unsafe-typecast)
@@ -1104,12 +1085,10 @@ contract JBRulesets is JBControlled, IJBRulesets {
1104
1085
  JBRuleset memory ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: false});
1105
1086
 
1106
1087
  // There is no upcoming ruleset if the latest ruleset has already started.
1107
- // slither-disable-next-line incorrect-equality
1108
1088
  // forge-lint: disable-next-line(block-timestamp)
1109
1089
  if (block.timestamp >= ruleset.start) return 0;
1110
1090
 
1111
1091
  // If this is the first ruleset, it is queued.
1112
- // slither-disable-next-line incorrect-equality
1113
1092
  if (ruleset.cycleNumber == 1) return rulesetId;
1114
1093
 
1115
1094
  // Get a reference to the ID of the ruleset the latest ruleset was based on.
package/src/JBSplits.sol CHANGED
@@ -20,8 +20,8 @@ contract JBSplits is JBControlled, IJBSplits {
20
20
  //*********************************************************************//
21
21
 
22
22
  error JBSplits_PreviousLockedSplitsNotIncluded(uint256 projectId, uint256 rulesetId);
23
- error JBSplits_TotalPercentExceeds100();
24
- error JBSplits_ZeroSplitPercent();
23
+ error JBSplits_TotalPercentExceeds100(uint256 projectId, uint256 rulesetId, uint256 groupId, uint256 percentTotal);
24
+ error JBSplits_ZeroSplitPercent(uint256 projectId, uint256 rulesetId, uint256 groupId, uint256 splitIndex);
25
25
 
26
26
  //*********************************************************************//
27
27
  // ------------------------- public constants ------------------------ //
@@ -180,7 +180,7 @@ contract JBSplits is JBControlled, IJBSplits {
180
180
  block.timestamp < currentSplits[i].lockedUntil
181
181
  && !_includesLockedSplits({splits: splits, lockedSplit: currentSplits[i]})
182
182
  ) {
183
- revert JBSplits_PreviousLockedSplitsNotIncluded(projectId, rulesetId);
183
+ revert JBSplits_PreviousLockedSplitsNotIncluded({projectId: projectId, rulesetId: rulesetId});
184
184
  }
185
185
  unchecked {
186
186
  ++i;
@@ -198,13 +198,21 @@ contract JBSplits is JBControlled, IJBSplits {
198
198
  JBSplit memory split = splits[i];
199
199
 
200
200
  // The percent should be greater than 0.
201
- if (split.percent == 0) revert JBSplits_ZeroSplitPercent();
201
+ if (split.percent == 0) {
202
+ revert JBSplits_ZeroSplitPercent({
203
+ projectId: projectId, rulesetId: rulesetId, groupId: groupId, splitIndex: i
204
+ });
205
+ }
202
206
 
203
207
  // Add to the `percent` total.
204
208
  percentTotal += split.percent;
205
209
 
206
210
  // Ensure the total does not exceed 100%.
207
- if (percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) revert JBSplits_TotalPercentExceeds100();
211
+ if (percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) {
212
+ revert JBSplits_TotalPercentExceeds100({
213
+ projectId: projectId, rulesetId: rulesetId, groupId: groupId, percentTotal: percentTotal
214
+ });
215
+ }
208
216
 
209
217
  uint256 packedSplitParts1;
210
218