@bananapus/core-v6 0.0.42 → 0.0.44

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +3 -3
  3. package/package.json +2 -2
  4. package/references/entrypoints.md +3 -1
  5. package/references/types-errors-events.md +2 -3
  6. package/src/JBChainlinkV3PriceFeed.sol +14 -6
  7. package/src/JBChainlinkV3SequencerPriceFeed.sol +5 -6
  8. package/src/JBController.sol +84 -68
  9. package/src/JBDirectory.sol +4 -7
  10. package/src/JBERC20.sol +8 -7
  11. package/src/JBFeelessAddresses.sol +32 -13
  12. package/src/JBFundAccessLimits.sol +12 -4
  13. package/src/JBMultiTerminal.sol +39 -61
  14. package/src/JBPermissions.sol +6 -3
  15. package/src/JBPrices.sol +18 -12
  16. package/src/JBRulesets.sol +4 -25
  17. package/src/JBSplits.sol +13 -5
  18. package/src/JBTerminalStore.sol +46 -82
  19. package/src/JBTokens.sol +11 -13
  20. package/src/abstract/JBControlled.sol +1 -2
  21. package/src/interfaces/IJBController.sol +0 -6
  22. package/src/interfaces/IJBFeelessAddresses.sol +17 -7
  23. package/src/libraries/JBCashOuts.sol +6 -2
  24. package/src/libraries/JBCurrencyIds.sol +3 -0
  25. package/src/libraries/JBMetadataResolver.sol +20 -12
  26. package/src/libraries/JBPayoutSplitGroupLib.sol +8 -3
  27. package/src/libraries/JBRulesetMetadataResolver.sol +4 -4
  28. package/src/libraries/JBSplitGroupIds.sol +1 -0
  29. package/src/periphery/JBDeadline1Day.sol +1 -0
  30. package/src/periphery/JBDeadline3Days.sol +1 -0
  31. package/src/periphery/JBDeadline3Hours.sol +1 -0
  32. package/src/periphery/JBDeadline7Days.sol +1 -0
  33. package/src/structs/JBBeforeCashOutRecordedContext.sol +3 -2
  34. package/src/structs/JBRulesetMetadata.sol +3 -3
  35. package/test/helpers/JBTest.sol +3 -3
package/src/JBTokens.sol CHANGED
@@ -19,8 +19,8 @@ contract JBTokens is JBControlled, IJBTokens {
19
19
  // --------------------------- custom errors ------------------------- //
20
20
  //*********************************************************************//
21
21
 
22
- error JBTokens_EmptyName();
23
- error JBTokens_EmptySymbol();
22
+ error JBTokens_EmptyName(uint256 projectId);
23
+ error JBTokens_EmptySymbol(uint256 projectId);
24
24
  error JBTokens_EmptyToken(uint256 projectId);
25
25
  error JBTokens_InsufficientCredits(uint256 count, uint256 creditBalance);
26
26
  error JBTokens_InsufficientTokensToBurn(uint256 count, uint256 tokenBalance);
@@ -28,7 +28,7 @@ contract JBTokens is JBControlled, IJBTokens {
28
28
  error JBTokens_ProjectAlreadyHasToken(IJBToken token);
29
29
  error JBTokens_TokenAlreadyBeingUsed(uint256 projectId);
30
30
  error JBTokens_TokenCantBeAdded(uint256 projectId);
31
- error JBTokens_TokenNotFound();
31
+ error JBTokens_TokenNotFound(uint256 projectId);
32
32
  error JBTokens_TokensMustHave18Decimals(uint256 decimals);
33
33
 
34
34
  //*********************************************************************//
@@ -49,7 +49,6 @@ contract JBTokens is JBControlled, IJBTokens {
49
49
 
50
50
  /// @notice The project ID that a given ERC-20 token is associated with.
51
51
  /// @custom:param token The address of the token associated with the project.
52
- // slither-disable-next-line unused-return
53
52
  mapping(IJBToken token => uint256) public override projectIdOf;
54
53
 
55
54
  /// @notice Each project's attached token contract.
@@ -92,7 +91,7 @@ contract JBTokens is JBControlled, IJBTokens {
92
91
 
93
92
  // There must be enough tokens to burn across the holder's combined token and credit balance.
94
93
  if (count > tokenBalance + creditBalance) {
95
- revert JBTokens_InsufficientTokensToBurn(count, tokenBalance + creditBalance);
94
+ revert JBTokens_InsufficientTokensToBurn({count: count, tokenBalance: tokenBalance + creditBalance});
96
95
  }
97
96
 
98
97
  // The amount of tokens to burn.
@@ -153,7 +152,7 @@ contract JBTokens is JBControlled, IJBTokens {
153
152
  IJBToken token = tokenOf[projectId];
154
153
 
155
154
  // The project must have a token contract attached.
156
- if (token == IJBToken(address(0))) revert JBTokens_TokenNotFound();
155
+ if (token == IJBToken(address(0))) revert JBTokens_TokenNotFound({projectId: projectId});
157
156
 
158
157
  // Get a reference to the amount of credits the holder has.
159
158
  uint256 creditBalance = creditBalanceOf[holder][projectId];
@@ -204,10 +203,10 @@ contract JBTokens is JBControlled, IJBTokens {
204
203
  returns (IJBToken token)
205
204
  {
206
205
  // There must be a name.
207
- if (bytes(name).length == 0) revert JBTokens_EmptyName();
206
+ if (bytes(name).length == 0) revert JBTokens_EmptyName({projectId: projectId});
208
207
 
209
208
  // There must be a symbol.
210
- if (bytes(symbol).length == 0) revert JBTokens_EmptySymbol();
209
+ if (bytes(symbol).length == 0) revert JBTokens_EmptySymbol({projectId: projectId});
211
210
 
212
211
  // The project shouldn't already have a token.
213
212
  if (tokenOf[projectId] != IJBToken(address(0))) revert JBTokens_ProjectAlreadyHasToken(tokenOf[projectId]);
@@ -263,12 +262,11 @@ contract JBTokens is JBControlled, IJBTokens {
263
262
 
264
263
  // The total supply after minting can't exceed the maximum value storable in a uint208.
265
264
  if (supply + count > type(uint208).max) {
266
- revert JBTokens_OverflowAlert(supply + count, type(uint208).max);
265
+ revert JBTokens_OverflowAlert({value: supply + count, limit: type(uint208).max});
267
266
  }
268
267
 
269
268
  if (tokensWereClaimed) {
270
269
  // If tokens should be claimed, mint tokens into the holder's wallet.
271
- // slither-disable-next-line reentrancy-events
272
270
  token.mint({account: holder, amount: count});
273
271
  } else {
274
272
  // Otherwise, add the tokens to their credits and the credit supply.
@@ -333,13 +331,13 @@ contract JBTokens is JBControlled, IJBTokens {
333
331
  IJBToken token = tokenOf[projectId];
334
332
 
335
333
  // The project must have a token contract attached.
336
- if (token == IJBToken(address(0))) revert JBTokens_TokenNotFound();
334
+ if (token == IJBToken(address(0))) revert JBTokens_TokenNotFound({projectId: projectId});
337
335
 
338
336
  // There must be a name.
339
- if (bytes(name).length == 0) revert JBTokens_EmptyName();
337
+ if (bytes(name).length == 0) revert JBTokens_EmptyName({projectId: projectId});
340
338
 
341
339
  // There must be a symbol.
342
- if (bytes(symbol).length == 0) revert JBTokens_EmptySymbol();
340
+ if (bytes(symbol).length == 0) revert JBTokens_EmptySymbol({projectId: projectId});
343
341
 
344
342
  emit SetTokenMetadata({projectId: projectId, name: name, symbol: symbol, caller: msg.sender});
345
343
 
@@ -48,10 +48,9 @@ abstract contract JBControlled is IJBControlled {
48
48
  /// @notice Only allows the controller of the specified project to proceed.
49
49
  function _onlyControllerOf(uint256 projectId) internal view {
50
50
  // Cache the controller address to avoid a redundant external call on revert.
51
- // slither-disable-next-line calls-loop
52
51
  address controller = address(DIRECTORY.controllerOf(projectId));
53
52
  if (controller != msg.sender) {
54
- revert JBControlled_ControllerUnauthorized(controller);
53
+ revert JBControlled_ControllerUnauthorized({controller: controller});
55
54
  }
56
55
  }
57
56
  }
@@ -81,12 +81,6 @@ interface IJBController is IERC165, IJBProjectUriRegistry, IJBDirectoryAccessCon
81
81
  address caller
82
82
  );
83
83
 
84
- /// @notice A project was prepared for migration from another controller.
85
- /// @param projectId The ID of the project to prepare for migration.
86
- /// @param from The controller to migrate from.
87
- /// @param caller The address that called the prep migration function.
88
- event PrepMigration(uint256 indexed projectId, address from, address caller);
89
-
90
84
  /// @notice Rulesets were queued for a project.
91
85
  /// @param rulesetId The ID of the first queued ruleset.
92
86
  /// @param projectId The ID of the project.
@@ -1,21 +1,31 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.0;
3
3
 
4
- /// @notice Tracks addresses that are exempt from fees.
4
+ /// @notice Tracks addresses that are exempt from fees, both globally and on a per-project basis.
5
+ /// @dev `projectId = 0` is the wildcard — an address feeless for project 0 is feeless for ALL projects.
5
6
  interface IJBFeelessAddresses {
6
- /// @notice An address's feeless status was set.
7
+ /// @notice An address's feeless status was set for a project (or globally if projectId is 0).
8
+ /// @param projectId The project the feeless status applies to. 0 means all projects.
7
9
  /// @param addr The address whose feeless status was set.
8
10
  /// @param isFeeless Whether the address is feeless.
9
11
  /// @param caller The address that set the feeless status.
10
- event SetFeelessAddress(address indexed addr, bool indexed isFeeless, address caller);
12
+ event SetFeelessAddress(uint256 indexed projectId, address indexed addr, bool indexed isFeeless, address caller);
11
13
 
12
- /// @notice Returns whether the specified address is feeless.
14
+ /// @notice Returns whether the specified address is feeless for a specific project, considering both the wildcard
15
+ /// (projectId 0) and project-specific feeless status.
13
16
  /// @param addr The address to check.
14
- /// @return A flag indicating whether the address is feeless.
15
- function isFeeless(address addr) external view returns (bool);
17
+ /// @param projectId The ID of the project to check.
18
+ /// @return A flag indicating whether the address is feeless (globally or for the project).
19
+ function isFeelessFor(address addr, uint256 projectId) external view returns (bool);
16
20
 
17
- /// @notice Sets whether an address is feeless.
21
+ /// @notice Sets whether an address is feeless globally (for all projects).
18
22
  /// @param addr The address to set the feeless status of.
19
23
  /// @param flag A flag indicating whether the address should be feeless.
20
24
  function setFeelessAddress(address addr, bool flag) external;
25
+
26
+ /// @notice Sets whether an address is feeless for a specific project.
27
+ /// @param projectId The ID of the project. 0 means all projects (same as `setFeelessAddress`).
28
+ /// @param addr The address to set the feeless status of.
29
+ /// @param flag A flag indicating whether the address should be feeless for the project.
30
+ function setFeelessAddressFor(uint256 projectId, address addr, bool flag) external;
21
31
  }
@@ -13,7 +13,7 @@ import {JBConstants} from "./JBConstants.sol";
13
13
  /// reclaim amount.
14
14
  library JBCashOuts {
15
15
  /// @notice Thrown when the desired output cannot be achieved (e.g., cash out tax rate is 100%).
16
- error JBCashOuts_DesiredOutputNotAchievable();
16
+ error JBCashOuts_DesiredOutputNotAchievable(uint256 desiredOutput, uint256 cashOutTaxRate, uint256 maxTaxRate);
17
17
 
18
18
  /// @notice Returns the amount of surplus terminal tokens which can be reclaimed based on the total surplus, the
19
19
  /// number of tokens to cash out, the total token supply, and the ruleset's cash out tax rate.
@@ -81,7 +81,11 @@ library JBCashOuts {
81
81
 
82
82
  // If the cash out tax rate is at maximum, no output is achievable.
83
83
  if (cashOutTaxRate == JBConstants.MAX_CASH_OUT_TAX_RATE) {
84
- revert JBCashOuts_DesiredOutputNotAchievable();
84
+ revert JBCashOuts_DesiredOutputNotAchievable({
85
+ desiredOutput: desiredOutput,
86
+ cashOutTaxRate: cashOutTaxRate,
87
+ maxTaxRate: JBConstants.MAX_CASH_OUT_TAX_RATE
88
+ });
85
89
  }
86
90
 
87
91
  // If the desired output meets or exceeds the surplus, the entire supply must be cashed out.
@@ -4,6 +4,9 @@ pragma solidity 0.8.28;
4
4
  /// @notice Well-known currency IDs used as the `baseCurrency` in ruleset metadata. These are distinct from accounting
5
5
  /// context currencies (which use `uint32(uint160(tokenAddress))`). Only used for price feed lookups in `JBPrices`.
6
6
  library JBCurrencyIds {
7
+ /// @notice The currency ID used for ETH-denominated price feeds.
7
8
  uint32 public constant ETH = 1;
9
+
10
+ /// @notice The currency ID used for USD-denominated price feeds.
8
11
  uint32 public constant USD = 2;
9
12
  }
@@ -25,10 +25,10 @@ pragma solidity 0.8.28;
25
25
  * +-----------------------+
26
26
  */
27
27
  library JBMetadataResolver {
28
- error JBMetadataResolver_DataNotPadded();
29
- error JBMetadataResolver_LengthMismatch();
30
- error JBMetadataResolver_MetadataTooLong();
31
- error JBMetadataResolver_MetadataTooShort();
28
+ error JBMetadataResolver_DataNotPadded(uint256 dataLength);
29
+ error JBMetadataResolver_LengthMismatch(uint256 idsLength, uint256 datasLength);
30
+ error JBMetadataResolver_MetadataTooLong(uint256 offset, uint256 maxOffset);
31
+ error JBMetadataResolver_MetadataTooShort(uint256 metadataLength, uint256 minMetadataLength);
32
32
 
33
33
  // The various sizes used in bytes.
34
34
  uint256 constant ID_SIZE = 4;
@@ -61,7 +61,7 @@ library JBMetadataResolver {
61
61
  returns (bytes memory newMetadata)
62
62
  {
63
63
  // Validate data padding upfront so that the fast path below cannot bypass the check.
64
- if (dataToAdd.length < 32) revert JBMetadataResolver_DataNotPadded();
64
+ if (dataToAdd.length < 32) revert JBMetadataResolver_DataNotPadded({dataLength: dataToAdd.length});
65
65
 
66
66
  // Empty original metadata and maybe something in the first 32 bytes: create new metadata
67
67
  if (originalMetadata.length <= RESERVED_SIZE) {
@@ -70,7 +70,11 @@ library JBMetadataResolver {
70
70
  }
71
71
 
72
72
  // There is something in the table offset, but not a valid entry - avoid overwriting
73
- if (originalMetadata.length < RESERVED_SIZE + ID_SIZE + 1) revert JBMetadataResolver_MetadataTooShort();
73
+ if (originalMetadata.length < RESERVED_SIZE + ID_SIZE + 1) {
74
+ revert JBMetadataResolver_MetadataTooShort({
75
+ metadataLength: originalMetadata.length, minMetadataLength: RESERVED_SIZE + ID_SIZE + 1
76
+ });
77
+ }
74
78
 
75
79
  // Get the first data offset - upcast to avoid overflow (same for other offset)...
76
80
  uint256 firstOffset = uint8(originalMetadata[RESERVED_SIZE + ID_SIZE]);
@@ -104,7 +108,9 @@ library JBMetadataResolver {
104
108
  // Increment every offset by 1 (as the table now takes one more word)
105
109
  for (uint256 j = RESERVED_SIZE + ID_SIZE; j < lastOffsetIndex + 1; j += TOTAL_ID_SIZE) {
106
110
  uint256 incremented = uint256(uint8(originalMetadata[j])) + 1;
107
- if (incremented > 255) revert JBMetadataResolver_MetadataTooLong();
111
+ if (incremented > 255) {
112
+ revert JBMetadataResolver_MetadataTooLong({offset: incremented, maxOffset: 255});
113
+ }
108
114
  // forge-lint: disable-next-line(unsafe-typecast)
109
115
  newMetadata[j] = bytes1(uint8(incremented));
110
116
  }
@@ -121,7 +127,7 @@ library JBMetadataResolver {
121
127
  // taken by the last data
122
128
  // Compute in uint256 first — casting directly to uint8 silently wraps offsets > 255.
123
129
  uint256 newOffset = lastOffset + numberOfWordslastData;
124
- if (newOffset > 255) revert JBMetadataResolver_MetadataTooLong();
130
+ if (newOffset > 255) revert JBMetadataResolver_MetadataTooLong({offset: newOffset, maxOffset: 255});
125
131
  // forge-lint: disable-next-line(unsafe-typecast)
126
132
  newMetadata = abi.encodePacked(newMetadata, idToAdd, bytes1(uint8(newOffset)));
127
133
 
@@ -167,7 +173,9 @@ library JBMetadataResolver {
167
173
  /// @param datas The list of corresponding datas
168
174
  /// @return metadata The resulting metadata
169
175
  function createMetadata(bytes4[] memory ids, bytes[] memory datas) internal pure returns (bytes memory metadata) {
170
- if (ids.length != datas.length) revert JBMetadataResolver_LengthMismatch();
176
+ if (ids.length != datas.length) {
177
+ revert JBMetadataResolver_LengthMismatch({idsLength: ids.length, datasLength: datas.length});
178
+ }
171
179
 
172
180
  // Return empty bytes for empty input arrays to avoid underflow in offset calculation below.
173
181
  if (ids.length == 0) return bytes("");
@@ -191,7 +199,7 @@ library JBMetadataResolver {
191
199
  bytes memory data = datas[i];
192
200
 
193
201
  if (data.length < 32 || data.length % JBMetadataResolver.WORD_SIZE != 0) {
194
- revert JBMetadataResolver_DataNotPadded();
202
+ revert JBMetadataResolver_DataNotPadded({dataLength: data.length});
195
203
  }
196
204
 
197
205
  // forge-lint: disable-next-line(unsafe-typecast)
@@ -199,7 +207,7 @@ library JBMetadataResolver {
199
207
  offset += data.length / JBMetadataResolver.WORD_SIZE;
200
208
 
201
209
  // Overflowing a bytes1?
202
- if (offset > 255) revert JBMetadataResolver_MetadataTooLong();
210
+ if (offset > 255) revert JBMetadataResolver_MetadataTooLong({offset: offset, maxOffset: 255});
203
211
  }
204
212
 
205
213
  // Pad the table to a multiple of 32B
@@ -277,7 +285,7 @@ library JBMetadataResolver {
277
285
  /// @param purpose A string describing the purpose associated with the id
278
286
  /// @return id The resulting ID.
279
287
  function getId(string memory purpose) internal view returns (bytes4) {
280
- return getId(purpose, address(this));
288
+ return getId({purpose: purpose, target: address(this)});
281
289
  }
282
290
 
283
291
  /// @notice Returns an unique id following a suggested format (`xor(address(this), purpose name)` where purpose name
@@ -12,6 +12,13 @@ import {JBConstants} from "./JBConstants.sol";
12
12
  /// @dev Kept local to this file because `executePayout(...)` is an implementation detail, not a shared public
13
13
  /// interface.
14
14
  interface IJBPayoutSplitGroupExecutor {
15
+ /// @notice Executes one payout split from the terminal that is using this library.
16
+ /// @param split The split to pay.
17
+ /// @param projectId The ID of the project paying the split.
18
+ /// @param token The token being paid out.
19
+ /// @param amount The amount assigned to the split.
20
+ /// @param originalMessageSender The account that started the payout flow.
21
+ /// @return netPayoutAmount The amount that was actually paid after fees or hook behavior.
15
22
  function executePayout(
16
23
  JBSplit calldata split,
17
24
  uint256 projectId,
@@ -30,6 +37,7 @@ interface IJBPayoutSplitGroupExecutor {
30
37
  /// are emitted from the terminal's address.
31
38
  library JBPayoutSplitGroupLib {
32
39
  event PayoutReverted(uint256 indexed projectId, JBSplit split, uint256 amount, bytes reason, address caller);
40
+
33
41
  event SendPayoutToSplit(
34
42
  uint256 indexed projectId,
35
43
  uint256 indexed rulesetId,
@@ -80,7 +88,6 @@ library JBPayoutSplitGroupLib {
80
88
  uint256 payoutAmount = mulDiv(leftoverAmount, split.percent, leftoverPercentage);
81
89
 
82
90
  // The final payout amount after taking out any fees.
83
- // slither-disable-next-line calls-loop
84
91
  uint256 netPayoutAmount = _sendPayoutToSplit({
85
92
  store: store, split: split, projectId: projectId, token: token, amount: payoutAmount, caller: caller
86
93
  });
@@ -140,7 +147,6 @@ library JBPayoutSplitGroupLib {
140
147
  // split from DoS-ing the entire payout. Failed splits' amounts are returned to the project balance via
141
148
  // `recordAddedBalanceFor`. Payout limit consumption is correct because the project authorized the
142
149
  // distribution.
143
- // slither-disable-next-line reentrancy-events,calls-loop
144
150
  try IJBPayoutSplitGroupExecutor(address(this))
145
151
  .executePayout({
146
152
  split: split, projectId: projectId, token: token, amount: amount, originalMessageSender: caller
@@ -154,7 +160,6 @@ library JBPayoutSplitGroupLib {
154
160
  });
155
161
 
156
162
  // Add balance back to the project.
157
- // slither-disable-next-line calls-loop
158
163
  store.recordAddedBalanceFor({projectId: projectId, token: token, amount: amount});
159
164
 
160
165
  // Since the payout failed the netPayoutAmount is zero.
@@ -67,7 +67,7 @@ library JBRulesetMetadataResolver {
67
67
  return ((ruleset.metadata >> 78) & 1) == 1;
68
68
  }
69
69
 
70
- function useTotalSurplusForCashOuts(JBRuleset memory ruleset) internal pure returns (bool) {
70
+ function scopeCashOutsToLocalBalances(JBRuleset memory ruleset) internal pure returns (bool) {
71
71
  return ((ruleset.metadata >> 79) & 1) == 1;
72
72
  }
73
73
 
@@ -123,8 +123,8 @@ library JBRulesetMetadataResolver {
123
123
  if (rulesetMetadata.ownerMustSendPayouts) packed |= 1 << 77;
124
124
  // hold fees in bit 78.
125
125
  if (rulesetMetadata.holdFees) packed |= 1 << 78;
126
- // useTotalSurplusForCashOuts in bit 79.
127
- if (rulesetMetadata.useTotalSurplusForCashOuts) packed |= 1 << 79;
126
+ // scopeCashOutsToLocalBalances in bit 79.
127
+ if (rulesetMetadata.scopeCashOutsToLocalBalances) packed |= 1 << 79;
128
128
  // use pay data source in bit 80.
129
129
  if (rulesetMetadata.useDataHookForPay) packed |= 1 << 80;
130
130
  // use cash out data source in bit 81.
@@ -154,7 +154,7 @@ library JBRulesetMetadataResolver {
154
154
  allowAddPriceFeed: allowAddPriceFeed(ruleset),
155
155
  ownerMustSendPayouts: ownerMustSendPayouts(ruleset),
156
156
  holdFees: holdFees(ruleset),
157
- useTotalSurplusForCashOuts: useTotalSurplusForCashOuts(ruleset),
157
+ scopeCashOutsToLocalBalances: scopeCashOutsToLocalBalances(ruleset),
158
158
  useDataHookForPay: useDataHookForPay(ruleset),
159
159
  useDataHookForCashOut: useDataHookForCashOut(ruleset),
160
160
  dataHook: dataHook(ruleset),
@@ -4,5 +4,6 @@ pragma solidity 0.8.28;
4
4
  /// @notice Well-known split group IDs. The reserved tokens group (ID 1) defines how a project's reserved tokens are
5
5
  /// distributed. Payout split groups use the token address cast to `uint256(uint160(token))` as their group ID.
6
6
  library JBSplitGroupIds {
7
+ /// @notice The split group ID used for reserved token distributions.
7
8
  uint256 public constant RESERVED_TOKENS = 1;
8
9
  }
@@ -3,6 +3,7 @@ pragma solidity 0.8.28;
3
3
 
4
4
  import {JBDeadline} from "../JBDeadline.sol";
5
5
 
6
+ /// @notice A reusable deadline implementation with a fixed one-day duration.
6
7
  contract JBDeadline1Day is JBDeadline {
7
8
  constructor() JBDeadline(1 days) {}
8
9
  }
@@ -3,6 +3,7 @@ pragma solidity 0.8.28;
3
3
 
4
4
  import {JBDeadline} from "../JBDeadline.sol";
5
5
 
6
+ /// @notice A reusable deadline implementation with a fixed three-day duration.
6
7
  contract JBDeadline3Days is JBDeadline {
7
8
  constructor() JBDeadline(3 days) {}
8
9
  }
@@ -3,6 +3,7 @@ pragma solidity 0.8.28;
3
3
 
4
4
  import {JBDeadline} from "../JBDeadline.sol";
5
5
 
6
+ /// @notice A reusable deadline implementation with a fixed three-hour duration.
6
7
  contract JBDeadline3Hours is JBDeadline {
7
8
  constructor() JBDeadline(3 hours) {}
8
9
  }
@@ -3,6 +3,7 @@ pragma solidity 0.8.28;
3
3
 
4
4
  import {JBDeadline} from "../JBDeadline.sol";
5
5
 
6
+ /// @notice A reusable deadline implementation with a fixed seven-day duration.
6
7
  contract JBDeadline7Days is JBDeadline {
7
8
  constructor() JBDeadline(7 days) {}
8
9
  }
@@ -14,7 +14,8 @@ import {JBTokenAmount} from "./JBTokenAmount.sol";
14
14
  /// @custom:member surplus The surplus amount used for the calculation, as a fixed point number with 18 decimals.
15
15
  /// Includes the token of the surplus, the surplus value, the number of decimals
16
16
  /// included, and the currency of the surplus.
17
- /// @custom:member useTotalSurplus If true, use surplus across all of a project's terminals when calculating cash outs.
17
+ /// @custom:member scopeCashOutsToLocalBalances If true, omnichain hooks should use only local chain balances for cash
18
+ /// outs (skip cross-chain aggregation).
18
19
  /// @custom:member cashOutTaxRate The cash out tax rate of the ruleset the cash out is made during, out of
19
20
  /// `JBConstants.MAX_CASH_OUT_TAX_RATE`.
20
21
  /// @custom:member beneficiaryIsFeeless Whether the cash out's beneficiary is a feeless address. Useful for data hooks
@@ -29,7 +30,7 @@ struct JBBeforeCashOutRecordedContext {
29
30
  uint256 cashOutCount;
30
31
  uint256 totalSupply;
31
32
  JBTokenAmount surplus;
32
- bool useTotalSurplus;
33
+ bool scopeCashOutsToLocalBalances;
33
34
  uint256 cashOutTaxRate;
34
35
  bool beneficiaryIsFeeless;
35
36
  bytes metadata;
@@ -21,8 +21,8 @@ pragma solidity ^0.8.0;
21
21
  /// @custom:member allowAddPriceFeed If `true`, the project can register new price feeds in `JBPrices`.
22
22
  /// @custom:member ownerMustSendPayouts If `true`, only the project owner can trigger payout distribution.
23
23
  /// @custom:member holdFees If `true`, fees are accumulated but not processed until a future ruleset (or manually).
24
- /// @custom:member useTotalSurplusForCashOuts If `true`, cash-out calculations use surplus across all terminals (not
25
- /// just the one to cash out from).
24
+ /// @custom:member scopeCashOutsToLocalBalances If `true`, omnichain cash-out calculations use only the local chain's
25
+ /// balances (not cross-chain aggregates).
26
26
  /// @custom:member useDataHookForPay If `true`, the data hook is called before recording payments.
27
27
  /// @custom:member useDataHookForCashOut If `true`, the data hook is called before recording cash outs.
28
28
  /// @custom:member dataHook Contract called before pay/cash-out to potentially override token counts or add hooks.
@@ -42,7 +42,7 @@ struct JBRulesetMetadata {
42
42
  bool allowAddPriceFeed;
43
43
  bool ownerMustSendPayouts;
44
44
  bool holdFees;
45
- bool useTotalSurplusForCashOuts;
45
+ bool scopeCashOutsToLocalBalances;
46
46
  bool useDataHookForPay;
47
47
  bool useDataHookForCashOut;
48
48
  address dataHook;
@@ -43,7 +43,7 @@ contract JBTest is Test {
43
43
  allowAddAccountingContext: true,
44
44
  allowAddPriceFeed: true,
45
45
  holdFees: false,
46
- useTotalSurplusForCashOuts: true,
46
+ scopeCashOutsToLocalBalances: true,
47
47
  useDataHookForPay: false,
48
48
  useDataHookForCashOut: false,
49
49
  dataHook: address(0),
@@ -81,7 +81,7 @@ contract JBTest is Test {
81
81
  allowAddAccountingContext: true,
82
82
  allowAddPriceFeed: false,
83
83
  holdFees: false,
84
- useTotalSurplusForCashOuts: false,
84
+ scopeCashOutsToLocalBalances: false,
85
85
  useDataHookForPay: false,
86
86
  useDataHookForCashOut: false,
87
87
  dataHook: address(0),
@@ -105,7 +105,7 @@ contract JBTest is Test {
105
105
  allowAddAccountingContext: false,
106
106
  allowAddPriceFeed: false,
107
107
  holdFees: true,
108
- useTotalSurplusForCashOuts: true,
108
+ scopeCashOutsToLocalBalances: true,
109
109
  useDataHookForPay: false,
110
110
  useDataHookForCashOut: false,
111
111
  dataHook: address(0),