@bananapus/721-hook-v6 0.0.25 → 0.0.26

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/721-hook-v6",
3
- "version": "0.0.25",
3
+ "version": "0.0.26",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -42,6 +42,7 @@ contract JB721TiersHook is JBOwnable, ERC2771Context, JB721Hook, IJB721TiersHook
42
42
  //*********************************************************************//
43
43
 
44
44
  error JB721TiersHook_AlreadyInitialized(uint256 projectId);
45
+ error JB721TiersHook_CantBuyWithCredits();
45
46
  error JB721TiersHook_CurrencyMismatch(uint256 paymentCurrency, uint256 tierCurrency);
46
47
  error JB721TiersHook_InvalidPricingDecimals(uint256 decimals);
47
48
  error JB721TiersHook_MintReserveNftsPaused();
@@ -387,23 +388,13 @@ contract JB721TiersHook is JBOwnable, ERC2771Context, JB721Hook, IJB721TiersHook
387
388
 
388
389
  // Record the mint. The token IDs returned correspond to the tiers passed in.
389
390
  // slither-disable-next-line reentrancy-events,unused-return
390
- (tokenIds,) = STORE.recordMint({
391
+ (tokenIds,,) = STORE.recordMint({
391
392
  amount: type(uint256).max, // force the mint.
392
393
  tierIds: tierIds,
393
394
  isOwnerMint: true // manual mint.
394
395
  });
395
396
 
396
- for (uint256 i; i < tierIds.length; i++) {
397
- // Set the token ID.
398
- uint256 tokenId = tokenIds[i];
399
-
400
- // Mint the NFT.
401
- _mint({to: beneficiary, tokenId: tokenId});
402
-
403
- emit Mint({
404
- tokenId: tokenId, tierId: tierIds[i], beneficiary: beneficiary, totalAmountPaid: 0, caller: _msgSender()
405
- });
406
- }
397
+ _mintTokens({tokenIds: tokenIds, tierIds: tierIds, beneficiary: beneficiary, totalAmountPaid: 0});
407
398
  }
408
399
 
409
400
  /// @notice Mint pending reserved NFTs based on the provided information.
@@ -594,47 +585,30 @@ contract JB721TiersHook is JBOwnable, ERC2771Context, JB721Hook, IJB721TiersHook
594
585
  STORE.recordBurn(tokenIds);
595
586
  }
596
587
 
597
- /// @notice Mints one NFT from each of the specified tiers for the beneficiary.
598
- /// @dev The same tier can be specified more than once.
599
- /// @param amount The amount to base the mints on. The total price of the NFTs being minted cannot be larger than
600
- /// this amount.
601
- /// @param mintTierIds An array of NFT tier IDs to be minted.
602
- /// @param beneficiary The address receiving the newly minted NFTs.
603
- /// @return leftoverAmount The `amount` leftover after minting.
604
- function _mintAll(
605
- uint256 amount,
606
- uint16[] memory mintTierIds,
607
- address beneficiary
588
+ /// @notice Mints NFTs and emits events for each.
589
+ /// @param tokenIds The token IDs to mint.
590
+ /// @param tierIds The tier IDs corresponding to each token.
591
+ /// @param beneficiary The address receiving the NFTs.
592
+ /// @param totalAmountPaid The amount to report in the Mint event.
593
+ function _mintTokens(
594
+ uint256[] memory tokenIds,
595
+ uint16[] memory tierIds,
596
+ address beneficiary,
597
+ uint256 totalAmountPaid
608
598
  )
609
599
  internal
610
- returns (uint256 leftoverAmount)
611
600
  {
612
- // Keep a reference to the NFT token IDs.
613
- uint256[] memory tokenIds;
614
-
615
- // Record the NFT mints. The token IDs returned correspond to the tier IDs passed in.
616
- (tokenIds, leftoverAmount) = STORE.recordMint({
617
- amount: amount,
618
- tierIds: mintTierIds,
619
- isOwnerMint: false // Not a manual mint
620
- });
621
-
622
- // Loop through each token ID and mint the corresponding NFT.
623
601
  for (uint256 i; i < tokenIds.length; i++) {
624
- // Get a reference to the token ID being iterated on.
625
- uint256 tokenId = tokenIds[i];
626
-
627
602
  emit Mint({
628
- tokenId: tokenId,
629
- tierId: mintTierIds[i],
603
+ tokenId: tokenIds[i],
604
+ tierId: tierIds[i],
630
605
  beneficiary: beneficiary,
631
- totalAmountPaid: amount,
606
+ totalAmountPaid: totalAmountPaid,
632
607
  caller: _msgSender()
633
608
  });
634
609
 
635
- // Mint the NFT.
636
610
  // slither-disable-next-line reentrancy-events
637
- _mint({to: beneficiary, tokenId: tokenId});
611
+ _mint({to: beneficiary, tokenId: tokenIds[i]});
638
612
  }
639
613
  }
640
614
 
@@ -683,9 +657,25 @@ contract JB721TiersHook is JBOwnable, ERC2771Context, JB721Hook, IJB721TiersHook
683
657
 
684
658
  // Mint NFTs from the tiers as specified.
685
659
  if (tierIdsToMint.length != 0) {
660
+ uint256[] memory tokenIds;
661
+ uint256 restrictedCost;
662
+ uint256 totalAmountPaid = leftoverAmount;
663
+
664
+ // Record the mints.
686
665
  // slither-disable-next-line reentrancy-events,reentrancy-no-eth
687
- leftoverAmount =
688
- _mintAll({amount: leftoverAmount, mintTierIds: tierIdsToMint, beneficiary: context.beneficiary});
666
+ (tokenIds, leftoverAmount, restrictedCost) =
667
+ STORE.recordMint({amount: leftoverAmount, tierIds: tierIdsToMint, isOwnerMint: false});
668
+
669
+ // Enforce `cantBuyWithCredits`: restricted tiers must be fully covered by fresh payment (not credits).
670
+ if (restrictedCost > value) revert JB721TiersHook_CantBuyWithCredits();
671
+
672
+ // Mint each token.
673
+ _mintTokens({
674
+ tokenIds: tokenIds,
675
+ tierIds: tierIdsToMint,
676
+ beneficiary: context.beneficiary,
677
+ totalAmountPaid: totalAmountPaid
678
+ });
689
679
  }
690
680
  }
691
681
 
@@ -331,7 +331,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
331
331
  JBStored721Tier memory storedTier = _storedTierOf[hook][tierId];
332
332
 
333
333
  // Check if voting units should be used. Price will be used otherwise.
334
- (,, bool useVotingUnits,,) = _unpackBools(storedTier.packedBools);
334
+ (,, bool useVotingUnits,,,) = _unpackBools(storedTier.packedBools);
335
335
 
336
336
  // Return the address' voting units within the tier.
337
337
  return balance * (useVotingUnits ? _tierVotingUnitsOf[hook][tierId] : storedTier.price);
@@ -376,7 +376,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
376
376
  JBStored721Tier memory storedTier = _storedTierOf[hook][i];
377
377
 
378
378
  // Parse the flags.
379
- (,, bool useVotingUnits,,) = _unpackBools(storedTier.packedBools);
379
+ (,, bool useVotingUnits,,,) = _unpackBools(storedTier.packedBools);
380
380
 
381
381
  // Add the voting units for the address' balance in this tier.
382
382
  // Use custom voting units if set. Otherwise, use the tier's price.
@@ -532,13 +532,8 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
532
532
  // Get a reference to the reserve beneficiary.
533
533
  address reserveBeneficiary = reserveBeneficiaryOf({hook: hook, tierId: tierId});
534
534
 
535
- (
536
- bool allowOwnerMint,
537
- bool transfersPausable,
538
- bool useVotingUnits,
539
- bool cannotBeRemoved,
540
- bool cannotIncreaseDiscountPercent
541
- ) = _unpackBools(storedTier.packedBools);
535
+ // Cache packed bools to avoid stack-too-deep from destructuring all 6 bools.
536
+ uint8 packed = storedTier.packedBools;
542
537
 
543
538
  // slither-disable-next-line calls-loop
544
539
  return JB721Tier({
@@ -547,17 +542,18 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
547
542
  price: storedTier.price,
548
543
  remainingSupply: storedTier.remainingSupply,
549
544
  initialSupply: storedTier.initialSupply,
550
- votingUnits: useVotingUnits ? _tierVotingUnitsOf[hook][tierId] : storedTier.price,
545
+ votingUnits: (packed & 0x4 != 0) ? _tierVotingUnitsOf[hook][tierId] : storedTier.price,
551
546
  // No reserve frequency if there is no reserve beneficiary.
552
547
  reserveFrequency: reserveBeneficiary == address(0) ? 0 : storedTier.reserveFrequency,
553
548
  reserveBeneficiary: reserveBeneficiary,
554
549
  encodedIPFSUri: encodedIPFSUriOf[hook][tierId],
555
550
  category: storedTier.category,
556
551
  discountPercent: storedTier.discountPercent,
557
- allowOwnerMint: allowOwnerMint,
558
- transfersPausable: transfersPausable,
559
- cannotBeRemoved: cannotBeRemoved,
560
- cannotIncreaseDiscountPercent: cannotIncreaseDiscountPercent,
552
+ allowOwnerMint: (packed & 0x1 != 0),
553
+ transfersPausable: (packed & 0x2 != 0),
554
+ cannotBeRemoved: (packed & 0x8 != 0),
555
+ cannotIncreaseDiscountPercent: (packed & 0x10 != 0),
556
+ cantBuyWithCredits: (packed & 0x20 != 0),
561
557
  splitPercent: storedTier.splitPercent,
562
558
  resolvedUri: !includeResolvedUri || tokenUriResolverOf[hook] == IJB721TokenUriResolver(address(0))
563
559
  ? ""
@@ -680,13 +676,15 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
680
676
  /// @param useVotingUnits Whether or not custom voting unit amounts are allowed in new tiers.
681
677
  /// @param cannotBeRemoved Whether or not attempts to remove the tier will revert.
682
678
  /// @param cannotIncreaseDiscountPercent Whether or not attempts to increase the discount percent will revert.
679
+ /// @param cantBuyWithCredits Whether or not the tier cannot be purchased using accumulated pay credits.
683
680
  /// @return packed The packed bools.
684
681
  function _packBools(
685
682
  bool allowOwnerMint,
686
683
  bool transfersPausable,
687
684
  bool useVotingUnits,
688
685
  bool cannotBeRemoved,
689
- bool cannotIncreaseDiscountPercent
686
+ bool cannotIncreaseDiscountPercent,
687
+ bool cantBuyWithCredits
690
688
  )
691
689
  internal
692
690
  pure
@@ -698,16 +696,18 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
698
696
  packed := or(shl(0x2, useVotingUnits), packed)
699
697
  packed := or(shl(0x3, cannotBeRemoved), packed)
700
698
  packed := or(shl(0x4, cannotIncreaseDiscountPercent), packed)
699
+ packed := or(shl(0x5, cantBuyWithCredits), packed)
701
700
  }
702
701
  }
703
702
 
704
- /// @notice Unpack five bools from a single uint8.
703
+ /// @notice Unpack six bools from a single uint8.
705
704
  /// @param packed The packed bools.
706
705
  /// @param allowOwnerMint Whether or not owner minting is allowed in new tiers.
707
706
  /// @param transfersPausable Whether or not 721 transfers can be paused.
708
707
  /// @param useVotingUnits Whether or not custom voting unit amounts are allowed in new tiers.
709
708
  /// @param cannotBeRemoved Whether or not the tier can be removed once added.
710
709
  /// @param cannotIncreaseDiscountPercent Whether or not the discount percent cannot be increased.
710
+ /// @param cantBuyWithCredits Whether or not the tier cannot be purchased using accumulated pay credits.
711
711
  function _unpackBools(uint8 packed)
712
712
  internal
713
713
  pure
@@ -716,7 +716,8 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
716
716
  bool transfersPausable,
717
717
  bool useVotingUnits,
718
718
  bool cannotBeRemoved,
719
- bool cannotIncreaseDiscountPercent
719
+ bool cannotIncreaseDiscountPercent,
720
+ bool cantBuyWithCredits
720
721
  )
721
722
  {
722
723
  assembly {
@@ -725,6 +726,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
725
726
  useVotingUnits := iszero(iszero(and(0x4, packed)))
726
727
  cannotBeRemoved := iszero(iszero(and(0x8, packed)))
727
728
  cannotIncreaseDiscountPercent := iszero(iszero(and(0x10, packed)))
729
+ cantBuyWithCredits := iszero(iszero(and(0x20, packed)))
728
730
  }
729
731
  }
730
732
 
@@ -907,7 +909,8 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
907
909
  transfersPausable: tierToAdd.transfersPausable,
908
910
  useVotingUnits: tierToAdd.useVotingUnits,
909
911
  cannotBeRemoved: tierToAdd.cannotBeRemoved,
910
- cannotIncreaseDiscountPercent: tierToAdd.cannotIncreaseDiscountPercent
912
+ cannotIncreaseDiscountPercent: tierToAdd.cannotIncreaseDiscountPercent,
913
+ cantBuyWithCredits: tierToAdd.cantBuyWithCredits
911
914
  })
912
915
  });
913
916
 
@@ -1055,6 +1058,8 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
1055
1058
  /// @param isOwnerMint A flag indicating whether this function is being directly called by the 721 contract's owner.
1056
1059
  /// @return tokenIds The token IDs of the NFTs which were minted.
1057
1060
  /// @return leftoverAmount The `amount` remaining after minting.
1061
+ /// @return restrictedCost Total cost of tiers with `cantBuyWithCredits` set. The caller can use this to enforce
1062
+ /// credit restrictions.
1058
1063
  function recordMint(
1059
1064
  uint256 amount,
1060
1065
  uint16[] calldata tierIds,
@@ -1062,7 +1067,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
1062
1067
  )
1063
1068
  external
1064
1069
  override
1065
- returns (uint256[] memory tokenIds, uint256 leftoverAmount)
1070
+ returns (uint256[] memory tokenIds, uint256 leftoverAmount, uint256 restrictedCost)
1066
1071
  {
1067
1072
  // Set the leftover amount as the initial amount.
1068
1073
  leftoverAmount = amount;
@@ -1079,6 +1084,9 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
1079
1084
  // Initialize a `JBBitmapWord` for checking whether tiers have been removed.
1080
1085
  JBBitmapWord memory bitmapWord;
1081
1086
 
1087
+ // Track total cost of tiers that can't be bought with credits (order-independent check).
1088
+ uint256 restrictedCost;
1089
+
1082
1090
  for (uint256 i; i < numberOfTiers; i++) {
1083
1091
  // Set the tier ID being iterated on.
1084
1092
  uint256 tierId = tierIds[i];
@@ -1092,7 +1100,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
1092
1100
  storedTier = _storedTierOf[msg.sender][tierId];
1093
1101
 
1094
1102
  // Parse the flags.
1095
- (bool allowOwnerMint,,,,) = _unpackBools(storedTier.packedBools);
1103
+ (bool allowOwnerMint,,,,, bool cantBuyWithCredits) = _unpackBools(storedTier.packedBools);
1096
1104
 
1097
1105
  // If this is an owner mint, make sure owner minting is allowed.
1098
1106
  if (isOwnerMint && !allowOwnerMint) revert JB721TiersHookStore_CantMintManually(tierId);
@@ -1113,6 +1121,9 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
1113
1121
  });
1114
1122
  }
1115
1123
 
1124
+ // Accumulate cost of credit-restricted tiers.
1125
+ if (cantBuyWithCredits) restrictedCost += price;
1126
+
1116
1127
  // Make sure the `amount` is greater than or equal to the tier's price.
1117
1128
  if (price > leftoverAmount) revert JB721TiersHookStore_PriceExceedsAmount(price, leftoverAmount);
1118
1129
 
@@ -1188,7 +1199,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
1188
1199
  JBStored721Tier storage storedTier = _storedTierOf[msg.sender][tierId];
1189
1200
 
1190
1201
  // Parse the flags.
1191
- (,,, bool cannotBeRemoved,) = _unpackBools(storedTier.packedBools);
1202
+ (,,, bool cannotBeRemoved,,) = _unpackBools(storedTier.packedBools);
1192
1203
 
1193
1204
  // Make sure the tier can be removed.
1194
1205
  if (cannotBeRemoved) revert JB721TiersHookStore_CantRemoveTier(tierId);
@@ -1217,7 +1228,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
1217
1228
  JBStored721Tier storage storedTier = _storedTierOf[msg.sender][tierId];
1218
1229
 
1219
1230
  // Parse the flags.
1220
- (,,,, bool cannotIncreaseDiscountPercent) = _unpackBools(storedTier.packedBools);
1231
+ (,,,, bool cannotIncreaseDiscountPercent,) = _unpackBools(storedTier.packedBools);
1221
1232
 
1222
1233
  // Make sure that increasing the discount is allowed for the tier.
1223
1234
  if (discountPercent > storedTier.discountPercent && cannotIncreaseDiscountPercent) {
@@ -193,13 +193,14 @@ interface IJB721TiersHookStore {
193
193
  /// @param isOwnerMint Whether this is a direct owner mint.
194
194
  /// @return tokenIds The token IDs of the NFTs which were minted.
195
195
  /// @return leftoverAmount The amount remaining after minting.
196
+ /// @return restrictedCost Total cost of tiers with `cantBuyWithCredits` set.
196
197
  function recordMint(
197
198
  uint256 amount,
198
199
  uint16[] calldata tierIds,
199
200
  bool isOwnerMint
200
201
  )
201
202
  external
202
- returns (uint256[] memory tokenIds, uint256 leftoverAmount);
203
+ returns (uint256[] memory tokenIds, uint256 leftoverAmount, uint256 restrictedCost);
203
204
 
204
205
  /// @notice Record reserve 721 minting for the provided tier ID.
205
206
  /// @param tierId The ID of the tier to mint reserves from.
@@ -17,6 +17,7 @@ pragma solidity ^0.8.0;
17
17
  /// on-demand.
18
18
  /// @custom:member cannotBeRemoved A boolean indicating whether attempts to remove this tier will revert.
19
19
  /// @custom:member cannotIncreaseDiscountPercent If the tier cannot have its discount increased.
20
+ /// @custom:member cantBuyWithCredits If true, this tier cannot be purchased using accumulated pay credits.
20
21
  /// @custom:member transfersPausable A boolean indicating whether transfers for NFTs in tier can be paused.
21
22
  /// @custom:member splitPercent The percentage of the tier's price that gets routed to the project's split group when
22
23
  /// an NFT from this tier is minted. Out of `JBConstants.SPLITS_TOTAL_PERCENT`.
@@ -39,6 +40,7 @@ struct JB721Tier {
39
40
  bool transfersPausable;
40
41
  bool cannotBeRemoved;
41
42
  bool cannotIncreaseDiscountPercent;
43
+ bool cantBuyWithCredits;
42
44
  uint32 splitPercent;
43
45
  string resolvedUri;
44
46
  }
@@ -26,6 +26,8 @@ import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
26
26
  /// power. If `useVotingUnits` is false, voting power is based on the tier's price.
27
27
  /// @custom:member cannotBeRemoved If the tier cannot be removed once added.
28
28
  /// @custom:member cannotIncreaseDiscount If the tier cannot have its discount increased.
29
+ /// @custom:member cantBuyWithCredits If true, this tier cannot be purchased using accumulated pay credits. Only fresh
30
+ /// payment value counts toward this tier's price.
29
31
  /// @custom:member splitPercent The percentage of the tier's price that gets routed to the tier's split group when
30
32
  /// an NFT from this tier is minted. Out of `JBConstants.SPLITS_TOTAL_PERCENT`.
31
33
  /// @custom:member splits The splits to use for this tier's split group. These define where the split portion of the
@@ -47,6 +49,7 @@ struct JB721TierConfig {
47
49
  bool useVotingUnits;
48
50
  bool cannotBeRemoved;
49
51
  bool cannotIncreaseDiscountPercent;
52
+ bool cantBuyWithCredits;
50
53
  uint32 splitPercent;
51
54
  JBSplit[] splits;
52
55
  }
@@ -12,7 +12,7 @@ pragma solidity ^0.8.0;
12
12
  /// tier. With a `reserveFrequency` of 5, an extra NFT will be minted for the `reserveBeneficiary` for every 5 NFTs
13
13
  /// purchased.
14
14
  /// @custom:member packedBools Packed boolean flags: allowOwnerMint, transfersPausable, useVotingUnits,
15
- /// cannotBeRemoved, cannotIncreaseDiscountPercent.
15
+ /// cannotBeRemoved, cannotIncreaseDiscountPercent, cantBuyWithCredits.
16
16
  // forge-lint: disable-next-line(pascal-case-struct)
17
17
  struct JBStored721Tier {
18
18
  uint104 price;
@@ -86,6 +86,7 @@ contract NFTHookAttacks is UnitTestSetup {
86
86
  transfersPausable: false,
87
87
  cannotBeRemoved: false,
88
88
  cannotIncreaseDiscountPercent: false,
89
+ cantBuyWithCredits: false,
89
90
  useVotingUnits: false,
90
91
  splitPercent: 0,
91
92
  splits: new JBSplit[](0)
@@ -373,6 +374,7 @@ contract NFTHookAttacks is UnitTestSetup {
373
374
  transfersPausable: false,
374
375
  cannotBeRemoved: false,
375
376
  cannotIncreaseDiscountPercent: false,
377
+ cantBuyWithCredits: false,
376
378
  useVotingUnits: false,
377
379
  splitPercent: 0,
378
380
  splits: new JBSplit[](0)
@@ -802,6 +802,7 @@ contract Test_TiersHook_E2E is TestBaseWorkflow {
802
802
  useVotingUnits: false,
803
803
  cannotBeRemoved: false,
804
804
  cannotIncreaseDiscountPercent: false,
805
+ cantBuyWithCredits: false,
805
806
  splitPercent: 0,
806
807
  splits: new JBSplit[](0)
807
808
  });
@@ -894,6 +895,7 @@ contract Test_TiersHook_E2E is TestBaseWorkflow {
894
895
  useVotingUnits: false,
895
896
  cannotBeRemoved: false,
896
897
  cannotIncreaseDiscountPercent: false,
898
+ cantBuyWithCredits: false,
897
899
  splitPercent: 0,
898
900
  splits: new JBSplit[](0)
899
901
  });
package/test/Fork.t.sol CHANGED
@@ -364,6 +364,7 @@ contract Fork_721Hook_Test is Test {
364
364
  useVotingUnits: false,
365
365
  cannotBeRemoved: false,
366
366
  cannotIncreaseDiscountPercent: false,
367
+ cantBuyWithCredits: false,
367
368
  splitPercent: 0,
368
369
  splits: new JBSplit[](0)
369
370
  });
@@ -794,6 +795,7 @@ contract Fork_721Hook_Test is Test {
794
795
  useVotingUnits: false,
795
796
  cannotBeRemoved: false,
796
797
  cannotIncreaseDiscountPercent: false,
798
+ cantBuyWithCredits: false,
797
799
  splitPercent: 0,
798
800
  splits: new JBSplit[](0)
799
801
  });
@@ -826,6 +828,7 @@ contract Fork_721Hook_Test is Test {
826
828
  useVotingUnits: false,
827
829
  cannotBeRemoved: false,
828
830
  cannotIncreaseDiscountPercent: false,
831
+ cantBuyWithCredits: false,
829
832
  splitPercent: 0,
830
833
  splits: new JBSplit[](0)
831
834
  });
@@ -1133,6 +1136,7 @@ contract Fork_721Hook_Test is Test {
1133
1136
  useVotingUnits: false,
1134
1137
  cannotBeRemoved: false,
1135
1138
  cannotIncreaseDiscountPercent: false,
1139
+ cantBuyWithCredits: false,
1136
1140
  splitPercent: 0,
1137
1141
  splits: new JBSplit[](0)
1138
1142
  });
@@ -1526,6 +1530,7 @@ contract Fork_721Hook_Test is Test {
1526
1530
  useVotingUnits: false,
1527
1531
  cannotBeRemoved: false,
1528
1532
  cannotIncreaseDiscountPercent: false,
1533
+ cantBuyWithCredits: false,
1529
1534
  splitPercent: 0,
1530
1535
  splits: new JBSplit[](0)
1531
1536
  });
@@ -1772,6 +1777,7 @@ contract Fork_721Hook_Test is Test {
1772
1777
  useVotingUnits: false,
1773
1778
  cannotBeRemoved: false,
1774
1779
  cannotIncreaseDiscountPercent: false,
1780
+ cantBuyWithCredits: false,
1775
1781
  splitPercent: 0,
1776
1782
  splits: new JBSplit[](0)
1777
1783
  });
@@ -2047,6 +2053,7 @@ contract Fork_721Hook_Test is Test {
2047
2053
  useVotingUnits: false,
2048
2054
  cannotBeRemoved: false,
2049
2055
  cannotIncreaseDiscountPercent: false,
2056
+ cantBuyWithCredits: false,
2050
2057
  splitPercent: splitPct,
2051
2058
  splits: splits
2052
2059
  });
@@ -455,6 +455,7 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
455
455
  transfersPausable: false,
456
456
  cannotBeRemoved: false,
457
457
  cannotIncreaseDiscountPercent: false,
458
+ cantBuyWithCredits: false,
458
459
  useVotingUnits: false,
459
460
  splitPercent: 0,
460
461
  splits: new JBSplit[](0)
@@ -508,6 +509,7 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
508
509
  transfersPausable: false,
509
510
  cannotBeRemoved: false,
510
511
  cannotIncreaseDiscountPercent: false,
512
+ cantBuyWithCredits: false,
511
513
  useVotingUnits: false,
512
514
  splitPercent: 0,
513
515
  splits: new JBSplit[](0)
@@ -563,6 +565,7 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
563
565
  transfersPausable: false,
564
566
  cannotBeRemoved: false,
565
567
  cannotIncreaseDiscountPercent: false,
568
+ cantBuyWithCredits: false,
566
569
  useVotingUnits: false,
567
570
  splitPercent: 0,
568
571
  splits: new JBSplit[](0)
@@ -664,6 +667,7 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
664
667
  transfersPausable: false,
665
668
  cannotBeRemoved: false,
666
669
  cannotIncreaseDiscountPercent: false,
670
+ cantBuyWithCredits: false,
667
671
  useVotingUnits: false,
668
672
  splitPercent: 0,
669
673
  splits: new JBSplit[](0)
@@ -713,6 +717,7 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
713
717
  transfersPausable: false,
714
718
  cannotBeRemoved: false,
715
719
  cannotIncreaseDiscountPercent: false,
720
+ cantBuyWithCredits: false,
716
721
  useVotingUnits: false,
717
722
  splitPercent: 0,
718
723
  splits: new JBSplit[](0)
@@ -774,6 +779,7 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
774
779
  transfersPausable: false,
775
780
  cannotBeRemoved: false,
776
781
  cannotIncreaseDiscountPercent: false,
782
+ cantBuyWithCredits: false,
777
783
  useVotingUnits: false,
778
784
  splitPercent: 0,
779
785
  splits: new JBSplit[](0)
@@ -846,6 +852,7 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
846
852
  transfersPausable: false,
847
853
  cannotBeRemoved: false,
848
854
  cannotIncreaseDiscountPercent: false,
855
+ cantBuyWithCredits: false,
849
856
  useVotingUnits: false,
850
857
  splitPercent: 0,
851
858
  splits: new JBSplit[](0)
@@ -1041,6 +1048,7 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
1041
1048
  transfersPausable: false,
1042
1049
  cannotBeRemoved: false,
1043
1050
  cannotIncreaseDiscountPercent: false,
1051
+ cantBuyWithCredits: false,
1044
1052
  useVotingUnits: false,
1045
1053
  splitPercent: 0,
1046
1054
  splits: new JBSplit[](0)
@@ -281,7 +281,7 @@ contract TestVotingUnitsLifecycle is UnitTestSetup {
281
281
  reserveFrequency: uint16(0),
282
282
  category: uint24(100),
283
283
  discountPercent: uint8(0),
284
- packedBools: testHook.test_store().ForTest_packBools(true, false, false, false, false),
284
+ packedBools: testHook.test_store().ForTest_packBools(true, false, false, false, false, false),
285
285
  splitPercent: 0
286
286
  })
287
287
  );
@@ -123,6 +123,7 @@ contract CodexPayCreditsBypassTierSplits is UnitTestSetup {
123
123
  transfersPausable: false,
124
124
  cannotBeRemoved: false,
125
125
  cannotIncreaseDiscountPercent: false,
126
+ cantBuyWithCredits: false,
126
127
  useVotingUnits: false,
127
128
  splitPercent: 1_000_000_000,
128
129
  splits: new JBSplit[](0)
@@ -126,6 +126,7 @@ contract CodexSplitCreditsMismatch is UnitTestSetup {
126
126
  transfersPausable: false,
127
127
  cannotBeRemoved: false,
128
128
  cannotIncreaseDiscountPercent: false,
129
+ cantBuyWithCredits: false,
129
130
  useVotingUnits: false,
130
131
  splitPercent: 1_000_000_000,
131
132
  splits: new JBSplit[](0)
@@ -355,6 +355,7 @@ contract ERC20CashOutFork is Test {
355
355
  useVotingUnits: false,
356
356
  cannotBeRemoved: false,
357
357
  cannotIncreaseDiscountPercent: false,
358
+ cantBuyWithCredits: false,
358
359
  splitPercent: 0,
359
360
  splits: new JBSplit[](0)
360
361
  });
@@ -440,6 +441,7 @@ contract ERC20CashOutFork is Test {
440
441
  useVotingUnits: false,
441
442
  cannotBeRemoved: false,
442
443
  cannotIncreaseDiscountPercent: false,
444
+ cantBuyWithCredits: false,
443
445
  splitPercent: 0,
444
446
  splits: new JBSplit[](0)
445
447
  });
@@ -526,6 +528,7 @@ contract ERC20CashOutFork is Test {
526
528
  useVotingUnits: false,
527
529
  cannotBeRemoved: false,
528
530
  cannotIncreaseDiscountPercent: false,
531
+ cantBuyWithCredits: false,
529
532
  splitPercent: 0,
530
533
  splits: new JBSplit[](0)
531
534
  });
@@ -545,6 +548,7 @@ contract ERC20CashOutFork is Test {
545
548
  useVotingUnits: false,
546
549
  cannotBeRemoved: false,
547
550
  cannotIncreaseDiscountPercent: false,
551
+ cantBuyWithCredits: false,
548
552
  splitPercent: 0,
549
553
  splits: new JBSplit[](0)
550
554
  });
@@ -408,6 +408,7 @@ contract ERC20TierSplitFork is Test {
408
408
  useVotingUnits: false,
409
409
  cannotBeRemoved: false,
410
410
  cannotIncreaseDiscountPercent: false,
411
+ cantBuyWithCredits: false,
411
412
  splitPercent: 300_000_000, // 30%
412
413
  splits: splits
413
414
  });
@@ -477,6 +478,7 @@ contract ERC20TierSplitFork is Test {
477
478
  useVotingUnits: false,
478
479
  cannotBeRemoved: false,
479
480
  cannotIncreaseDiscountPercent: false,
481
+ cantBuyWithCredits: false,
480
482
  splitPercent: 300_000_000, // 30%
481
483
  splits: splits
482
484
  });
@@ -544,6 +546,7 @@ contract ERC20TierSplitFork is Test {
544
546
  useVotingUnits: false,
545
547
  cannotBeRemoved: false,
546
548
  cannotIncreaseDiscountPercent: false,
549
+ cantBuyWithCredits: false,
547
550
  splitPercent: 500_000_000, // 50%
548
551
  splits: splits
549
552
  });
@@ -355,6 +355,7 @@ contract IssueTokensForSplitsFork is Test {
355
355
  useVotingUnits: false,
356
356
  cannotBeRemoved: false,
357
357
  cannotIncreaseDiscountPercent: false,
358
+ cantBuyWithCredits: false,
358
359
  splitPercent: splitPercent,
359
360
  splits: splits
360
361
  });
@@ -129,7 +129,7 @@ contract TierLifecycleHandler is Test {
129
129
  tierIds[0] = uint16(tierId);
130
130
 
131
131
  vm.prank(hookAddress);
132
- try store.recordMint(tierPrice, tierIds, false) returns (uint256[] memory tokenIds, uint256) {
132
+ try store.recordMint(tierPrice, tierIds, false) returns (uint256[] memory tokenIds, uint256, uint256) {
133
133
  // Track minted tokens
134
134
  for (uint256 i = 0; i < tokenIds.length; i++) {
135
135
  _actorTokenIds[actor].push(tokenIds[i]);
@@ -195,6 +195,7 @@ contract TierLifecycleHandler is Test {
195
195
  useVotingUnits: false,
196
196
  cannotBeRemoved: false,
197
197
  cannotIncreaseDiscountPercent: false,
198
+ cantBuyWithCredits: false,
198
199
  splitPercent: 0,
199
200
  splits: new JBSplit[](0)
200
201
  });
@@ -268,7 +269,7 @@ contract TierLifecycleHandler is Test {
268
269
  tierIds[0] = uint16(tierId);
269
270
 
270
271
  vm.prank(hookAddress);
271
- try store.recordMint(0, tierIds, true) returns (uint256[] memory tokenIds, uint256) {
272
+ try store.recordMint(0, tierIds, true) returns (uint256[] memory tokenIds, uint256, uint256) {
272
273
  address actor = _getActor(seed);
273
274
  for (uint256 i = 0; i < tokenIds.length; i++) {
274
275
  _actorTokenIds[actor].push(tokenIds[i]);
@@ -65,6 +65,7 @@ contract TierStoreHandler is CommonBase, StdCheats, StdUtils {
65
65
  useVotingUnits: false,
66
66
  cannotBeRemoved: false,
67
67
  cannotIncreaseDiscountPercent: false,
68
+ cantBuyWithCredits: false,
68
69
  splitPercent: 0,
69
70
  splits: new JBSplit[](0)
70
71
  });
@@ -122,7 +123,7 @@ contract TierStoreHandler is CommonBase, StdCheats, StdUtils {
122
123
 
123
124
  /// @dev External wrapper for calldata.
124
125
  function _doMint(uint256 amount, uint16[] calldata tierIds) external returns (uint256[] memory tokenIds) {
125
- (tokenIds,) = STORE.recordMint(amount, tierIds, true);
126
+ (tokenIds,,) = STORE.recordMint(amount, tierIds, true);
126
127
  }
127
128
 
128
129
  /// @notice Burn a minted token.
@@ -125,6 +125,7 @@ contract Test_ProjectDeployerRulesets is UnitTestSetup {
125
125
  useVotingUnits: true,
126
126
  cannotBeRemoved: false,
127
127
  cannotIncreaseDiscountPercent: false,
128
+ cantBuyWithCredits: false,
128
129
  splitPercent: 0,
129
130
  splits: new JBSplit[](0)
130
131
  });
@@ -475,6 +475,7 @@ contract Test_AuditFixes_Unit is UnitTestSetup {
475
475
  useVotingUnits: false,
476
476
  cannotBeRemoved: false,
477
477
  cannotIncreaseDiscountPercent: false,
478
+ cantBuyWithCredits: false,
478
479
  splitPercent: 0,
479
480
  splits: new JBSplit[](0)
480
481
  });
@@ -493,6 +494,7 @@ contract Test_AuditFixes_Unit is UnitTestSetup {
493
494
  useVotingUnits: false,
494
495
  cannotBeRemoved: false,
495
496
  cannotIncreaseDiscountPercent: false,
497
+ cantBuyWithCredits: false,
496
498
  splitPercent: 0,
497
499
  splits: new JBSplit[](0)
498
500
  });
@@ -511,6 +513,7 @@ contract Test_AuditFixes_Unit is UnitTestSetup {
511
513
  useVotingUnits: false,
512
514
  cannotBeRemoved: false,
513
515
  cannotIncreaseDiscountPercent: false,
516
+ cantBuyWithCredits: false,
514
517
  splitPercent: 0,
515
518
  splits: new JBSplit[](0)
516
519
  });
@@ -579,6 +582,7 @@ contract Test_AuditFixes_Unit is UnitTestSetup {
579
582
  useVotingUnits: false,
580
583
  cannotBeRemoved: false,
581
584
  cannotIncreaseDiscountPercent: false,
585
+ cantBuyWithCredits: false,
582
586
  splitPercent: 0,
583
587
  splits: new JBSplit[](0)
584
588
  });
@@ -551,6 +551,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
551
551
  useVotingUnits: true,
552
552
  cannotBeRemoved: false,
553
553
  cannotIncreaseDiscountPercent: false,
554
+ cantBuyWithCredits: false,
554
555
  splitPercent: 0,
555
556
  splits: new JBSplit[](0)
556
557
  });
@@ -570,6 +571,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
570
571
  transfersPausable: tierConfigs[i].transfersPausable,
571
572
  cannotBeRemoved: tierConfigs[i].cannotBeRemoved,
572
573
  cannotIncreaseDiscountPercent: tierConfigs[i].cannotIncreaseDiscountPercent,
574
+ cantBuyWithCredits: tierConfigs[i].cantBuyWithCredits,
573
575
  splitPercent: 0,
574
576
  resolvedUri: ""
575
577
  });
@@ -684,6 +686,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
684
686
  useVotingUnits: true,
685
687
  cannotBeRemoved: false,
686
688
  cannotIncreaseDiscountPercent: false,
689
+ cantBuyWithCredits: false,
687
690
  splitPercent: 0,
688
691
  splits: new JBSplit[](0)
689
692
  });
@@ -703,6 +706,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
703
706
  transfersPausable: tierConfigs[i].transfersPausable,
704
707
  cannotBeRemoved: tierConfigs[i].cannotBeRemoved,
705
708
  cannotIncreaseDiscountPercent: tierConfigs[i].cannotIncreaseDiscountPercent,
709
+ cantBuyWithCredits: tierConfigs[i].cantBuyWithCredits,
706
710
  splitPercent: 0,
707
711
  resolvedUri: ""
708
712
  });
@@ -753,6 +757,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
753
757
  useVotingUnits: true,
754
758
  cannotBeRemoved: false,
755
759
  cannotIncreaseDiscountPercent: false,
760
+ cantBuyWithCredits: false,
756
761
  splitPercent: 0,
757
762
  splits: new JBSplit[](0)
758
763
  });
@@ -772,6 +777,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
772
777
  transfersPausable: tierConfigsRemaining[arrayIndex].transfersPausable,
773
778
  cannotBeRemoved: tierConfigsRemaining[arrayIndex].cannotBeRemoved,
774
779
  cannotIncreaseDiscountPercent: tierConfigsRemaining[arrayIndex].cannotIncreaseDiscountPercent,
780
+ cantBuyWithCredits: tierConfigsRemaining[arrayIndex].cantBuyWithCredits,
775
781
  splitPercent: 0,
776
782
  resolvedUri: ""
777
783
  });
@@ -804,6 +810,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
804
810
  useVotingUnits: true,
805
811
  cannotBeRemoved: false,
806
812
  cannotIncreaseDiscountPercent: false,
813
+ cantBuyWithCredits: false,
807
814
  splitPercent: 0,
808
815
  splits: new JBSplit[](0)
809
816
  });
@@ -822,6 +829,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
822
829
  transfersPausable: tierConfigsToAdd[i].transfersPausable,
823
830
  cannotBeRemoved: tierConfigsToAdd[i].cannotBeRemoved,
824
831
  cannotIncreaseDiscountPercent: tierConfigsToAdd[i].cannotIncreaseDiscountPercent,
832
+ cantBuyWithCredits: tierConfigsToAdd[i].cantBuyWithCredits,
825
833
  splitPercent: 0,
826
834
  resolvedUri: ""
827
835
  });
@@ -880,6 +888,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
880
888
  useVotingUnits: true,
881
889
  cannotBeRemoved: false,
882
890
  cannotIncreaseDiscountPercent: false,
891
+ cantBuyWithCredits: false,
883
892
  splitPercent: 0,
884
893
  splits: new JBSplit[](0)
885
894
  });
@@ -899,6 +908,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
899
908
  transfersPausable: tierConfigs[i].transfersPausable,
900
909
  cannotBeRemoved: tierConfigs[i].cannotBeRemoved,
901
910
  cannotIncreaseDiscountPercent: tierConfigs[i].cannotIncreaseDiscountPercent,
911
+ cantBuyWithCredits: tierConfigs[i].cantBuyWithCredits,
902
912
  splitPercent: 0,
903
913
  resolvedUri: ""
904
914
  });
@@ -948,6 +958,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
948
958
  useVotingUnits: true,
949
959
  cannotBeRemoved: false,
950
960
  cannotIncreaseDiscountPercent: false,
961
+ cantBuyWithCredits: false,
951
962
  splitPercent: 0,
952
963
  splits: new JBSplit[](0)
953
964
  });
@@ -966,6 +977,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
966
977
  transfersPausable: tierConfigsToAdd[i].transfersPausable,
967
978
  cannotBeRemoved: tierConfigsToAdd[i].cannotBeRemoved,
968
979
  cannotIncreaseDiscountPercent: tierConfigsToAdd[i].cannotIncreaseDiscountPercent,
980
+ cantBuyWithCredits: tierConfigsToAdd[i].cantBuyWithCredits,
969
981
  splitPercent: 0,
970
982
  resolvedUri: ""
971
983
  });
@@ -1008,6 +1020,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1008
1020
  useVotingUnits: true,
1009
1021
  cannotBeRemoved: false,
1010
1022
  cannotIncreaseDiscountPercent: false,
1023
+ cantBuyWithCredits: false,
1011
1024
  splitPercent: 0,
1012
1025
  splits: new JBSplit[](0)
1013
1026
  });
@@ -1027,6 +1040,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1027
1040
  transfersPausable: tierConfigs[i].transfersPausable,
1028
1041
  cannotBeRemoved: tierConfigs[i].cannotBeRemoved,
1029
1042
  cannotIncreaseDiscountPercent: tierConfigs[i].cannotIncreaseDiscountPercent,
1043
+ cantBuyWithCredits: tierConfigs[i].cantBuyWithCredits,
1030
1044
  splitPercent: 0,
1031
1045
  resolvedUri: ""
1032
1046
  });
@@ -1075,6 +1089,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1075
1089
  useVotingUnits: true,
1076
1090
  cannotBeRemoved: false,
1077
1091
  cannotIncreaseDiscountPercent: false,
1092
+ cantBuyWithCredits: false,
1078
1093
  splitPercent: 0,
1079
1094
  splits: new JBSplit[](0)
1080
1095
  });
@@ -1093,6 +1108,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1093
1108
  transfersPausable: tierConfigsToAdd[i].transfersPausable,
1094
1109
  cannotBeRemoved: tierConfigsToAdd[i].cannotBeRemoved,
1095
1110
  cannotIncreaseDiscountPercent: tierConfigsToAdd[i].cannotIncreaseDiscountPercent,
1111
+ cantBuyWithCredits: tierConfigsToAdd[i].cantBuyWithCredits,
1096
1112
  splitPercent: 0,
1097
1113
  resolvedUri: ""
1098
1114
  });
@@ -1130,6 +1146,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1130
1146
  useVotingUnits: true,
1131
1147
  cannotBeRemoved: true,
1132
1148
  cannotIncreaseDiscountPercent: false,
1149
+ cantBuyWithCredits: false,
1133
1150
  splitPercent: 0,
1134
1151
  splits: new JBSplit[](0)
1135
1152
  });
@@ -1148,6 +1165,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1148
1165
  useVotingUnits: true,
1149
1166
  cannotBeRemoved: false,
1150
1167
  cannotIncreaseDiscountPercent: false,
1168
+ cantBuyWithCredits: false,
1151
1169
  splitPercent: 0,
1152
1170
  splits: new JBSplit[](0)
1153
1171
  });
@@ -1204,6 +1222,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1204
1222
  useVotingUnits: true,
1205
1223
  cannotBeRemoved: false,
1206
1224
  cannotIncreaseDiscountPercent: false,
1225
+ cantBuyWithCredits: false,
1207
1226
  splitPercent: 0,
1208
1227
  splits: new JBSplit[](0)
1209
1228
  });
@@ -1223,6 +1242,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1223
1242
  transfersPausable: tierConfigs[i].transfersPausable,
1224
1243
  cannotBeRemoved: tierConfigs[i].cannotBeRemoved,
1225
1244
  cannotIncreaseDiscountPercent: tierConfigs[i].cannotIncreaseDiscountPercent,
1245
+ cantBuyWithCredits: tierConfigs[i].cantBuyWithCredits,
1226
1246
  splitPercent: 0,
1227
1247
  resolvedUri: ""
1228
1248
  });
@@ -1270,6 +1290,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1270
1290
  useVotingUnits: false,
1271
1291
  cannotBeRemoved: false,
1272
1292
  cannotIncreaseDiscountPercent: false,
1293
+ cantBuyWithCredits: false,
1273
1294
  splitPercent: 0,
1274
1295
  splits: new JBSplit[](0)
1275
1296
  });
@@ -1288,6 +1309,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1288
1309
  transfersPausable: tierConfigsToAdd[i].transfersPausable,
1289
1310
  cannotBeRemoved: tierConfigsToAdd[i].cannotBeRemoved,
1290
1311
  cannotIncreaseDiscountPercent: tierConfigsToAdd[i].cannotIncreaseDiscountPercent,
1312
+ cantBuyWithCredits: tierConfigsToAdd[i].cantBuyWithCredits,
1291
1313
  splitPercent: 0,
1292
1314
  resolvedUri: ""
1293
1315
  });
@@ -1332,6 +1354,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1332
1354
  cannotBeRemoved: false,
1333
1355
  useVotingUnits: true,
1334
1356
  cannotIncreaseDiscountPercent: false,
1357
+ cantBuyWithCredits: false,
1335
1358
  splitPercent: 0,
1336
1359
  splits: new JBSplit[](0)
1337
1360
  });
@@ -1375,6 +1398,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1375
1398
  useVotingUnits: false,
1376
1399
  cannotBeRemoved: false,
1377
1400
  cannotIncreaseDiscountPercent: false,
1401
+ cantBuyWithCredits: false,
1378
1402
  splitPercent: 0,
1379
1403
  splits: new JBSplit[](0)
1380
1404
  });
@@ -1424,6 +1448,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1424
1448
  useVotingUnits: false, // <-- If false, voting power is based on tier price
1425
1449
  cannotBeRemoved: false,
1426
1450
  cannotIncreaseDiscountPercent: false,
1451
+ cantBuyWithCredits: false,
1427
1452
  splitPercent: 0,
1428
1453
  splits: new JBSplit[](0)
1429
1454
  });
@@ -1467,6 +1492,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1467
1492
  useVotingUnits: true,
1468
1493
  cannotBeRemoved: false,
1469
1494
  cannotIncreaseDiscountPercent: false,
1495
+ cantBuyWithCredits: false,
1470
1496
  splitPercent: 0,
1471
1497
  splits: new JBSplit[](0)
1472
1498
  });
@@ -1516,6 +1542,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1516
1542
  useVotingUnits: true, // <-- If false, voting power is based on tier price
1517
1543
  cannotBeRemoved: false,
1518
1544
  cannotIncreaseDiscountPercent: false,
1545
+ cantBuyWithCredits: false,
1519
1546
  splitPercent: 0,
1520
1547
  splits: new JBSplit[](0)
1521
1548
  });
@@ -1591,6 +1618,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1591
1618
  useVotingUnits: false,
1592
1619
  cannotBeRemoved: false,
1593
1620
  cannotIncreaseDiscountPercent: false,
1621
+ cantBuyWithCredits: false,
1594
1622
  splitPercent: 0,
1595
1623
  splits: new JBSplit[](0)
1596
1624
  });
@@ -1610,6 +1638,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1610
1638
  transfersPausable: tierConfigs[i].transfersPausable,
1611
1639
  cannotBeRemoved: tierConfigs[i].cannotBeRemoved,
1612
1640
  cannotIncreaseDiscountPercent: tierConfigs[i].cannotIncreaseDiscountPercent,
1641
+ cantBuyWithCredits: tierConfigs[i].cantBuyWithCredits,
1613
1642
  splitPercent: 0,
1614
1643
  resolvedUri: ""
1615
1644
  });
@@ -1720,6 +1749,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1720
1749
  useVotingUnits: true,
1721
1750
  cannotBeRemoved: true,
1722
1751
  cannotIncreaseDiscountPercent: true,
1752
+ cantBuyWithCredits: false,
1723
1753
  splitPercent: 0,
1724
1754
  splits: new JBSplit[](0)
1725
1755
  });
@@ -1775,6 +1805,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1775
1805
  useVotingUnits: true,
1776
1806
  cannotBeRemoved: true,
1777
1807
  cannotIncreaseDiscountPercent: true,
1808
+ cantBuyWithCredits: false,
1778
1809
  splitPercent: 0,
1779
1810
  splits: new JBSplit[](0)
1780
1811
  });
@@ -1793,6 +1824,7 @@ contract Test_adjustTier_Unit is UnitTestSetup {
1793
1824
  useVotingUnits: true,
1794
1825
  cannotBeRemoved: true,
1795
1826
  cannotIncreaseDiscountPercent: false,
1827
+ cantBuyWithCredits: false,
1796
1828
  splitPercent: 0,
1797
1829
  splits: new JBSplit[](0)
1798
1830
  });
@@ -46,16 +46,17 @@ contract Test_Getters_Constructor_Unit is UnitTestSetup {
46
46
  assertEq(decimals2, uint256(decimals));
47
47
  }
48
48
 
49
- function test_bools_doesPackingAndUnpackingWork(bool a, bool b, bool c, bool d, bool e) public {
49
+ function test_bools_doesPackingAndUnpackingWork(bool a, bool b, bool c, bool d, bool e, bool f) public {
50
50
  ForTest_JB721TiersHookStore store = new ForTest_JB721TiersHookStore();
51
- uint8 packed = store.ForTest_packBools(a, b, c, d, e);
52
- (bool a2, bool b2, bool c2, bool d2, bool e2) = store.ForTest_unpackBools(packed);
51
+ uint8 packed = store.ForTest_packBools(a, b, c, d, e, f);
52
+ (bool a2, bool b2, bool c2, bool d2, bool e2, bool f2) = store.ForTest_unpackBools(packed);
53
53
  // Check: do the packed values match the unpacked values?
54
54
  assertEq(a, a2);
55
55
  assertEq(b, b2);
56
56
  assertEq(c, c2);
57
57
  assertEq(d, d2);
58
58
  assertEq(e, e2);
59
+ assertEq(f, f2);
59
60
  }
60
61
 
61
62
  function test_tiersOf_returnsAllTiersWithResolver(uint256 numberOfTiers) public {
@@ -154,6 +155,7 @@ contract Test_Getters_Constructor_Unit is UnitTestSetup {
154
155
  transfersPausable: false,
155
156
  cannotBeRemoved: false,
156
157
  cannotIncreaseDiscountPercent: false,
158
+ cantBuyWithCredits: false,
157
159
  splitPercent: 0,
158
160
  resolvedUri: ""
159
161
  })
@@ -181,7 +183,7 @@ contract Test_Getters_Constructor_Unit is UnitTestSetup {
181
183
  reserveFrequency: uint16(0),
182
184
  category: uint24(100),
183
185
  discountPercent: uint8(0),
184
- packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false),
186
+ packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false, false),
185
187
  splitPercent: 0
186
188
  })
187
189
  );
@@ -238,7 +240,7 @@ contract Test_Getters_Constructor_Unit is UnitTestSetup {
238
240
  reserveFrequency: uint16(reserveFrequency),
239
241
  category: uint24(100),
240
242
  discountPercent: uint8(0),
241
- packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false),
243
+ packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false, false),
242
244
  splitPercent: 0
243
245
  })
244
246
  );
@@ -280,7 +282,7 @@ contract Test_Getters_Constructor_Unit is UnitTestSetup {
280
282
  reserveFrequency: uint16(100),
281
283
  category: uint24(100),
282
284
  discountPercent: uint8(0),
283
- packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false),
285
+ packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false, false),
284
286
  splitPercent: 0
285
287
  })
286
288
  );
@@ -441,7 +443,7 @@ contract Test_Getters_Constructor_Unit is UnitTestSetup {
441
443
  reserveFrequency: uint16(0),
442
444
  category: uint24(100),
443
445
  discountPercent: uint8(0),
444
- packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false),
446
+ packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false, false),
445
447
  splitPercent: 0
446
448
  })
447
449
  );
@@ -550,6 +552,7 @@ contract Test_Getters_Constructor_Unit is UnitTestSetup {
550
552
  useVotingUnits: true,
551
553
  cannotBeRemoved: false,
552
554
  cannotIncreaseDiscountPercent: false,
555
+ cantBuyWithCredits: false,
553
556
  splitPercent: 0,
554
557
  splits: new JBSplit[](0)
555
558
  });
@@ -36,7 +36,7 @@ contract Test_mintFor_mintReservesFor_Unit is UnitTestSetup {
36
36
  reserveFrequency: uint16(reserveFrequency),
37
37
  category: uint24(100),
38
38
  discountPercent: uint8(0),
39
- packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false),
39
+ packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false, false),
40
40
  splitPercent: 0
41
41
  })
42
42
  );
@@ -86,7 +86,7 @@ contract Test_mintFor_mintReservesFor_Unit is UnitTestSetup {
86
86
  reserveFrequency: uint16(reserveFrequency),
87
87
  category: uint24(100),
88
88
  discountPercent: uint8(0),
89
- packedBools: hook.test_store().ForTest_packBools(true, false, true, false, false),
89
+ packedBools: hook.test_store().ForTest_packBools(true, false, true, false, false, false),
90
90
  splitPercent: 0
91
91
  })
92
92
  );
@@ -193,7 +193,7 @@ contract Test_mintFor_mintReservesFor_Unit is UnitTestSetup {
193
193
  reserveFrequency: uint16(reserveFrequency),
194
194
  category: uint24(100),
195
195
  discountPercent: uint8(0),
196
- packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false),
196
+ packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false, false),
197
197
  splitPercent: 0
198
198
  })
199
199
  );
@@ -295,7 +295,7 @@ contract Test_mintFor_mintReservesFor_Unit is UnitTestSetup {
295
295
  reserveFrequency: uint16(reserveFrequency),
296
296
  category: uint24(100),
297
297
  discountPercent: uint8(0),
298
- packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false),
298
+ packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false, false),
299
299
  splitPercent: 0
300
300
  })
301
301
  );
@@ -336,7 +336,7 @@ contract Test_mintFor_mintReservesFor_Unit is UnitTestSetup {
336
336
  reserveFrequency: uint16(reserveFrequency),
337
337
  category: uint24(100),
338
338
  discountPercent: uint8(0),
339
- packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false),
339
+ packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false, false),
340
340
  splitPercent: 0
341
341
  })
342
342
  );
@@ -387,7 +387,7 @@ contract Test_mintFor_mintReservesFor_Unit is UnitTestSetup {
387
387
  reserveFrequency: uint16(reserveFrequency),
388
388
  category: uint24(100),
389
389
  discountPercent: uint8(0),
390
- packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false),
390
+ packedBools: hook.test_store().ForTest_packBools(false, false, true, false, false, false),
391
391
  splitPercent: 0
392
392
  })
393
393
  );
@@ -28,7 +28,7 @@ contract Test_cashOut_Unit is UnitTestSetup {
28
28
  reserveFrequency: uint16(0),
29
29
  category: uint24(100),
30
30
  discountPercent: uint8(0),
31
- packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false),
31
+ packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false, false),
32
32
  splitPercent: 0
33
33
  })
34
34
  );
@@ -103,7 +103,7 @@ contract Test_cashOut_Unit is UnitTestSetup {
103
103
  reserveFrequency: uint16(0),
104
104
  category: uint24(100),
105
105
  discountPercent: uint8(0),
106
- packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false),
106
+ packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false, false),
107
107
  splitPercent: 0
108
108
  })
109
109
  );
@@ -164,7 +164,7 @@ contract Test_cashOut_Unit is UnitTestSetup {
164
164
  reserveFrequency: uint16(0),
165
165
  category: uint24(100),
166
166
  discountPercent: uint8(0),
167
- packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false),
167
+ packedBools: hook.test_store().ForTest_packBools(false, false, false, false, false, false),
168
168
  splitPercent: 0
169
169
  })
170
170
  );