@bananapus/721-hook-v6 0.0.56 → 0.0.58

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/README.md CHANGED
@@ -73,7 +73,7 @@ That split is why UI bugs, economic bugs, and deployment bugs often land in diff
73
73
  1. `test/E2E/Pay_Mint_Redeem_E2E.t.sol`
74
74
  2. `test/invariants/TierLifecycleInvariant.t.sol`
75
75
  3. `test/invariants/TieredHookStoreInvariant.t.sol`
76
- 4. `test/regression/RegressionSplitCreditsMismatch.t.sol`
76
+ 4. `test/regression/SplitCreditsMismatch.t.sol`
77
77
  5. `test/regression/ProjectDeployerRulesets.t.sol`
78
78
 
79
79
  ## Install
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/721-hook-v6",
3
- "version": "0.0.56",
3
+ "version": "0.0.58",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,8 +26,8 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@bananapus/address-registry-v6": "^0.0.26",
29
- "@bananapus/core-v6": "^0.0.60",
30
- "@bananapus/ownable-v6": "^0.0.28",
29
+ "@bananapus/core-v6": "^0.0.70",
30
+ "@bananapus/ownable-v6": "^0.0.31",
31
31
  "@bananapus/permission-ids-v6": "^0.0.27",
32
32
  "@openzeppelin/contracts": "5.6.1",
33
33
  "@prb/math": "4.1.1",
@@ -77,6 +77,7 @@ contract JB721TiersHookProjectDeployer is
77
77
  /// @param salt A salt to use for the deterministic deployment.
78
78
  /// @return projectId The ID of the newly launched project.
79
79
  /// @return hook The 721 tiers hook that was deployed for the project.
80
+ /// @dev Forwards `msg.value` to `JBProjects.createFor` to cover any configured project creation fee.
80
81
  function launchProjectFor(
81
82
  address owner,
82
83
  JBDeploy721TiersHookConfig calldata deployTiersHookConfig,
@@ -85,12 +86,13 @@ contract JB721TiersHookProjectDeployer is
85
86
  bytes32 salt
86
87
  )
87
88
  external
89
+ payable
88
90
  override
89
91
  returns (uint256 projectId, IJB721TiersHook hook)
90
92
  {
91
93
  // Reserve the project ID up front so permissionless project creations cannot invalidate hook deployment.
92
94
  IJBProjects projects = DIRECTORY.PROJECTS();
93
- projectId = projects.createFor(address(this));
95
+ projectId = projects.createFor{value: msg.value}(address(this));
94
96
 
95
97
  // Deploy the hook.
96
98
  hook = HOOK_DEPLOYER.deployHookFor({
@@ -296,7 +296,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
296
296
  // Keep a reference to the tier being iterated upon.
297
297
  JBStored721Tier memory storedTier;
298
298
 
299
- // Initialize a `JBBitmapWord` to track if whether tiers have been removed.
299
+ // Initialize a `JBBitmapWord` to track whether tiers have been removed.
300
300
  JBBitmapWord memory bitmapWord;
301
301
 
302
302
  // Keep a reference to an iterator variable to represent the category being iterated upon.
@@ -578,7 +578,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
578
578
  /// @notice Get the first tier ID from an 721 contract (when sorted by category) within a provided category.
579
579
  /// @param hook The 721 contract to get the first sorted tier ID of.
580
580
  /// @param category The category to get the first sorted tier ID within. Send 0 for the first ID across all tiers,
581
- /// which might not be in the 0th category if the 0th category does not exist.
581
+ /// which may belong to any category.
582
582
  /// @return id The first sorted tier ID within the provided category.
583
583
  function _firstSortedTierIdOf(address hook, uint256 category) internal view returns (uint256 id) {
584
584
  id = category == 0 ? _tierIdAfter[hook][0] : _startingTierIdOfCategory[hook][category];
@@ -952,7 +952,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
952
952
  if (i != 0) {
953
953
  uint256 previousCategory = tiersToAdd[i - 1].category;
954
954
 
955
- // Revert if the category is not equal or greater than the previously added tier's category.
955
+ // Revert if the category is less than the previously added tier's category.
956
956
  if (tierToAdd.category < previousCategory) {
957
957
  revert JB721TiersHookStore_InvalidCategorySortOrder({
958
958
  tierCategory: tierToAdd.category, previousTierCategory: previousCategory
@@ -1043,8 +1043,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
1043
1043
  // If this is the first tier in a category within this batch, store it as that category's traversal start.
1044
1044
  // Same-category additions are inserted before older tiers in the category-sorted linked list, so a later
1045
1045
  // batch must overwrite the previous start pointer to keep category-filtered `tiersOf` queries complete.
1046
- // The `_startingTierIdOfCategory` of the category "0" will always be the same as the `_tierIdAfter` the 0th
1047
- // tier.
1046
+ // Category 0 starts at the same tier as the default traversal.
1048
1047
  // Access the previous tier's category directly from calldata (0 when i == 0, matching the old
1049
1048
  // uninitialized-memory behavior).
1050
1049
  if ((i == 0 ? 0 : tiersToAdd[i - 1].category) != tierToAdd.category && tierToAdd.category != 0) {
@@ -1104,9 +1103,7 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
1104
1103
 
1105
1104
  // If the previous tier's `_tierIdAfter` was set to something else, update it.
1106
1105
  if (previousTierId != tierId - 1 || _tierIdAfter[msg.sender][previousTierId] != 0) {
1107
- // Set the the previous tier's `_tierIdAfter` to the tier being added, or 0 if the tier ID
1108
- // is
1109
- // incremented.
1106
+ // Point the previous tier at the tier being added, or store 0 when the next ID is implicit.
1110
1107
  _tierIdAfter[msg.sender][previousTierId] = previousTierId == tierId - 1 ? 0 : tierId;
1111
1108
  }
1112
1109
 
@@ -61,8 +61,7 @@ abstract contract JB721Hook is ERC721, IJB721Hook {
61
61
  /// @param directory A directory of terminals and controllers for projects.
62
62
  constructor(IJBDirectory directory) {
63
63
  DIRECTORY = directory;
64
- // Store the address of the original hook deploy. Clones will each use the address of the instance they're based
65
- // on.
64
+ // Store the implementation address. Clones use their own address when they initialize.
66
65
  METADATA_ID_TARGET = address(this);
67
66
  }
68
67
 
@@ -168,7 +167,7 @@ abstract contract JB721Hook is ERC721, IJB721Hook {
168
167
  /// @notice Indicates if this contract adheres to the specified interface.
169
168
  /// @dev See {IERC165-supportsInterface}.
170
169
  /// @param interfaceId The ID of the interface to check for adherence to.
171
- // ERC-2981 royalty support was removed — no royaltyInfo implementation exists.
170
+ // No ERC-2981 royalty interface is exposed.
172
171
  function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, IERC165) returns (bool) {
173
172
  return interfaceId == type(IJB721Hook).interfaceId || interfaceId == type(IJBRulesetDataHook).interfaceId
174
173
  || interfaceId == type(IJBPayHook).interfaceId || interfaceId == type(IJBCashOutHook).interfaceId
@@ -262,7 +261,7 @@ abstract contract JB721Hook is ERC721, IJB721Hook {
262
261
  // the terminal, so any ETH sent alongside an ERC-20 context would be accidental value trapped in the hook.
263
262
  uint256 expectedMsgValue =
264
263
  context.forwardedAmount.token == JBConstants.NATIVE_TOKEN ? context.forwardedAmount.value : 0;
265
- // Keep the terminal-reported forwarded amount and the actual ETH attached to the callback in lockstep.
264
+ // Keep the terminal-reported forwarded amount and the ETH attached to the callback in lockstep.
266
265
  if (msg.value != expectedMsgValue) {
267
266
  revert JB721Hook_InvalidPayValue({
268
267
  token: context.forwardedAmount.token, msgValue: msg.value, forwardedValue: context.forwardedAmount.value
@@ -29,6 +29,7 @@ interface IJB721TiersHookProjectDeployer {
29
29
  /// @param salt A salt to use for the deterministic deployment.
30
30
  /// @return projectId The ID of the newly launched project.
31
31
  /// @return hook The 721 tiers hook that was deployed for the project.
32
+ /// @dev Forwards `msg.value` to `JBProjects.createFor` to cover any configured project creation fee.
32
33
  function launchProjectFor(
33
34
  address owner,
34
35
  JBDeploy721TiersHookConfig memory deployTiersHookConfig,
@@ -37,6 +38,7 @@ interface IJB721TiersHookProjectDeployer {
37
38
  bytes32 salt
38
39
  )
39
40
  external
41
+ payable
40
42
  returns (uint256 projectId, IJB721TiersHook hook);
41
43
 
42
44
  /// @notice Launches rulesets for a project with an attached 721 tiers hook.
@@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
4
4
  import {JB721TierFlags} from "./JB721TierFlags.sol";
5
5
 
6
6
  /// @custom:member id The tier's ID.
7
- /// @custom:member price The price to buy an NFT in this tier, in terms of the currency in its `JBInitTiersConfig`.
7
+ /// @custom:member price The price to buy an NFT in this tier, in terms of the currency in its `JB721InitTiersConfig`.
8
8
  /// @custom:member remainingSupply The remaining number of NFTs which can be minted from this tier.
9
9
  /// @custom:member initialSupply The total number of NFTs which can be minted from this tier.
10
10
  /// @custom:member votingUnits The number of votes that each NFT in this tier gets.
@@ -13,14 +13,13 @@ import {JB721TierFlags} from "./JB721TierFlags.sol";
13
13
  /// purchased.
14
14
  /// @custom:member reserveBeneficiary The address which receives any reserve NFTs from this tier.
15
15
  /// @custom:member encodedIpfsUri The IPFS URI to use for each NFT in this tier.
16
- /// @custom:member category The category that NFTs in this tier belongs to. Used to group NFT tiers.
16
+ /// @custom:member category The category that NFTs in this tier belong to. Used to group NFT tiers.
17
17
  /// @custom:member discountPercent The discount that should be applied to the tier.
18
18
  /// @custom:member flags Boolean flags for this tier (allowOwnerMint, transfersPausable, cantBeRemoved,
19
19
  /// cantIncreaseDiscountPercent, cantBuyWithCredits).
20
20
  /// @custom:member splitPercent The percentage of the tier's price that gets routed to the project's split group when
21
21
  /// an NFT from this tier is minted. Out of `JBConstants.SPLITS_TOTAL_PERCENT`.
22
- /// @custom:member resolvedUri A resolved token URI for NFTs in this tier. Only available if the NFT this tier belongs
23
- /// to has a resolver.
22
+ /// @custom:member resolvedUri A resolved token URI for NFTs in this tier. Only available if the hook has a resolver.
24
23
  struct JB721Tier {
25
24
  uint32 id;
26
25
  uint104 price;
@@ -6,7 +6,7 @@ import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
6
6
  import {JB721TierConfigFlags} from "./JB721TierConfigFlags.sol";
7
7
 
8
8
  /// @notice Config for a single NFT tier within a `JB721TiersHook`.
9
- /// @custom:member price The price to buy an NFT in this tier, in terms of the currency in its `JBInitTiersConfig`.
9
+ /// @custom:member price The price to buy an NFT in this tier, in terms of the currency in its `JB721InitTiersConfig`.
10
10
  /// @custom:member initialSupply The total number of NFTs which can be minted from this tier.
11
11
  /// @custom:member votingUnits The number of votes that each NFT in this tier gets if `useVotingUnits` is true.
12
12
  /// @custom:member reserveFrequency The frequency at which an extra NFT is minted for the `reserveBeneficiary` from this
@@ -15,7 +15,7 @@ import {JB721TierConfigFlags} from "./JB721TierConfigFlags.sol";
15
15
  /// @custom:member reserveBeneficiary The address which receives any reserve NFTs from this tier. Overrides the default
16
16
  /// reserve beneficiary if one is set.
17
17
  /// @custom:member encodedIpfsUri The IPFS URI to use for each NFT in this tier.
18
- /// @custom:member category The category that NFTs in this tier belongs to. Used to group NFT tiers.
18
+ /// @custom:member category The category that NFTs in this tier belong to. Used to group NFT tiers.
19
19
  /// @custom:member discountPercent The discount that should be applied to the tier.
20
20
  /// @custom:member flags Boolean flags for this tier config (allowOwnerMint, useReserveBeneficiaryAsDefault,
21
21
  /// transfersPausable, useVotingUnits, cantBeRemoved, cantIncreaseDiscountPercent, cantBuyWithCredits).
@@ -3,8 +3,8 @@ pragma solidity ^0.8.0;
3
3
 
4
4
  /// @dev A "word" is a 256-bit integer that stores the status of 256 bits (true/false values). Each row of the
5
5
  /// `JBBitmap` matrix is a "word".
6
- /// @custom:member The information stored at the index.
7
- /// @custom:member The index.
6
+ /// @custom:member currentWord The 256-bit bitmap word at `currentDepth`.
7
+ /// @custom:member currentDepth The bitmap row index for `currentWord`.
8
8
  struct JBBitmapWord {
9
9
  uint256 currentWord;
10
10
  uint256 currentDepth;
@@ -10,7 +10,7 @@ import {JBPayDataHookRulesetConfig} from "./JBPayDataHookRulesetConfig.sol";
10
10
  /// @custom:member terminalConfigurations The terminal configurations to add for the project.
11
11
  /// @custom:member memo A memo to pass along to the emitted event.
12
12
  struct JBLaunchRulesetsConfig {
13
- uint56 projectId;
13
+ uint64 projectId;
14
14
  JBPayDataHookRulesetConfig[] rulesetConfigurations;
15
15
  JBTerminalConfig[] terminalConfigurations;
16
16
  string memo;
@@ -8,7 +8,7 @@ pragma solidity ^0.8.0;
8
8
  /// @custom:member baseCurrency The currency on which to base the ruleset's weight.
9
9
  /// @custom:member pausePay A flag indicating if the pay functionality should be paused during the ruleset.
10
10
  /// @custom:member pauseCreditTransfers A flag indicating if the project token transfer functionality should be paused
11
- /// during the funding cycle.
11
+ /// during the ruleset.
12
12
  /// @custom:member allowOwnerMinting A flag indicating if the project owner or an operator with the `MINT_TOKENS`
13
13
  /// permission from the owner should be allowed to mint project tokens on demand during this ruleset.
14
14
  /// @custom:member allowSetCustomToken A flag indicating if the project owner can set the project's token to a custom
@@ -21,13 +21,13 @@ pragma solidity ^0.8.0;
21
21
  /// terminals to use.
22
22
  /// @custom:member allowAddPriceFeed A flag indicating if a project can add new price feeds to calculate exchange rates
23
23
  /// between its tokens.
24
+ /// @custom:member ownerMustSendPayouts A flag indicating if the owner must manually trigger payout distributions.
24
25
  /// @custom:member holdFees A flag indicating if fees should be held during this ruleset.
25
26
  /// @custom:member scopeCashOutsToLocalBalances A flag indicating if omnichain cash-out calculations should use only
26
27
  /// the local chain's terminal balance instead of the project's balance held in all terminals.
27
- /// @custom:member useDataHookForCashOuts A flag indicating if the data hook should be used for cash out transactions
28
- /// during
29
- /// this ruleset.
30
- /// @custom:member metadata Metadata of the metadata, up to uint8 in size.
28
+ /// @custom:member useDataHookForCashOut A flag indicating if the data hook should be used for cash out transactions
29
+ /// during this ruleset.
30
+ /// @custom:member metadata Extra controller-specific metadata packed into the ruleset metadata.
31
31
  struct JBPayDataHookRulesetMetadata {
32
32
  uint16 reservedPercent;
33
33
  uint16 cashOutTaxRate;
@@ -7,7 +7,7 @@ import {JBPayDataHookRulesetConfig} from "./JBPayDataHookRulesetConfig.sol";
7
7
  /// @custom:member rulesetConfigurations The ruleset configurations to queue.
8
8
  /// @custom:member memo A memo to pass along to the emitted event.
9
9
  struct JBQueueRulesetsConfig {
10
- uint56 projectId;
10
+ uint64 projectId;
11
11
  JBPayDataHookRulesetConfig[] rulesetConfigurations;
12
12
  string memo;
13
13
  }
@@ -1,12 +1,12 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity ^0.8.0;
3
3
 
4
- /// @custom:member price The price to buy an NFT in this tier, in terms of the currency in its `JBInitTiersConfig`.
4
+ /// @custom:member price The price to buy an NFT in this tier, in terms of the currency in its `JB721InitTiersConfig`.
5
5
  /// @custom:member remainingSupply The remaining number of NFTs which can be minted from this tier.
6
6
  /// @custom:member initialSupply The total number of NFTs which can be minted from this tier.
7
7
  /// @custom:member splitPercent The percentage of the tier's price that gets routed to the tier's split group when
8
8
  /// an NFT from this tier is minted. Out of `JBConstants.SPLITS_TOTAL_PERCENT`.
9
- /// @custom:member category The category that NFTs in this tier belongs to. Used to group NFT tiers.
9
+ /// @custom:member category The category that NFTs in this tier belong to. Used to group NFT tiers.
10
10
  /// @custom:member discountPercent The discount that should be applied to the tier.
11
11
  /// @custom:member reserveFrequency The frequency at which an extra NFT is minted for the `reserveBeneficiary` from this
12
12
  /// tier. With a `reserveFrequency` of 5, an extra NFT will be minted for the `reserveBeneficiary` for every 5 NFTs