@bananapus/core-v6 0.0.32 → 0.0.33

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/JBRulesets.sol +67 -94
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/core-v6",
3
- "version": "0.0.32",
3
+ "version": "0.0.33",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -208,8 +208,8 @@ contract JBRulesets is JBControlled, IJBRulesets {
208
208
  caller: msg.sender
209
209
  });
210
210
 
211
- // Return the struct for the new ruleset's ID.
212
- return _getStructFor({projectId: projectId, rulesetId: rulesetId});
211
+ // Return the struct for the new ruleset's ID, with metadata.
212
+ return _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: true});
213
213
  }
214
214
 
215
215
  /// @notice Cache the value of the ruleset weight for a specific ruleset.
@@ -221,7 +221,8 @@ contract JBRulesets is JBControlled, IJBRulesets {
221
221
  /// @param rulesetId The ID of the ruleset to update the cache for.
222
222
  function updateRulesetWeightCache(uint256 projectId, uint256 rulesetId) external override {
223
223
  // Get the target ruleset.
224
- JBRuleset memory targetRuleset = _getStructFor({projectId: projectId, rulesetId: rulesetId});
224
+ JBRuleset memory targetRuleset =
225
+ _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: false});
225
226
 
226
227
  // Nothing to cache if the target ruleset doesn't have a duration or a weight cut percent.
227
228
  // slither-disable-next-line incorrect-equality
@@ -296,8 +297,8 @@ contract JBRulesets is JBControlled, IJBRulesets {
296
297
  // Keep a reference to the number of rulesets being returned.
297
298
  uint256 count = 0;
298
299
 
299
- // Keep a reference to the starting ruleset.
300
- JBRuleset memory ruleset = _getStructFor({projectId: projectId, rulesetId: startingId});
300
+ // Keep a reference to the starting ruleset (metadata not needed — only counting).
301
+ JBRuleset memory ruleset = _getStructFor({projectId: projectId, rulesetId: startingId, withMetadata: false});
301
302
 
302
303
  // First, count the number of rulesets to include in the result by iterating backwards from the starting
303
304
  // ruleset.
@@ -306,7 +307,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
306
307
  count++;
307
308
 
308
309
  // Iterate to the ruleset it was based on.
309
- ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId});
310
+ ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId, withMetadata: false});
310
311
  }
311
312
 
312
313
  // Keep a reference to the array of rulesets that'll be populated.
@@ -317,8 +318,8 @@ contract JBRulesets is JBControlled, IJBRulesets {
317
318
  return rulesets;
318
319
  }
319
320
 
320
- // Reset the ruleset being iterated on to the starting ruleset.
321
- ruleset = _getStructFor({projectId: projectId, rulesetId: startingId});
321
+ // Reset the ruleset being iterated on to the starting ruleset, now with metadata for the return array.
322
+ ruleset = _getStructFor({projectId: projectId, rulesetId: startingId, withMetadata: true});
322
323
 
323
324
  // Set the counter.
324
325
  uint256 i;
@@ -328,8 +329,10 @@ contract JBRulesets is JBControlled, IJBRulesets {
328
329
  // Add the ruleset to the array.
329
330
  rulesets[i++] = ruleset;
330
331
 
331
- // Get the ruleset it was based on if needed.
332
- if (i != count) ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId});
332
+ // Get the ruleset it was based on if needed, with metadata for the return array.
333
+ if (i != count) {
334
+ ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId, withMetadata: true});
335
+ }
333
336
  }
334
337
  }
335
338
 
@@ -345,8 +348,8 @@ contract JBRulesets is JBControlled, IJBRulesets {
345
348
  // Get a reference to the latest ruleset ID.
346
349
  uint256 rulesetId = latestRulesetIdOf[projectId];
347
350
 
348
- // Resolve the struct for the latest ruleset.
349
- JBRuleset memory ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId});
351
+ // Resolve the struct for the latest ruleset, with metadata (forwarded to the external approval hook).
352
+ JBRuleset memory ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: true});
350
353
 
351
354
  return _approvalStatusOf({projectId: projectId, ruleset: ruleset});
352
355
  }
@@ -362,15 +365,18 @@ contract JBRulesets is JBControlled, IJBRulesets {
362
365
  function currentOf(uint256 projectId) external view override returns (JBRuleset memory ruleset) {
363
366
  // If the project does not have a ruleset, return an empty struct.
364
367
  // slither-disable-next-line incorrect-equality
365
- if (latestRulesetIdOf[projectId] == 0) return _getStructFor({projectId: 0, rulesetId: 0});
368
+ if (latestRulesetIdOf[projectId] == 0) {
369
+ return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
370
+ }
366
371
 
367
372
  // Get a reference to the currently approvable ruleset's ID.
368
373
  uint256 rulesetId = _currentlyApprovableRulesetIdOf(projectId);
369
374
 
370
375
  // If a currently approvable ruleset exists...
371
376
  if (rulesetId != 0) {
372
- // Resolve the struct for the currently approvable ruleset.
373
- ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId});
377
+ // Resolve the struct for the currently approvable ruleset, with metadata (forwarded to external hooks
378
+ // and potentially returned).
379
+ ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: true});
374
380
 
375
381
  // Get a reference to the approval status.
376
382
  JBApprovalStatus approvalStatus = _approvalStatusOf({projectId: projectId, ruleset: ruleset});
@@ -387,15 +393,16 @@ contract JBRulesets is JBControlled, IJBRulesets {
387
393
  // which carries the last approved configuration.
388
394
  rulesetId = ruleset.basedOnId;
389
395
 
390
- // Keep a reference to its ruleset.
391
- ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId});
396
+ // Keep a reference to its ruleset, with metadata (used by `_simulateCycledRulesetBasedOn` and may be
397
+ // returned).
398
+ ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: true});
392
399
  } else {
393
400
  // No upcoming ruleset found that is currently approvable,
394
401
  // so use the latest ruleset ID.
395
402
  rulesetId = latestRulesetIdOf[projectId];
396
403
 
397
- // Get the struct for the latest ID.
398
- ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId});
404
+ // Get the struct for the latest ID, with metadata (forwarded to external hooks and may be returned).
405
+ ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: true});
399
406
 
400
407
  // Get a reference to the approval status.
401
408
  JBApprovalStatus approvalStatus = _approvalStatusOf({projectId: projectId, ruleset: ruleset});
@@ -407,7 +414,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
407
414
  || block.timestamp < ruleset.start
408
415
  ) {
409
416
  rulesetId = ruleset.basedOnId;
410
- ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId});
417
+ ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: true});
411
418
  approvalStatus = _approvalStatusOf({projectId: projectId, ruleset: ruleset});
412
419
  }
413
420
  }
@@ -433,7 +440,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
433
440
  override
434
441
  returns (JBRuleset memory ruleset)
435
442
  {
436
- return _getStructFor({projectId: projectId, rulesetId: rulesetId});
443
+ ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: true});
437
444
  }
438
445
 
439
446
  /// @notice The latest ruleset queued for a project. Returns the ruleset's struct and its current approval status.
@@ -451,8 +458,9 @@ contract JBRulesets is JBControlled, IJBRulesets {
451
458
  // Get a reference to the latest ruleset's ID.
452
459
  uint256 rulesetId = latestRulesetIdOf[projectId];
453
460
 
454
- // Resolve the struct for the latest ruleset.
455
- ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId});
461
+ // Resolve the struct for the latest ruleset, with metadata (forwarded to the external approval hook and
462
+ // returned).
463
+ ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: true});
456
464
 
457
465
  // Resolve the approval status.
458
466
  approvalStatus = _approvalStatusOf({projectId: projectId, ruleset: ruleset});
@@ -465,7 +473,9 @@ contract JBRulesets is JBControlled, IJBRulesets {
465
473
  function upcomingOf(uint256 projectId) external view override returns (JBRuleset memory ruleset) {
466
474
  // If the project does not have a latest ruleset, return an empty struct.
467
475
  // slither-disable-next-line incorrect-equality
468
- if (latestRulesetIdOf[projectId] == 0) return _getStructFor({projectId: 0, rulesetId: 0});
476
+ if (latestRulesetIdOf[projectId] == 0) {
477
+ return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
478
+ }
469
479
 
470
480
  // Get a reference to the upcoming approvable ruleset's ID.
471
481
  uint256 upcomingApprovableRulesetId = _upcomingApprovableRulesetIdOf(projectId);
@@ -476,7 +486,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
476
486
  // If an upcoming approvable ruleset has been queued, and it's approval status is Approved or ApprovalExpected,
477
487
  // return its ruleset struct
478
488
  if (upcomingApprovableRulesetId != 0) {
479
- ruleset = _getStructFor({projectId: projectId, rulesetId: upcomingApprovableRulesetId});
489
+ ruleset = _getStructFor({projectId: projectId, rulesetId: upcomingApprovableRulesetId, withMetadata: true});
480
490
 
481
491
  // Get a reference to the approval status.
482
492
  approvalStatus = _approvalStatusOf({projectId: projectId, ruleset: ruleset});
@@ -488,23 +498,25 @@ contract JBRulesets is JBControlled, IJBRulesets {
488
498
  || approvalStatus == JBApprovalStatus.Empty
489
499
  ) return ruleset;
490
500
 
491
- // Resolve the ruleset for the ruleset the upcoming approvable ruleset was based on.
492
- ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId});
501
+ // Resolve the ruleset for the ruleset the upcoming approvable ruleset was based on, with metadata
502
+ // (used by `_simulateCycledRulesetBasedOn`).
503
+ ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId, withMetadata: true});
493
504
  } else {
494
- // Resolve the ruleset for the latest queued ruleset.
495
- ruleset = _getStructFor({projectId: projectId, rulesetId: latestRulesetIdOf[projectId]});
505
+ // Resolve the ruleset for the latest queued ruleset, with metadata (forwarded to external hooks and used
506
+ // by `_simulateCycledRulesetBasedOn`).
507
+ ruleset = _getStructFor({projectId: projectId, rulesetId: latestRulesetIdOf[projectId], withMetadata: true});
496
508
 
497
509
  // If the latest ruleset starts in the future, it must start in the distant future
498
510
  // Since its not the upcoming approvable ruleset. In this case, base the upcoming ruleset on the base
499
511
  // ruleset.
500
512
  while (ruleset.start > block.timestamp) {
501
- ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId});
513
+ ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId, withMetadata: true});
502
514
  }
503
515
  }
504
516
 
505
517
  // There's no queued if the current has a duration of 0.
506
518
  // slither-disable-next-line incorrect-equality
507
- if (ruleset.duration == 0) return _getStructFor({projectId: 0, rulesetId: 0});
519
+ if (ruleset.duration == 0) return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
508
520
 
509
521
  // Get a reference to the approval status.
510
522
  approvalStatus = _approvalStatusOf({projectId: projectId, ruleset: ruleset});
@@ -516,12 +528,13 @@ contract JBRulesets is JBControlled, IJBRulesets {
516
528
  return _simulateCycledRulesetBasedOn({projectId: projectId, baseRuleset: ruleset, allowMidRuleset: false});
517
529
  }
518
530
 
519
- // Get the ruleset of its base ruleset, which carries the last approved configuration.
520
- ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId});
531
+ // Get the ruleset of its base ruleset, which carries the last approved configuration. Metadata is needed by
532
+ // `_simulateCycledRulesetBasedOn`.
533
+ ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId, withMetadata: true});
521
534
 
522
535
  // There's no queued if the base, which must still be the current, has a duration of 0.
523
536
  // slither-disable-next-line incorrect-equality
524
- if (ruleset.duration == 0) return _getStructFor({projectId: 0, rulesetId: 0});
537
+ if (ruleset.duration == 0) return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
525
538
 
526
539
  // Return a simulated cycled ruleset.
527
540
  return _simulateCycledRulesetBasedOn({projectId: projectId, baseRuleset: ruleset, allowMidRuleset: false});
@@ -715,16 +728,16 @@ contract JBRulesets is JBControlled, IJBRulesets {
715
728
  // Use an empty ruleset as the base.
716
729
  return _initializeRulesetFor({
717
730
  projectId: projectId,
718
- baseRuleset: _getStructFor({projectId: 0, rulesetId: 0}),
731
+ baseRuleset: _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false}),
719
732
  rulesetId: rulesetId,
720
733
  mustStartAtOrAfter: mustStartAtOrAfter,
721
734
  weight: weight
722
735
  });
723
736
  }
724
737
 
725
- // Get a reference to the latest ruleset's struct.
726
- // Note: full metadata is loaded because `_approvalStatusOf` forwards the struct to external approval hooks.
727
- JBRuleset memory baseRuleset = _getStructFor({projectId: projectId, rulesetId: latestId});
738
+ // Get a reference to the latest ruleset's struct, with metadata because `_approvalStatusOf` forwards the
739
+ // struct to external approval hooks.
740
+ JBRuleset memory baseRuleset = _getStructFor({projectId: projectId, rulesetId: latestId, withMetadata: true});
728
741
 
729
742
  // Get a reference to the approval status.
730
743
  JBApprovalStatus approvalStatus = _approvalStatusOf({projectId: projectId, ruleset: baseRuleset});
@@ -748,7 +761,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
748
761
  ) {
749
762
  // Metadata not needed — the fallback ruleset is only used for intrinsic fields (start, basedOnId, etc.)
750
763
  // and not forwarded to any external approval hook.
751
- baseRuleset = _getStructWithoutMetadataFor({projectId: projectId, rulesetId: baseRuleset.basedOnId});
764
+ baseRuleset = _getStructFor({projectId: projectId, rulesetId: baseRuleset.basedOnId, withMetadata: false});
752
765
  }
753
766
 
754
767
  // Make sure the ruleset starts after the base ruleset.
@@ -935,7 +948,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
935
948
  uint256 rulesetId = latestRulesetIdOf[projectId];
936
949
 
937
950
  // Get the struct for the latest ruleset (metadata not needed — only traversal fields are checked).
938
- JBRuleset memory ruleset = _getStructWithoutMetadataFor({projectId: projectId, rulesetId: rulesetId});
951
+ JBRuleset memory ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: false});
939
952
 
940
953
  // Loop through all most recently queued rulesets until an approvable one is found, or we've proven one can't
941
954
  // exist.
@@ -951,22 +964,23 @@ contract JBRulesets is JBControlled, IJBRulesets {
951
964
  return ruleset.id;
952
965
  }
953
966
 
954
- ruleset = _getStructWithoutMetadataFor({projectId: projectId, rulesetId: ruleset.basedOnId});
967
+ ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId, withMetadata: false});
955
968
  } while (ruleset.cycleNumber != 0);
956
969
 
957
970
  return 0;
958
971
  }
959
972
 
960
- /// @notice Unpack a ruleset's intrinsic and user properties without loading metadata.
961
- /// @dev Saves one cold SLOAD (~2,100 gas) compared to `_getStructFor`. Use this for linked-list traversal where
962
- /// only `id`, `start`, `duration`, `basedOnId`, `cycleNumber`, `weight`, `weightCutPercent`, and `approvalHook`
963
- /// are needed.
973
+ /// @notice Unpack a ruleset's packed stored values into a struct.
974
+ /// @dev When `withMetadata` is false, one cold SLOAD (~2,100 gas) is skipped use this for linked-list traversal
975
+ /// where only id, start, duration, basedOnId, etc. are needed.
964
976
  /// @param projectId The ID of the project the ruleset belongs to.
965
977
  /// @param rulesetId The ID of the ruleset to get the struct for.
966
- /// @return ruleset A ruleset struct with `metadata` set to 0.
967
- function _getStructWithoutMetadataFor(
978
+ /// @param withMetadata Whether to load the packed metadata from storage.
979
+ /// @return ruleset The ruleset struct (`metadata` is 0 when `withMetadata` is false).
980
+ function _getStructFor(
968
981
  uint256 projectId,
969
- uint256 rulesetId
982
+ uint256 rulesetId,
983
+ bool withMetadata
970
984
  )
971
985
  internal
972
986
  view
@@ -1006,49 +1020,8 @@ contract JBRulesets is JBControlled, IJBRulesets {
1006
1020
  // forge-lint: disable-next-line(unsafe-typecast)
1007
1021
  ruleset.weightCutPercent = uint32(packedUserProperties >> 192);
1008
1022
 
1009
- // metadata intentionally not loaded — saves one cold SLOAD (~2,100 gas).
1010
- }
1011
-
1012
- /// @notice Unpack a ruleset's packed stored values into an easy-to-work-with ruleset struct.
1013
- /// @param projectId The ID of the project the ruleset belongs to.
1014
- /// @param rulesetId The ID of the ruleset to get the full struct for.
1015
- /// @return ruleset A ruleset struct.
1016
- function _getStructFor(uint256 projectId, uint256 rulesetId) internal view returns (JBRuleset memory ruleset) {
1017
- // Return an empty ruleset if the specified `rulesetId` is 0.
1018
- // slither-disable-next-line incorrect-equality
1019
- if (rulesetId == 0) return ruleset;
1020
-
1021
- // forge-lint: disable-next-line(unsafe-typecast)
1022
- ruleset.id = uint48(rulesetId);
1023
-
1024
- uint256 packedIntrinsicProperties = _packedIntrinsicPropertiesOf[projectId][rulesetId];
1025
-
1026
- // `weight` in bits 0-111 bits.
1027
- // forge-lint: disable-next-line(unsafe-typecast)
1028
- ruleset.weight = uint112(packedIntrinsicProperties);
1029
- // `basedOnId` in bits 112-159 bits.
1030
- // forge-lint: disable-next-line(unsafe-typecast)
1031
- ruleset.basedOnId = uint48(packedIntrinsicProperties >> 112);
1032
- // `start` in bits 160-207 bits.
1033
- // forge-lint: disable-next-line(unsafe-typecast)
1034
- ruleset.start = uint48(packedIntrinsicProperties >> 160);
1035
- // `cycleNumber` in bits 208-255 bits.
1036
- // forge-lint: disable-next-line(unsafe-typecast)
1037
- ruleset.cycleNumber = uint48(packedIntrinsicProperties >> 208);
1038
-
1039
- uint256 packedUserProperties = _packedUserPropertiesOf[projectId][rulesetId];
1040
-
1041
- // approval hook in bits 0-159 bits.
1042
- // forge-lint: disable-next-line(unsafe-typecast)
1043
- ruleset.approvalHook = IJBRulesetApprovalHook(address(uint160(packedUserProperties)));
1044
- // `duration` in bits 160-191 bits.
1045
- // forge-lint: disable-next-line(unsafe-typecast)
1046
- ruleset.duration = uint32(packedUserProperties >> 160);
1047
- // weight cut percent in bits 192-223 bits.
1048
- // forge-lint: disable-next-line(unsafe-typecast)
1049
- ruleset.weightCutPercent = uint32(packedUserProperties >> 192);
1050
-
1051
- ruleset.metadata = _metadataOf[projectId][rulesetId];
1023
+ // Load metadata only when needed — saves one cold SLOAD (~2,100 gas) for traversal-only paths.
1024
+ if (withMetadata) ruleset.metadata = _metadataOf[projectId][rulesetId];
1052
1025
  }
1053
1026
 
1054
1027
  /// @notice A simulated view of the ruleset that would be created if the provided one cycled over (if the project
@@ -1126,7 +1099,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
1126
1099
  rulesetId = latestRulesetIdOf[projectId];
1127
1100
 
1128
1101
  // Get the struct for the latest ruleset (metadata not needed — only traversal fields are checked).
1129
- JBRuleset memory ruleset = _getStructWithoutMetadataFor({projectId: projectId, rulesetId: rulesetId});
1102
+ JBRuleset memory ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: false});
1130
1103
 
1131
1104
  // There is no upcoming ruleset if the latest ruleset has already started.
1132
1105
  // slither-disable-next-line incorrect-equality
@@ -1144,7 +1117,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
1144
1117
 
1145
1118
  // Find the base ruleset that is not still queued.
1146
1119
  while (true) {
1147
- baseRuleset = _getStructWithoutMetadataFor({projectId: projectId, rulesetId: basedOnId});
1120
+ baseRuleset = _getStructFor({projectId: projectId, rulesetId: basedOnId, withMetadata: false});
1148
1121
 
1149
1122
  // If the base ruleset starts in the future,
1150
1123
  if (block.timestamp < baseRuleset.start) {
@@ -1159,7 +1132,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
1159
1132
  }
1160
1133
 
1161
1134
  // Get the ruleset struct for the ID found (metadata not needed — only `start` and `duration` are checked).
1162
- ruleset = _getStructWithoutMetadataFor({projectId: projectId, rulesetId: rulesetId});
1135
+ ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: false});
1163
1136
 
1164
1137
  // If the latest ruleset doesn't start until after another base ruleset return 0.
1165
1138
  if (baseRuleset.duration != 0 && block.timestamp < ruleset.start - baseRuleset.duration) {