@bananapus/721-hook-v6 0.0.25 → 0.0.27

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.27",
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
+ cantBeRemoved: (packed & 0x8 != 0),
555
+ cantIncreaseDiscountPercent: (packed & 0x10 != 0),
556
+ cantBuyWithCredits: (packed & 0x20 != 0),
561
557
  splitPercent: storedTier.splitPercent,
562
558
  resolvedUri: !includeResolvedUri || tokenUriResolverOf[hook] == IJB721TokenUriResolver(address(0))
563
559
  ? ""
@@ -678,15 +674,17 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
678
674
  /// @param allowOwnerMint Whether or not owner minting is allowed in new tiers.
679
675
  /// @param transfersPausable Whether or not 721 transfers can be paused.
680
676
  /// @param useVotingUnits Whether or not custom voting unit amounts are allowed in new tiers.
681
- /// @param cannotBeRemoved Whether or not attempts to remove the tier will revert.
682
- /// @param cannotIncreaseDiscountPercent Whether or not attempts to increase the discount percent will revert.
677
+ /// @param cantBeRemoved Whether or not attempts to remove the tier will revert.
678
+ /// @param cantIncreaseDiscountPercent 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
- bool cannotBeRemoved,
689
- bool cannotIncreaseDiscountPercent
685
+ bool cantBeRemoved,
686
+ bool cantIncreaseDiscountPercent,
687
+ bool cantBuyWithCredits
690
688
  )
691
689
  internal
692
690
  pure
@@ -696,18 +694,20 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
696
694
  packed := or(allowOwnerMint, packed)
697
695
  packed := or(shl(0x1, transfersPausable), packed)
698
696
  packed := or(shl(0x2, useVotingUnits), packed)
699
- packed := or(shl(0x3, cannotBeRemoved), packed)
700
- packed := or(shl(0x4, cannotIncreaseDiscountPercent), packed)
697
+ packed := or(shl(0x3, cantBeRemoved), packed)
698
+ packed := or(shl(0x4, cantIncreaseDiscountPercent), 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
- /// @param cannotBeRemoved Whether or not the tier can be removed once added.
710
- /// @param cannotIncreaseDiscountPercent Whether or not the discount percent cannot be increased.
708
+ /// @param cantBeRemoved Whether or not the tier can be removed once added.
709
+ /// @param cantIncreaseDiscountPercent 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
@@ -715,16 +715,18 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
715
715
  bool allowOwnerMint,
716
716
  bool transfersPausable,
717
717
  bool useVotingUnits,
718
- bool cannotBeRemoved,
719
- bool cannotIncreaseDiscountPercent
718
+ bool cantBeRemoved,
719
+ bool cantIncreaseDiscountPercent,
720
+ bool cantBuyWithCredits
720
721
  )
721
722
  {
722
723
  assembly {
723
724
  allowOwnerMint := iszero(iszero(and(0x1, packed)))
724
725
  transfersPausable := iszero(iszero(and(0x2, packed)))
725
726
  useVotingUnits := iszero(iszero(and(0x4, packed)))
726
- cannotBeRemoved := iszero(iszero(and(0x8, packed)))
727
- cannotIncreaseDiscountPercent := iszero(iszero(and(0x10, packed)))
727
+ cantBeRemoved := iszero(iszero(and(0x8, packed)))
728
+ cantIncreaseDiscountPercent := iszero(iszero(and(0x10, packed)))
729
+ cantBuyWithCredits := iszero(iszero(and(0x20, packed)))
728
730
  }
729
731
  }
730
732
 
@@ -906,8 +908,9 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
906
908
  allowOwnerMint: tierToAdd.allowOwnerMint,
907
909
  transfersPausable: tierToAdd.transfersPausable,
908
910
  useVotingUnits: tierToAdd.useVotingUnits,
909
- cannotBeRemoved: tierToAdd.cannotBeRemoved,
910
- cannotIncreaseDiscountPercent: tierToAdd.cannotIncreaseDiscountPercent
911
+ cantBeRemoved: tierToAdd.cantBeRemoved,
912
+ cantIncreaseDiscountPercent: tierToAdd.cantIncreaseDiscountPercent,
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,10 +1199,10 @@ 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 cantBeRemoved,,) = _unpackBools(storedTier.packedBools);
1192
1203
 
1193
1204
  // Make sure the tier can be removed.
1194
- if (cannotBeRemoved) revert JB721TiersHookStore_CantRemoveTier(tierId);
1205
+ if (cantBeRemoved) revert JB721TiersHookStore_CantRemoveTier(tierId);
1195
1206
 
1196
1207
  // Remove the tier by marking it as removed in the bitmap.
1197
1208
  _removedTiersBitmapWordOf[msg.sender].removeTier(tierId);
@@ -1217,10 +1228,10 @@ 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 cantIncreaseDiscountPercent,) = _unpackBools(storedTier.packedBools);
1221
1232
 
1222
1233
  // Make sure that increasing the discount is allowed for the tier.
1223
- if (discountPercent > storedTier.discountPercent && cannotIncreaseDiscountPercent) {
1234
+ if (discountPercent > storedTier.discountPercent && cantIncreaseDiscountPercent) {
1224
1235
  revert JB721TiersHookStore_DiscountPercentIncreaseNotAllowed(discountPercent, storedTier.discountPercent);
1225
1236
  }
1226
1237
 
@@ -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.
@@ -15,8 +15,9 @@ pragma solidity ^0.8.0;
15
15
  /// @custom:member discountPercent The discount that should be applied to the tier.
16
16
  /// @custom:member allowOwnerMint A boolean indicating whether the contract's owner can mint NFTs from this tier
17
17
  /// on-demand.
18
- /// @custom:member cannotBeRemoved A boolean indicating whether attempts to remove this tier will revert.
19
- /// @custom:member cannotIncreaseDiscountPercent If the tier cannot have its discount increased.
18
+ /// @custom:member cantBeRemoved A boolean indicating whether attempts to remove this tier will revert.
19
+ /// @custom:member cantIncreaseDiscountPercent 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`.
@@ -37,8 +38,9 @@ struct JB721Tier {
37
38
  uint8 discountPercent;
38
39
  bool allowOwnerMint;
39
40
  bool transfersPausable;
40
- bool cannotBeRemoved;
41
- bool cannotIncreaseDiscountPercent;
41
+ bool cantBeRemoved;
42
+ bool cantIncreaseDiscountPercent;
43
+ bool cantBuyWithCredits;
42
44
  uint32 splitPercent;
43
45
  string resolvedUri;
44
46
  }
@@ -24,8 +24,10 @@ import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
24
24
  /// @custom:member transfersPausable A boolean indicating whether transfers for NFTs in tier can be paused.
25
25
  /// @custom:member useVotingUnits A boolean indicating whether the `votingUnits` should be used to calculate voting
26
26
  /// power. If `useVotingUnits` is false, voting power is based on the tier's price.
27
- /// @custom:member cannotBeRemoved If the tier cannot be removed once added.
27
+ /// @custom:member cantBeRemoved 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
@@ -45,8 +47,9 @@ struct JB721TierConfig {
45
47
  bool useReserveBeneficiaryAsDefault;
46
48
  bool transfersPausable;
47
49
  bool useVotingUnits;
48
- bool cannotBeRemoved;
49
- bool cannotIncreaseDiscountPercent;
50
+ bool cantBeRemoved;
51
+ bool cantIncreaseDiscountPercent;
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
+ /// cantBeRemoved, cantIncreaseDiscountPercent, cantBuyWithCredits.
16
16
  // forge-lint: disable-next-line(pascal-case-struct)
17
17
  struct JBStored721Tier {
18
18
  uint104 price;
@@ -84,8 +84,9 @@ contract NFTHookAttacks is UnitTestSetup {
84
84
  allowOwnerMint: false,
85
85
  useReserveBeneficiaryAsDefault: false,
86
86
  transfersPausable: false,
87
- cannotBeRemoved: false,
88
- cannotIncreaseDiscountPercent: false,
87
+ cantBeRemoved: false,
88
+ cantIncreaseDiscountPercent: false,
89
+ cantBuyWithCredits: false,
89
90
  useVotingUnits: false,
90
91
  splitPercent: 0,
91
92
  splits: new JBSplit[](0)
@@ -115,7 +116,7 @@ contract NFTHookAttacks is UnitTestSetup {
115
116
  /// @notice Set discount to 100%, verify the effective price for the tier.
116
117
  function test_maxDiscountPercent_effectivePrice() public {
117
118
  defaultTierConfig.discountPercent = 0;
118
- defaultTierConfig.cannotIncreaseDiscountPercent = false;
119
+ defaultTierConfig.cantIncreaseDiscountPercent = false;
119
120
 
120
121
  JB721TiersHook targetHook = _initHookDefaultTiers(1);
121
122
 
@@ -131,12 +132,12 @@ contract NFTHookAttacks is UnitTestSetup {
131
132
  }
132
133
 
133
134
  // =========================================================================
134
- // Test 3: cannotIncreaseDiscountPercent flag enforcement
135
+ // Test 3: cantIncreaseDiscountPercent flag enforcement
135
136
  // =========================================================================
136
137
  /// @notice Try to increase discount when the flag forbids it.
137
- function test_cannotIncreaseDiscountPercent_enforcement() public {
138
+ function test_cantIncreaseDiscountPercent_enforcement() public {
138
139
  defaultTierConfig.discountPercent = 10;
139
- defaultTierConfig.cannotIncreaseDiscountPercent = true;
140
+ defaultTierConfig.cantIncreaseDiscountPercent = true;
140
141
 
141
142
  JB721TiersHook targetHook = _initHookDefaultTiers(1);
142
143
 
@@ -371,8 +372,9 @@ contract NFTHookAttacks is UnitTestSetup {
371
372
  allowOwnerMint: true,
372
373
  useReserveBeneficiaryAsDefault: false,
373
374
  transfersPausable: false,
374
- cannotBeRemoved: false,
375
- cannotIncreaseDiscountPercent: false,
375
+ cantBeRemoved: false,
376
+ cantIncreaseDiscountPercent: false,
377
+ cantBuyWithCredits: false,
376
378
  useVotingUnits: false,
377
379
  splitPercent: 0,
378
380
  splits: new JBSplit[](0)
@@ -800,8 +800,9 @@ contract Test_TiersHook_E2E is TestBaseWorkflow {
800
800
  useReserveBeneficiaryAsDefault: false,
801
801
  transfersPausable: false,
802
802
  useVotingUnits: false,
803
- cannotBeRemoved: false,
804
- cannotIncreaseDiscountPercent: false,
803
+ cantBeRemoved: false,
804
+ cantIncreaseDiscountPercent: false,
805
+ cantBuyWithCredits: false,
805
806
  splitPercent: 0,
806
807
  splits: new JBSplit[](0)
807
808
  });
@@ -892,8 +893,9 @@ contract Test_TiersHook_E2E is TestBaseWorkflow {
892
893
  useReserveBeneficiaryAsDefault: false,
893
894
  transfersPausable: false,
894
895
  useVotingUnits: false,
895
- cannotBeRemoved: false,
896
- cannotIncreaseDiscountPercent: false,
896
+ cantBeRemoved: false,
897
+ cantIncreaseDiscountPercent: false,
898
+ cantBuyWithCredits: false,
897
899
  splitPercent: 0,
898
900
  splits: new JBSplit[](0)
899
901
  });
package/test/Fork.t.sol CHANGED
@@ -362,8 +362,9 @@ contract Fork_721Hook_Test is Test {
362
362
  useReserveBeneficiaryAsDefault: false,
363
363
  transfersPausable: false,
364
364
  useVotingUnits: false,
365
- cannotBeRemoved: false,
366
- cannotIncreaseDiscountPercent: false,
365
+ cantBeRemoved: false,
366
+ cantIncreaseDiscountPercent: false,
367
+ cantBuyWithCredits: false,
367
368
  splitPercent: 0,
368
369
  splits: new JBSplit[](0)
369
370
  });
@@ -792,8 +793,9 @@ contract Fork_721Hook_Test is Test {
792
793
  useReserveBeneficiaryAsDefault: false,
793
794
  transfersPausable: false,
794
795
  useVotingUnits: false,
795
- cannotBeRemoved: false,
796
- cannotIncreaseDiscountPercent: false,
796
+ cantBeRemoved: false,
797
+ cantIncreaseDiscountPercent: false,
798
+ cantBuyWithCredits: false,
797
799
  splitPercent: 0,
798
800
  splits: new JBSplit[](0)
799
801
  });
@@ -824,8 +826,9 @@ contract Fork_721Hook_Test is Test {
824
826
  useReserveBeneficiaryAsDefault: false,
825
827
  transfersPausable: false,
826
828
  useVotingUnits: false,
827
- cannotBeRemoved: false,
828
- cannotIncreaseDiscountPercent: false,
829
+ cantBeRemoved: false,
830
+ cantIncreaseDiscountPercent: false,
831
+ cantBuyWithCredits: false,
829
832
  splitPercent: 0,
830
833
  splits: new JBSplit[](0)
831
834
  });
@@ -835,10 +838,10 @@ contract Fork_721Hook_Test is Test {
835
838
  IJB721TiersHook(hook).adjustTiers(newTiers, new uint256[](0));
836
839
  }
837
840
 
838
- /// @notice cannotBeRemoved: removing an immutable tier should revert.
839
- function test_fork_cannotBeRemoved_reverts() public {
841
+ /// @notice cantBeRemoved: removing an immutable tier should revert.
842
+ function test_fork_cantBeRemoved_reverts() public {
840
843
  JB721TierConfig[] memory tierConfigs = _makeStandardTiers(1, 10, false);
841
- tierConfigs[0].cannotBeRemoved = true;
844
+ tierConfigs[0].cantBeRemoved = true;
842
845
  JB721TiersHookFlags memory flags = _defaultFlags();
843
846
  (, address hook) = _launchProject(tierConfigs, flags, 5000, true, 0x00);
844
847
 
@@ -899,11 +902,11 @@ contract Fork_721Hook_Test is Test {
899
902
  assertEq(IERC721(hook).balanceOf(beneficiary), 1, "NFT minted for free");
900
903
  }
901
904
 
902
- /// @notice cannotIncreaseDiscountPercent: setting higher discount reverts.
905
+ /// @notice cantIncreaseDiscountPercent: setting higher discount reverts.
903
906
  function test_fork_cannotIncreaseDiscount() public {
904
907
  JB721TierConfig[] memory tierConfigs = _makeStandardTiers(1, 10, false);
905
908
  tierConfigs[0].discountPercent = 50;
906
- tierConfigs[0].cannotIncreaseDiscountPercent = true;
909
+ tierConfigs[0].cantIncreaseDiscountPercent = true;
907
910
  JB721TiersHookFlags memory flags = _defaultFlags();
908
911
  (, address hook) = _launchProject(tierConfigs, flags, 5000, true, 0x00);
909
912
 
@@ -1131,8 +1134,9 @@ contract Fork_721Hook_Test is Test {
1131
1134
  useReserveBeneficiaryAsDefault: false,
1132
1135
  transfersPausable: false,
1133
1136
  useVotingUnits: false,
1134
- cannotBeRemoved: false,
1135
- cannotIncreaseDiscountPercent: false,
1137
+ cantBeRemoved: false,
1138
+ cantIncreaseDiscountPercent: false,
1139
+ cantBuyWithCredits: false,
1136
1140
  splitPercent: 0,
1137
1141
  splits: new JBSplit[](0)
1138
1142
  });
@@ -1524,8 +1528,9 @@ contract Fork_721Hook_Test is Test {
1524
1528
  useReserveBeneficiaryAsDefault: false,
1525
1529
  transfersPausable: false,
1526
1530
  useVotingUnits: false,
1527
- cannotBeRemoved: false,
1528
- cannotIncreaseDiscountPercent: false,
1531
+ cantBeRemoved: false,
1532
+ cantIncreaseDiscountPercent: false,
1533
+ cantBuyWithCredits: false,
1529
1534
  splitPercent: 0,
1530
1535
  splits: new JBSplit[](0)
1531
1536
  });
@@ -1770,8 +1775,9 @@ contract Fork_721Hook_Test is Test {
1770
1775
  useReserveBeneficiaryAsDefault: false,
1771
1776
  transfersPausable: false,
1772
1777
  useVotingUnits: false,
1773
- cannotBeRemoved: false,
1774
- cannotIncreaseDiscountPercent: false,
1778
+ cantBeRemoved: false,
1779
+ cantIncreaseDiscountPercent: false,
1780
+ cantBuyWithCredits: false,
1775
1781
  splitPercent: 0,
1776
1782
  splits: new JBSplit[](0)
1777
1783
  });
@@ -2045,8 +2051,9 @@ contract Fork_721Hook_Test is Test {
2045
2051
  useReserveBeneficiaryAsDefault: false,
2046
2052
  transfersPausable: false,
2047
2053
  useVotingUnits: false,
2048
- cannotBeRemoved: false,
2049
- cannotIncreaseDiscountPercent: false,
2054
+ cantBeRemoved: false,
2055
+ cantIncreaseDiscountPercent: false,
2056
+ cantBuyWithCredits: false,
2050
2057
  splitPercent: splitPct,
2051
2058
  splits: splits
2052
2059
  });