@bananapus/core-v6 0.0.9 → 0.0.10

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 (39) hide show
  1. package/foundry.toml +0 -1
  2. package/package.json +2 -2
  3. package/src/JBChainlinkV3PriceFeed.sol +1 -5
  4. package/src/JBChainlinkV3SequencerPriceFeed.sol +1 -1
  5. package/src/JBController.sol +277 -277
  6. package/src/JBDeadline.sol +1 -1
  7. package/src/JBDirectory.sol +93 -93
  8. package/src/JBERC20.sol +43 -39
  9. package/src/JBFeelessAddresses.sol +12 -12
  10. package/src/JBFundAccessLimits.sol +82 -82
  11. package/src/JBMultiTerminal.sol +313 -313
  12. package/src/JBPermissions.sol +104 -100
  13. package/src/JBPrices.sol +68 -68
  14. package/src/JBProjects.sol +31 -31
  15. package/src/JBRulesets.sol +422 -422
  16. package/src/JBSplits.sol +116 -116
  17. package/src/JBTerminalStore.sol +651 -651
  18. package/src/JBTokens.sol +41 -41
  19. package/src/interfaces/IJBCashOutTerminal.sol +25 -7
  20. package/src/interfaces/IJBController.sol +78 -3
  21. package/src/interfaces/IJBDirectory.sol +25 -0
  22. package/src/interfaces/IJBFeeTerminal.sol +31 -0
  23. package/src/interfaces/IJBFeelessAddresses.sol +4 -0
  24. package/src/interfaces/IJBFundAccessLimits.sol +5 -0
  25. package/src/interfaces/IJBMigratable.sol +12 -8
  26. package/src/interfaces/IJBPayoutTerminal.sol +56 -9
  27. package/src/interfaces/IJBPermissions.sol +14 -7
  28. package/src/interfaces/IJBPermitTerminal.sol +4 -0
  29. package/src/interfaces/IJBPrices.sol +6 -0
  30. package/src/interfaces/IJBProjects.sol +8 -0
  31. package/src/interfaces/IJBRulesetApprovalHook.sol +1 -1
  32. package/src/interfaces/IJBRulesetDataHook.sol +23 -23
  33. package/src/interfaces/IJBRulesets.sol +54 -33
  34. package/src/interfaces/IJBSplits.sol +6 -0
  35. package/src/interfaces/IJBTerminal.sol +36 -0
  36. package/src/interfaces/IJBTerminalStore.sol +63 -63
  37. package/src/interfaces/IJBToken.sol +5 -5
  38. package/src/interfaces/IJBTokens.sol +50 -8
  39. package/test/TestDurationUnderflow.sol +3 -2
package/foundry.toml CHANGED
@@ -4,7 +4,6 @@ evm_version = 'paris'
4
4
  optimizer_runs = 200
5
5
  libs = ["node_modules", "lib"]
6
6
  fs_permissions = [{ access = "read-write", path = "./"}]
7
- match_contract = "_Local"
8
7
 
9
8
  [profile.ci_sizes]
10
9
  optimizer_runs = 200
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/core-v6",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,7 +26,7 @@
26
26
  "artifacts": "source ./.env && npx sphinx artifacts --org-id 'ea165b21-7cdc-4d7b-be59-ecdd4c26bee4' --project-name 'nana-core-v6'"
27
27
  },
28
28
  "dependencies": {
29
- "@bananapus/permission-ids-v6": "^0.0.4",
29
+ "@bananapus/permission-ids-v6": "^0.0.5",
30
30
  "@chainlink/contracts": "^1.3.0",
31
31
  "@openzeppelin/contracts": "^5.2.0",
32
32
  "@prb/math": "^4.1.0",
@@ -20,16 +20,12 @@ contract JBChainlinkV3PriceFeed is IJBPriceFeed {
20
20
  error JBChainlinkV3PriceFeed_StalePrice(uint256 timestamp, uint256 threshold, uint256 updatedAt);
21
21
 
22
22
  //*********************************************************************//
23
- // ---------------- public stored immutable properties --------------- //
23
+ // --------------- public immutable stored properties ---------------- //
24
24
  //*********************************************************************//
25
25
 
26
26
  /// @notice The Chainlink feed that prices are reported from.
27
27
  AggregatorV3Interface public immutable FEED;
28
28
 
29
- //*********************************************************************//
30
- // ---------------- public immutable stored properties --------------- //
31
- //*********************************************************************//
32
-
33
29
  /// @notice How many seconds old a Chainlink price update is allowed to be before considered "stale".
34
30
  uint256 public immutable THRESHOLD;
35
31
 
@@ -19,7 +19,7 @@ contract JBChainlinkV3SequencerPriceFeed is JBChainlinkV3PriceFeed {
19
19
  );
20
20
 
21
21
  //*********************************************************************//
22
- // ---------------- public stored immutable properties --------------- //
22
+ // --------------- public immutable stored properties ---------------- //
23
23
  //*********************************************************************//
24
24
 
25
25
  /// @notice How long the sequencer must be re-active in order to return a price.
@@ -150,210 +150,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
150
150
  }
151
151
 
152
152
  //*********************************************************************//
153
- // ------------------------- external views -------------------------- //
154
- //*********************************************************************//
155
-
156
- /// @notice Get an array of a project's rulesets (with metadata) up to a maximum array size, sorted from latest to
157
- /// earliest.
158
- /// @param projectId The ID of the project to get the rulesets of.
159
- /// @param startingId The ID of the ruleset to begin with. This will be the latest ruleset in the result. If the
160
- /// `startingId` is 0, passed, the project's latest ruleset will be used.
161
- /// @param size The maximum number of rulesets to return.
162
- /// @return rulesets The array of rulesets with their metadata.
163
- function allRulesetsOf(
164
- uint256 projectId,
165
- uint256 startingId,
166
- uint256 size
167
- )
168
- external
169
- view
170
- override
171
- returns (JBRulesetWithMetadata[] memory rulesets)
172
- {
173
- // Get the rulesets (without metadata).
174
- JBRuleset[] memory baseRulesets = RULESETS.allOf({projectId: projectId, startingId: startingId, size: size});
175
-
176
- // Keep a reference to the number of rulesets.
177
- uint256 numberOfRulesets = baseRulesets.length;
178
-
179
- // Initialize the array being returned.
180
- rulesets = new JBRulesetWithMetadata[](numberOfRulesets);
181
-
182
- // Populate the array with rulesets AND their metadata.
183
- for (uint256 i; i < numberOfRulesets; i++) {
184
- // Set the ruleset being iterated on.
185
- JBRuleset memory baseRuleset = baseRulesets[i];
186
-
187
- // Set the returned value.
188
- rulesets[i] = JBRulesetWithMetadata({ruleset: baseRuleset, metadata: baseRuleset.expandMetadata()});
189
- }
190
- }
191
-
192
- /// @notice A project's currently active ruleset and its metadata.
193
- /// @param projectId The ID of the project to get the current ruleset of.
194
- /// @return ruleset The current ruleset's struct.
195
- /// @return metadata The current ruleset's metadata.
196
- function currentRulesetOf(uint256 projectId)
197
- external
198
- view
199
- override
200
- returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata)
201
- {
202
- ruleset = _currentRulesetOf(projectId);
203
- metadata = ruleset.expandMetadata();
204
- }
205
-
206
- /// @notice Get the `JBRuleset` and `JBRulesetMetadata` corresponding to the specified `rulesetId`.
207
- /// @param projectId The ID of the project the ruleset belongs to.
208
- /// @return ruleset The ruleset's struct.
209
- /// @return metadata The ruleset's metadata.
210
- function getRulesetOf(
211
- uint256 projectId,
212
- uint256 rulesetId
213
- )
214
- external
215
- view
216
- override
217
- returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata)
218
- {
219
- ruleset = RULESETS.getRulesetOf({projectId: projectId, rulesetId: rulesetId});
220
- metadata = ruleset.expandMetadata();
221
- }
222
-
223
- /// @notice Gets the latest ruleset queued for a project, its approval status, and its metadata.
224
- /// @dev The 'latest queued ruleset' is the ruleset initialized furthest in the future (at the end of the ruleset
225
- /// queue).
226
- /// @param projectId The ID of the project to get the latest ruleset of.
227
- /// @return ruleset The struct for the project's latest queued ruleset.
228
- /// @return metadata The ruleset's metadata.
229
- /// @return approvalStatus The ruleset's approval status.
230
- function latestQueuedRulesetOf(uint256 projectId)
231
- external
232
- view
233
- override
234
- returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata, JBApprovalStatus approvalStatus)
235
- {
236
- (ruleset, approvalStatus) = RULESETS.latestQueuedOf(projectId);
237
- metadata = ruleset.expandMetadata();
238
- }
239
-
240
- /// @notice Check whether the project's terminals can currently be set.
241
- /// @param projectId The ID of the project to check.
242
- /// @return A `bool` which is true if the project allows terminals to be set.
243
- function setTerminalsAllowed(uint256 projectId) external view returns (bool) {
244
- return _currentRulesetOf(projectId).expandMetadata().allowSetTerminals;
245
- }
246
-
247
- /// @notice Check whether the project's controller can currently be set.
248
- /// @param projectId The ID of the project to check.
249
- /// @return A `bool` which is true if the project allows controllers to be set.
250
- function setControllerAllowed(uint256 projectId) external view returns (bool) {
251
- return _currentRulesetOf(projectId).expandMetadata().allowSetController;
252
- }
253
-
254
- /// @notice Gets the a project token's total supply, including pending reserved tokens.
255
- /// @param projectId The ID of the project to get the total token supply of.
256
- /// @return The total supply of the project's token, including pending reserved tokens.
257
- function totalTokenSupplyWithReservedTokensOf(uint256 projectId) external view override returns (uint256) {
258
- // Add the reserved tokens to the total supply.
259
- return TOKENS.totalSupplyOf(projectId) + pendingReservedTokenBalanceOf[projectId];
260
- }
261
-
262
- /// @notice A project's next ruleset along with its metadata.
263
- /// @dev If an upcoming ruleset isn't found, returns an empty ruleset with all properties set to 0.
264
- /// @param projectId The ID of the project to get the next ruleset of.
265
- /// @return ruleset The upcoming ruleset's struct.
266
- /// @return metadata The upcoming ruleset's metadata.
267
- function upcomingRulesetOf(uint256 projectId)
268
- external
269
- view
270
- override
271
- returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata)
272
- {
273
- ruleset = _upcomingRulesetOf(projectId);
274
- metadata = ruleset.expandMetadata();
275
- }
276
-
277
- //*********************************************************************//
278
- // -------------------------- public views --------------------------- //
279
- //*********************************************************************//
280
-
281
- /// @notice Indicates whether this contract adheres to the specified interface.
282
- /// @dev See {IERC165-supportsInterface}.
283
- /// @param interfaceId The ID of the interface to check for adherence to.
284
- /// @return A flag indicating if the provided interface ID is supported.
285
- function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
286
- return interfaceId == type(IJBController).interfaceId || interfaceId == type(IJBProjectUriRegistry).interfaceId
287
- || interfaceId == type(IJBDirectoryAccessControl).interfaceId
288
- || interfaceId == type(IJBMigratable).interfaceId || interfaceId == type(IJBPermissioned).interfaceId
289
- || interfaceId == type(IERC165).interfaceId;
290
- }
291
-
292
- //*********************************************************************//
293
- // -------------------------- internal views ------------------------- //
294
- //*********************************************************************//
295
-
296
- /// @dev `ERC-2771` specifies the context as being a single address (20 bytes).
297
- function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
298
- return super._contextSuffixLength();
299
- }
300
-
301
- /// @notice The project's current ruleset.
302
- /// @param projectId The ID of the project to check.
303
- /// @return The project's current ruleset.
304
- function _currentRulesetOf(uint256 projectId) internal view returns (JBRuleset memory) {
305
- return RULESETS.currentOf(projectId);
306
- }
307
-
308
- /// @notice Indicates whether the provided address is a terminal for the project.
309
- /// @param projectId The ID of the project to check.
310
- /// @param terminal The address to check.
311
- /// @return A flag indicating if the provided address is a terminal for the project.
312
- function _isTerminalOf(uint256 projectId, address terminal) internal view returns (bool) {
313
- return DIRECTORY.isTerminalOf({projectId: projectId, terminal: IJBTerminal(terminal)});
314
- }
315
-
316
- /// @notice Indicates whether the provided address has mint permission for the project byway of the data hook.
317
- /// @param projectId The ID of the project to check.
318
- /// @param ruleset The ruleset to check.
319
- /// @param addr The address to check.
320
- /// @return A flag indicating if the provided address has mint permission for the project.
321
- function _hasDataHookMintPermissionFor(
322
- uint256 projectId,
323
- JBRuleset memory ruleset,
324
- address addr
325
- )
326
- internal
327
- view
328
- returns (bool)
329
- {
330
- address dataHook = ruleset.dataHook();
331
-
332
- return dataHook != address(0)
333
- && IJBRulesetDataHook(dataHook).hasMintPermissionFor({projectId: projectId, ruleset: ruleset, addr: addr});
334
- }
335
-
336
- /// @notice The calldata. Preferred to use over `msg.data`.
337
- /// @return calldata The `msg.data` of this call.
338
- function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
339
- return ERC2771Context._msgData();
340
- }
341
-
342
- /// @notice The message's sender. Preferred to use over `msg.sender`.
343
- /// @return sender The address which sent this call.
344
- function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
345
- return ERC2771Context._msgSender();
346
- }
347
-
348
- /// @notice The project's upcoming ruleset.
349
- /// @param projectId The ID of the project to check.
350
- /// @return The project's upcoming ruleset.
351
- function _upcomingRulesetOf(uint256 projectId) internal view returns (JBRuleset memory) {
352
- return RULESETS.upcomingOf(projectId);
353
- }
354
-
355
- //*********************************************************************//
356
- // --------------------- external transactions ----------------------- //
153
+ // ---------------------- external transactions ---------------------- //
357
154
  //*********************************************************************//
358
155
 
359
156
  /// @notice Add a price feed for a project.
@@ -386,6 +183,18 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
386
183
  });
387
184
  }
388
185
 
186
+ /// @notice Called after this controller has been set as the project's controller in the directory.
187
+ /// @dev Can only be called by the directory.
188
+ /// @param from The controller being migrated from.
189
+ /// @param projectId The ID of the project that migrated to this controller.
190
+ function afterReceiveMigrationFrom(IERC165 from, uint256 projectId) external override {
191
+ from; // Suppress unused variable warning.
192
+ projectId; // Suppress unused variable warning.
193
+
194
+ // Make sure the sender is the directory.
195
+ if (_msgSender() != address(DIRECTORY)) revert JBController_OnlyDirectory(_msgSender(), DIRECTORY);
196
+ }
197
+
389
198
  /// @notice Prepares this controller to receive a project being migrated from another controller.
390
199
  /// @dev This controller should not be the project's controller yet.
391
200
  /// @param from The controller being migrated from.
@@ -412,18 +221,6 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
412
221
  }
413
222
  }
414
223
 
415
- /// @notice Called after this controller has been set as the project's controller in the directory.
416
- /// @dev Can only be called by the directory.
417
- /// @param from The controller being migrated from.
418
- /// @param projectId The ID of the project that migrated to this controller.
419
- function afterReceiveMigrationFrom(IERC165 from, uint256 projectId) external override {
420
- from; // Suppress unused variable warning.
421
- projectId; // Suppress unused variable warning.
422
-
423
- // Make sure the sender is the directory.
424
- if (_msgSender() != address(DIRECTORY)) revert JBController_OnlyDirectory(_msgSender(), DIRECTORY);
425
- }
426
-
427
224
  /// @notice Burns a project's tokens or credits from the specific holder's balance.
428
225
  /// @dev Can only be called by the holder, an address with the holder's permission to `BURN_TOKENS`, or a project's
429
226
  /// terminal.
@@ -895,19 +692,159 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
895
692
  }
896
693
 
897
694
  //*********************************************************************//
898
- // ------------------------ internal functions ----------------------- //
695
+ // ------------------------- external views -------------------------- //
899
696
  //*********************************************************************//
900
697
 
901
- /// @notice Set up a project's terminals.
902
- /// @param projectId The ID of the project to set up terminals for.
903
- /// @param terminalConfigurations The terminals to set up.
904
- function _configureTerminals(uint256 projectId, JBTerminalConfig[] calldata terminalConfigurations) internal {
905
- // Initialize an array of terminals to populate.
906
- IJBTerminal[] memory terminals = new IJBTerminal[](terminalConfigurations.length);
698
+ /// @notice Get an array of a project's rulesets (with metadata) up to a maximum array size, sorted from latest to
699
+ /// earliest.
700
+ /// @param projectId The ID of the project to get the rulesets of.
701
+ /// @param startingId The ID of the ruleset to begin with. This will be the latest ruleset in the result. If the
702
+ /// `startingId` is 0, passed, the project's latest ruleset will be used.
703
+ /// @param size The maximum number of rulesets to return.
704
+ /// @return rulesets The array of rulesets with their metadata.
705
+ function allRulesetsOf(
706
+ uint256 projectId,
707
+ uint256 startingId,
708
+ uint256 size
709
+ )
710
+ external
711
+ view
712
+ override
713
+ returns (JBRulesetWithMetadata[] memory rulesets)
714
+ {
715
+ // Get the rulesets (without metadata).
716
+ JBRuleset[] memory baseRulesets = RULESETS.allOf({projectId: projectId, startingId: startingId, size: size});
907
717
 
908
- for (uint256 i; i < terminalConfigurations.length; i++) {
909
- // Set the terminal configuration being iterated on.
910
- JBTerminalConfig memory terminalConfig = terminalConfigurations[i];
718
+ // Keep a reference to the number of rulesets.
719
+ uint256 numberOfRulesets = baseRulesets.length;
720
+
721
+ // Initialize the array being returned.
722
+ rulesets = new JBRulesetWithMetadata[](numberOfRulesets);
723
+
724
+ // Populate the array with rulesets AND their metadata.
725
+ for (uint256 i; i < numberOfRulesets; i++) {
726
+ // Set the ruleset being iterated on.
727
+ JBRuleset memory baseRuleset = baseRulesets[i];
728
+
729
+ // Set the returned value.
730
+ rulesets[i] = JBRulesetWithMetadata({ruleset: baseRuleset, metadata: baseRuleset.expandMetadata()});
731
+ }
732
+ }
733
+
734
+ /// @notice A project's currently active ruleset and its metadata.
735
+ /// @param projectId The ID of the project to get the current ruleset of.
736
+ /// @return ruleset The current ruleset's struct.
737
+ /// @return metadata The current ruleset's metadata.
738
+ function currentRulesetOf(uint256 projectId)
739
+ external
740
+ view
741
+ override
742
+ returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata)
743
+ {
744
+ ruleset = _currentRulesetOf(projectId);
745
+ metadata = ruleset.expandMetadata();
746
+ }
747
+
748
+ /// @notice Get the `JBRuleset` and `JBRulesetMetadata` corresponding to the specified `rulesetId`.
749
+ /// @param projectId The ID of the project the ruleset belongs to.
750
+ /// @return ruleset The ruleset's struct.
751
+ /// @return metadata The ruleset's metadata.
752
+ function getRulesetOf(
753
+ uint256 projectId,
754
+ uint256 rulesetId
755
+ )
756
+ external
757
+ view
758
+ override
759
+ returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata)
760
+ {
761
+ ruleset = RULESETS.getRulesetOf({projectId: projectId, rulesetId: rulesetId});
762
+ metadata = ruleset.expandMetadata();
763
+ }
764
+
765
+ /// @notice Gets the latest ruleset queued for a project, its approval status, and its metadata.
766
+ /// @dev The 'latest queued ruleset' is the ruleset initialized furthest in the future (at the end of the ruleset
767
+ /// queue).
768
+ /// @param projectId The ID of the project to get the latest ruleset of.
769
+ /// @return ruleset The struct for the project's latest queued ruleset.
770
+ /// @return metadata The ruleset's metadata.
771
+ /// @return approvalStatus The ruleset's approval status.
772
+ function latestQueuedRulesetOf(uint256 projectId)
773
+ external
774
+ view
775
+ override
776
+ returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata, JBApprovalStatus approvalStatus)
777
+ {
778
+ (ruleset, approvalStatus) = RULESETS.latestQueuedOf(projectId);
779
+ metadata = ruleset.expandMetadata();
780
+ }
781
+
782
+ /// @notice Check whether the project's controller can currently be set.
783
+ /// @param projectId The ID of the project to check.
784
+ /// @return A `bool` which is true if the project allows controllers to be set.
785
+ function setControllerAllowed(uint256 projectId) external view returns (bool) {
786
+ return _currentRulesetOf(projectId).expandMetadata().allowSetController;
787
+ }
788
+
789
+ /// @notice Check whether the project's terminals can currently be set.
790
+ /// @param projectId The ID of the project to check.
791
+ /// @return A `bool` which is true if the project allows terminals to be set.
792
+ function setTerminalsAllowed(uint256 projectId) external view returns (bool) {
793
+ return _currentRulesetOf(projectId).expandMetadata().allowSetTerminals;
794
+ }
795
+
796
+ /// @notice Gets the a project token's total supply, including pending reserved tokens.
797
+ /// @param projectId The ID of the project to get the total token supply of.
798
+ /// @return The total supply of the project's token, including pending reserved tokens.
799
+ function totalTokenSupplyWithReservedTokensOf(uint256 projectId) external view override returns (uint256) {
800
+ // Add the reserved tokens to the total supply.
801
+ return TOKENS.totalSupplyOf(projectId) + pendingReservedTokenBalanceOf[projectId];
802
+ }
803
+
804
+ /// @notice A project's next ruleset along with its metadata.
805
+ /// @dev If an upcoming ruleset isn't found, returns an empty ruleset with all properties set to 0.
806
+ /// @param projectId The ID of the project to get the next ruleset of.
807
+ /// @return ruleset The upcoming ruleset's struct.
808
+ /// @return metadata The upcoming ruleset's metadata.
809
+ function upcomingRulesetOf(uint256 projectId)
810
+ external
811
+ view
812
+ override
813
+ returns (JBRuleset memory ruleset, JBRulesetMetadata memory metadata)
814
+ {
815
+ ruleset = _upcomingRulesetOf(projectId);
816
+ metadata = ruleset.expandMetadata();
817
+ }
818
+
819
+ //*********************************************************************//
820
+ // -------------------------- public views --------------------------- //
821
+ //*********************************************************************//
822
+
823
+ /// @notice Indicates whether this contract adheres to the specified interface.
824
+ /// @dev See {IERC165-supportsInterface}.
825
+ /// @param interfaceId The ID of the interface to check for adherence to.
826
+ /// @return A flag indicating if the provided interface ID is supported.
827
+ function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
828
+ return interfaceId == type(IJBController).interfaceId || interfaceId == type(IJBProjectUriRegistry).interfaceId
829
+ || interfaceId == type(IJBDirectoryAccessControl).interfaceId
830
+ || interfaceId == type(IJBMigratable).interfaceId || interfaceId == type(IJBPermissioned).interfaceId
831
+ || interfaceId == type(IERC165).interfaceId;
832
+ }
833
+
834
+ //*********************************************************************//
835
+ // ---------------------- internal transactions ---------------------- //
836
+ //*********************************************************************//
837
+
838
+ /// @notice Set up a project's terminals.
839
+ /// @param projectId The ID of the project to set up terminals for.
840
+ /// @param terminalConfigurations The terminals to set up.
841
+ function _configureTerminals(uint256 projectId, JBTerminalConfig[] calldata terminalConfigurations) internal {
842
+ // Initialize an array of terminals to populate.
843
+ IJBTerminal[] memory terminals = new IJBTerminal[](terminalConfigurations.length);
844
+
845
+ for (uint256 i; i < terminalConfigurations.length; i++) {
846
+ // Set the terminal configuration being iterated on.
847
+ JBTerminalConfig memory terminalConfig = terminalConfigurations[i];
911
848
 
912
849
  // Add the accounting contexts for the specified tokens.
913
850
  terminalConfig.terminal
@@ -982,57 +919,6 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
982
919
  }
983
920
  }
984
921
 
985
- /// @notice Sends pending reserved tokens to the project's reserved token splits.
986
- /// @dev If the project has no reserved token splits, or if they don't add up to 100%, leftover tokens are sent to
987
- /// the project's owner.
988
- /// @param projectId The ID of the project to send reserved tokens for.
989
- /// @return tokenCount The amount of reserved tokens minted and sent.
990
- function _sendReservedTokensToSplitsOf(uint256 projectId) internal returns (uint256 tokenCount) {
991
- // Get a reference to the number of tokens that need to be minted.
992
- tokenCount = pendingReservedTokenBalanceOf[projectId];
993
-
994
- // Revert if there are no pending reserved tokens
995
- if (tokenCount == 0) revert JBController_NoReservedTokens();
996
-
997
- // Get the ruleset to read the reserved percent from.
998
- JBRuleset memory ruleset = _currentRulesetOf(projectId);
999
-
1000
- // Get a reference to the project's owner.
1001
- address owner = PROJECTS.ownerOf(projectId);
1002
-
1003
- // Reset the pending reserved token balance.
1004
- pendingReservedTokenBalanceOf[projectId] = 0;
1005
-
1006
- // Mint the tokens to this contract.
1007
- IJBToken token = TOKENS.mintFor({holder: address(this), projectId: projectId, count: tokenCount});
1008
-
1009
- // Send reserved tokens to splits and get a reference to the amount left after the splits have all been paid.
1010
- uint256 leftoverTokenCount = tokenCount == 0
1011
- ? 0
1012
- : _sendReservedTokensToSplitGroupOf({
1013
- projectId: projectId,
1014
- rulesetId: ruleset.id,
1015
- groupId: JBSplitGroupIds.RESERVED_TOKENS,
1016
- tokenCount: tokenCount,
1017
- token: token
1018
- });
1019
-
1020
- // Mint any leftover tokens to the project owner.
1021
- if (leftoverTokenCount > 0) {
1022
- _sendTokens({projectId: projectId, tokenCount: leftoverTokenCount, recipient: owner, token: token});
1023
- }
1024
-
1025
- emit SendReservedTokensToSplits({
1026
- rulesetId: ruleset.id,
1027
- rulesetCycleNumber: ruleset.cycleNumber,
1028
- projectId: projectId,
1029
- owner: owner,
1030
- tokenCount: tokenCount,
1031
- leftoverAmount: leftoverTokenCount,
1032
- caller: _msgSender()
1033
- });
1034
- }
1035
-
1036
922
  /// @notice Send project tokens to a split group.
1037
923
  /// @dev This is used to send reserved tokens to the reserved token split group.
1038
924
  /// @param projectId The ID of the project the splits belong to.
@@ -1169,6 +1055,57 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
1169
1055
  }
1170
1056
  }
1171
1057
 
1058
+ /// @notice Sends pending reserved tokens to the project's reserved token splits.
1059
+ /// @dev If the project has no reserved token splits, or if they don't add up to 100%, leftover tokens are sent to
1060
+ /// the project's owner.
1061
+ /// @param projectId The ID of the project to send reserved tokens for.
1062
+ /// @return tokenCount The amount of reserved tokens minted and sent.
1063
+ function _sendReservedTokensToSplitsOf(uint256 projectId) internal returns (uint256 tokenCount) {
1064
+ // Get a reference to the number of tokens that need to be minted.
1065
+ tokenCount = pendingReservedTokenBalanceOf[projectId];
1066
+
1067
+ // Revert if there are no pending reserved tokens
1068
+ if (tokenCount == 0) revert JBController_NoReservedTokens();
1069
+
1070
+ // Get the ruleset to read the reserved percent from.
1071
+ JBRuleset memory ruleset = _currentRulesetOf(projectId);
1072
+
1073
+ // Get a reference to the project's owner.
1074
+ address owner = PROJECTS.ownerOf(projectId);
1075
+
1076
+ // Reset the pending reserved token balance.
1077
+ pendingReservedTokenBalanceOf[projectId] = 0;
1078
+
1079
+ // Mint the tokens to this contract.
1080
+ IJBToken token = TOKENS.mintFor({holder: address(this), projectId: projectId, count: tokenCount});
1081
+
1082
+ // Send reserved tokens to splits and get a reference to the amount left after the splits have all been paid.
1083
+ uint256 leftoverTokenCount = tokenCount == 0
1084
+ ? 0
1085
+ : _sendReservedTokensToSplitGroupOf({
1086
+ projectId: projectId,
1087
+ rulesetId: ruleset.id,
1088
+ groupId: JBSplitGroupIds.RESERVED_TOKENS,
1089
+ tokenCount: tokenCount,
1090
+ token: token
1091
+ });
1092
+
1093
+ // Mint any leftover tokens to the project owner.
1094
+ if (leftoverTokenCount > 0) {
1095
+ _sendTokens({projectId: projectId, tokenCount: leftoverTokenCount, recipient: owner, token: token});
1096
+ }
1097
+
1098
+ emit SendReservedTokensToSplits({
1099
+ rulesetId: ruleset.id,
1100
+ rulesetCycleNumber: ruleset.cycleNumber,
1101
+ projectId: projectId,
1102
+ owner: owner,
1103
+ tokenCount: tokenCount,
1104
+ leftoverAmount: leftoverTokenCount,
1105
+ caller: _msgSender()
1106
+ });
1107
+ }
1108
+
1172
1109
  /// @notice Send tokens from this contract to a recipient.
1173
1110
  /// @param projectId The ID of the project the tokens belong to.
1174
1111
  /// @param tokenCount The number of tokens to send.
@@ -1183,4 +1120,67 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
1183
1120
  });
1184
1121
  }
1185
1122
  }
1123
+
1124
+ //*********************************************************************//
1125
+ // -------------------------- internal views ------------------------- //
1126
+ //*********************************************************************//
1127
+
1128
+ /// @dev `ERC-2771` specifies the context as being a single address (20 bytes).
1129
+ function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
1130
+ return super._contextSuffixLength();
1131
+ }
1132
+
1133
+ /// @notice The project's current ruleset.
1134
+ /// @param projectId The ID of the project to check.
1135
+ /// @return The project's current ruleset.
1136
+ function _currentRulesetOf(uint256 projectId) internal view returns (JBRuleset memory) {
1137
+ return RULESETS.currentOf(projectId);
1138
+ }
1139
+
1140
+ /// @notice Indicates whether the provided address has mint permission for the project byway of the data hook.
1141
+ /// @param projectId The ID of the project to check.
1142
+ /// @param ruleset The ruleset to check.
1143
+ /// @param addr The address to check.
1144
+ /// @return A flag indicating if the provided address has mint permission for the project.
1145
+ function _hasDataHookMintPermissionFor(
1146
+ uint256 projectId,
1147
+ JBRuleset memory ruleset,
1148
+ address addr
1149
+ )
1150
+ internal
1151
+ view
1152
+ returns (bool)
1153
+ {
1154
+ address dataHook = ruleset.dataHook();
1155
+
1156
+ return dataHook != address(0)
1157
+ && IJBRulesetDataHook(dataHook).hasMintPermissionFor({projectId: projectId, ruleset: ruleset, addr: addr});
1158
+ }
1159
+
1160
+ /// @notice Indicates whether the provided address is a terminal for the project.
1161
+ /// @param projectId The ID of the project to check.
1162
+ /// @param terminal The address to check.
1163
+ /// @return A flag indicating if the provided address is a terminal for the project.
1164
+ function _isTerminalOf(uint256 projectId, address terminal) internal view returns (bool) {
1165
+ return DIRECTORY.isTerminalOf({projectId: projectId, terminal: IJBTerminal(terminal)});
1166
+ }
1167
+
1168
+ /// @notice The calldata. Preferred to use over `msg.data`.
1169
+ /// @return calldata The `msg.data` of this call.
1170
+ function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
1171
+ return ERC2771Context._msgData();
1172
+ }
1173
+
1174
+ /// @notice The message's sender. Preferred to use over `msg.sender`.
1175
+ /// @return sender The address which sent this call.
1176
+ function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
1177
+ return ERC2771Context._msgSender();
1178
+ }
1179
+
1180
+ /// @notice The project's upcoming ruleset.
1181
+ /// @param projectId The ID of the project to check.
1182
+ /// @return The project's upcoming ruleset.
1183
+ function _upcomingRulesetOf(uint256 projectId) internal view returns (JBRuleset memory) {
1184
+ return RULESETS.upcomingOf(projectId);
1185
+ }
1186
1186
  }
@@ -3,9 +3,9 @@ pragma solidity 0.8.26;
3
3
 
4
4
  import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
5
5
 
6
- import {JBRuleset} from "./structs/JBRuleset.sol";
7
6
  import {JBApprovalStatus} from "./enums/JBApprovalStatus.sol";
8
7
  import {IJBRulesetApprovalHook} from "./interfaces/IJBRulesetApprovalHook.sol";
8
+ import {JBRuleset} from "./structs/JBRuleset.sol";
9
9
 
10
10
  /// @notice `JBDeadline` is a ruleset approval hook which rejects rulesets if they are not queued at least `duration`
11
11
  /// seconds before the current ruleset ends. In other words, rulesets must be queued before the deadline to take effect.