@bananapus/721-hook-v6 0.0.53 → 0.0.55

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,19 +1,16 @@
1
1
  {
2
2
  "name": "@bananapus/721-hook-v6",
3
- "version": "0.0.53",
3
+ "version": "0.0.55",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/Bananapus/nana-721-hook-v6"
8
8
  },
9
9
  "files": [
10
- "CHANGELOG.md",
11
- "foundry.lock",
12
10
  "foundry.toml",
13
11
  "references/",
14
12
  "remappings.txt",
15
13
  "script/",
16
- "sphinx.lock",
17
14
  "src/",
18
15
  "test/utils/"
19
16
  ],
@@ -28,10 +25,10 @@
28
25
  "artifacts": "source ./.env && npx sphinx artifacts --org-id 'ea165b21-7cdc-4d7b-be59-ecdd4c26bee4' --project-name 'nana-721-hook-v6'"
29
26
  },
30
27
  "dependencies": {
31
- "@bananapus/address-registry-v6": "^0.0.25",
32
- "@bananapus/core-v6": "^0.0.54",
33
- "@bananapus/ownable-v6": "^0.0.25",
34
- "@bananapus/permission-ids-v6": "^0.0.25",
28
+ "@bananapus/address-registry-v6": "^0.0.26",
29
+ "@bananapus/core-v6": "^0.0.57",
30
+ "@bananapus/ownable-v6": "^0.0.27",
31
+ "@bananapus/permission-ids-v6": "^0.0.26",
35
32
  "@openzeppelin/contracts": "5.6.1",
36
33
  "@prb/math": "4.1.1",
37
34
  "solady": "0.1.26"
@@ -44,6 +44,7 @@ contract JB721TiersHook is JBOwnable, ERC2771Context, JB721Hook, IJB721TiersHook
44
44
  error JB721TiersHook_AlreadyInitialized(uint256 projectId);
45
45
  error JB721TiersHook_InvalidPricingDecimals(uint256 decimals);
46
46
  error JB721TiersHook_MintReserveNftsPaused(uint256 projectId, uint256 tierId);
47
+ error JB721TiersHook_MissingSplitMetadata();
47
48
  error JB721TiersHook_NoProjectId(uint256 projectId);
48
49
  error JB721TiersHook_TierTransfersPaused(uint256 projectId, uint256 tokenId, address from, address to);
49
50
 
@@ -715,7 +716,11 @@ contract JB721TiersHook is JBOwnable, ERC2771Context, JB721Hook, IJB721TiersHook
715
716
  });
716
717
 
717
718
  // Distribute any forwarded funds to tier split groups.
718
- if (splitData.length != 0 && context.forwardedAmount.value != 0) {
719
+ if (context.forwardedAmount.value != 0) {
720
+ if (splitData.length == 0) {
721
+ revert JB721TiersHook_MissingSplitMetadata();
722
+ }
723
+
719
724
  JB721TiersHookLib.distributeAll({
720
725
  directory: DIRECTORY,
721
726
  splits: SPLITS,
@@ -879,6 +879,20 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
879
879
  currentSortedTierId = _nextSortedTierIdOf({hook: hook, id: currentSortedTierId, max: lastSortedTierId});
880
880
  }
881
881
 
882
+ if (previousSortedTierId != 0 && previousSortedTierId != lastSortedTierId) {
883
+ // All sorted IDs after `previousSortedTierId` were removed. Make the last active tier the traversal end so
884
+ // view functions do not keep walking a removed trailing suffix after cleanup.
885
+ if (_tierIdAfter[hook][previousSortedTierId] != 0) _tierIdAfter[hook][previousSortedTierId] = 0;
886
+
887
+ // Track the compacted end only when it is not the natural max tier ID. A zero value means
888
+ // `_lastSortedTierIdOf` can keep using `maxTierIdOf` as the implicit end.
889
+ uint256 maxTierId = maxTierIdOf[hook];
890
+ uint256 newLastTrackedSortedTierId = previousSortedTierId == maxTierId ? 0 : previousSortedTierId;
891
+ if (_lastTrackedSortedTierIdOf[hook] != newLastTrackedSortedTierId) {
892
+ _lastTrackedSortedTierIdOf[hook] = newLastTrackedSortedTierId;
893
+ }
894
+ }
895
+
882
896
  emit CleanTiers({hook: hook, caller: msg.sender});
883
897
  }
884
898
 
@@ -1026,7 +1040,9 @@ contract JB721TiersHookStore is IJB721TiersHookStore {
1026
1040
  _tierVotingUnitsOf[msg.sender][tierId] = uint32(tierToAdd.votingUnits);
1027
1041
  }
1028
1042
 
1029
- // If this is the first tier in a new category, store it as the first tier in that category.
1043
+ // If this is the first tier in a category within this batch, store it as that category's traversal start.
1044
+ // Same-category additions are inserted before older tiers in the category-sorted linked list, so a later
1045
+ // batch must overwrite the previous start pointer to keep category-filtered `tiersOf` queries complete.
1030
1046
  // The `_startingTierIdOfCategory` of the category "0" will always be the same as the `_tierIdAfter` the 0th
1031
1047
  // tier.
1032
1048
  // Access the previous tier's category directly from calldata (0 when i == 0, matching the old
@@ -6,6 +6,7 @@ import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
6
6
  import {IJBPayHook} from "@bananapus/core-v6/src/interfaces/IJBPayHook.sol";
7
7
  import {IJBRulesetDataHook} from "@bananapus/core-v6/src/interfaces/IJBRulesetDataHook.sol";
8
8
  import {IJBTerminal} from "@bananapus/core-v6/src/interfaces/IJBTerminal.sol";
9
+ import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
9
10
  import {JBMetadataResolver} from "@bananapus/core-v6/src/libraries/JBMetadataResolver.sol";
10
11
  import {JBAfterCashOutRecordedContext} from "@bananapus/core-v6/src/structs/JBAfterCashOutRecordedContext.sol";
11
12
  import {JBAfterPayRecordedContext} from "@bananapus/core-v6/src/structs/JBAfterPayRecordedContext.sol";
@@ -32,6 +33,7 @@ abstract contract JB721Hook is ERC721, IJB721Hook {
32
33
 
33
34
  error JB721Hook_InvalidCashOut(address caller, uint256 contextProjectId, uint256 projectId, uint256 msgValue);
34
35
  error JB721Hook_InvalidPay(address caller, uint256 contextProjectId, uint256 projectId);
36
+ error JB721Hook_InvalidPayValue(address token, uint256 msgValue, uint256 forwardedValue);
35
37
  error JB721Hook_UnauthorizedToken(uint256 tokenId, address holder);
36
38
  error JB721Hook_UnexpectedTokenCashedOut(uint256 cashOutCount);
37
39
 
@@ -256,6 +258,17 @@ abstract contract JB721Hook is ERC721, IJB721Hook {
256
258
  });
257
259
  }
258
260
 
261
+ // Native-token payments must arrive as ETH on this hook call. ERC-20 payments are already held/forwarded by
262
+ // the terminal, so any ETH sent alongside an ERC-20 context would be accidental value trapped in the hook.
263
+ uint256 expectedMsgValue =
264
+ 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.
266
+ if (msg.value != expectedMsgValue) {
267
+ revert JB721Hook_InvalidPayValue({
268
+ token: context.forwardedAmount.token, msgValue: msg.value, forwardedValue: context.forwardedAmount.value
269
+ });
270
+ }
271
+
259
272
  // Process the payment.
260
273
  _processPayment(context);
261
274
  }
@@ -34,7 +34,9 @@ library JB721TiersHookLib {
34
34
  error JB721TiersHook_CantBuyWithCredits(uint256 restrictedCost, uint256 freshValue);
35
35
  error JB721TiersHook_Overspending(uint256 leftoverAmount);
36
36
  error JB721TiersHookLib_NoTerminalForLeftover(uint256 projectId, address token, uint256 leftoverAmount);
37
+ error JB721TiersHookLib_SplitAmountMismatch(uint256 expectedAmount, uint256 actualAmount);
37
38
  error JB721TiersHookLib_SplitFallbackFailed(uint256 projectId, address token, uint256 amount, bytes reason);
39
+ error JB721TiersHookLib_SplitMetadataLengthMismatch(uint256 tierIdCount, uint256 amountCount);
38
40
  error JB721TiersHookLib_TokenTransferAmountMismatch(uint256 expectedAmount, uint256 receivedAmount);
39
41
 
40
42
  //*********************************************************************//
@@ -127,6 +129,29 @@ library JB721TiersHookLib {
127
129
  )
128
130
  external
129
131
  {
132
+ // `encodedSplitData` is terminal-forwarded hook metadata. Each tier ID must have exactly one explicit amount so
133
+ // later split-group routing cannot pair a tier with the wrong value or silently ignore trailing data.
134
+ (uint16[] memory tierIds, uint256[] memory amounts) = abi.decode(encodedSplitData, (uint16[], uint256[]));
135
+ if (tierIds.length != amounts.length) {
136
+ revert JB721TiersHookLib_SplitMetadataLengthMismatch({
137
+ tierIdCount: tierIds.length, amountCount: amounts.length
138
+ });
139
+ }
140
+
141
+ // The terminal tells the hook how much value was forwarded. Require the per-tier split metadata to account for
142
+ // all of it before any transfers happen, otherwise malformed metadata could over-distribute, under-distribute,
143
+ // or leave funds stuck in the hook.
144
+ uint256 totalAmount;
145
+ for (uint256 i; i < amounts.length;) {
146
+ totalAmount += amounts[i];
147
+ unchecked {
148
+ ++i;
149
+ }
150
+ }
151
+ if (totalAmount != amount) {
152
+ revert JB721TiersHookLib_SplitAmountMismatch({expectedAmount: amount, actualAmount: totalAmount});
153
+ }
154
+
130
155
  // For ERC20 tokens, pull from terminal using the allowance it granted via _beforeTransferTo.
131
156
  if (token != JBConstants.NATIVE_TOKEN) {
132
157
  uint256 balanceBefore = IERC20(token).balanceOf(address(this));
@@ -139,8 +164,6 @@ library JB721TiersHookLib {
139
164
  }
140
165
  }
141
166
 
142
- (uint16[] memory tierIds, uint256[] memory amounts) = abi.decode(encodedSplitData, (uint16[], uint256[]));
143
-
144
167
  for (uint256 i; i < tierIds.length;) {
145
168
  if (amounts[i] == 0) {
146
169
  unchecked {
@@ -7,11 +7,14 @@ import {JB721TiersRulesetMetadata} from "../structs/JB721TiersRulesetMetadata.so
7
7
  /// @notice Utility library to parse and store ruleset metadata associated for the tiered 721 hook.
8
8
  /// @dev This library parses the `metadata` member of the `JBRulesetMetadata` struct.
9
9
  library JB721TiersRulesetMetadataResolver {
10
- /// @notice Check whether transfers are paused based on the packed ruleset metadata.
11
- /// @param data The packed metadata to check.
12
- /// @return Whether transfers are paused (bit 0).
13
- function transfersPaused(uint256 data) internal pure returns (bool) {
14
- return (data & 1) == 1;
10
+ /// @notice Expand packed ruleset metadata for the 721 hook.
11
+ /// @param packedMetadata The packed metadata to expand.
12
+ /// @return metadata The metadata as a `JB721TiersRulesetMetadata` struct.
13
+ function expandMetadata(uint16 packedMetadata) internal pure returns (JB721TiersRulesetMetadata memory metadata) {
14
+ return JB721TiersRulesetMetadata({
15
+ pauseTransfers: transfersPaused(packedMetadata),
16
+ pauseMintPendingReserves: mintPendingReservesPaused(packedMetadata)
17
+ });
15
18
  }
16
19
 
17
20
  /// @notice Check whether minting pending reserves is paused based on the packed ruleset metadata.
@@ -35,13 +38,10 @@ library JB721TiersRulesetMetadataResolver {
35
38
  if (metadata.pauseMintPendingReserves) packed |= 1 << 1;
36
39
  }
37
40
 
38
- /// @notice Expand packed ruleset metadata for the 721 hook.
39
- /// @param packedMetadata The packed metadata to expand.
40
- /// @return metadata The metadata as a `JB721TiersRulesetMetadata` struct.
41
- function expandMetadata(uint16 packedMetadata) internal pure returns (JB721TiersRulesetMetadata memory metadata) {
42
- return JB721TiersRulesetMetadata({
43
- pauseTransfers: transfersPaused(packedMetadata),
44
- pauseMintPendingReserves: mintPendingReservesPaused(packedMetadata)
45
- });
41
+ /// @notice Check whether transfers are paused based on the packed ruleset metadata.
42
+ /// @param data The packed metadata to check.
43
+ /// @return Whether transfers are paused (bit 0).
44
+ function transfersPaused(uint256 data) internal pure returns (bool) {
45
+ return (data & 1) == 1;
46
46
  }
47
47
  }
@@ -6,20 +6,6 @@ import {JBBitmapWord} from "../structs/JBBitmapWord.sol";
6
6
  /// @title JBBitmap
7
7
  /// @notice Utilities to manage a bool bitmap. Used for storing inactive tiers.
8
8
  library JBBitmap {
9
- /// @notice Initialize a `JBBitmapWord` struct based on a mapping storage pointer and an index.
10
- function readId(
11
- mapping(uint256 => uint256) storage self,
12
- uint256 index
13
- )
14
- internal
15
- view
16
- returns (JBBitmapWord memory)
17
- {
18
- uint256 depth = _retrieveDepth(index);
19
-
20
- return JBBitmapWord({currentWord: self[depth], currentDepth: depth});
21
- }
22
-
23
9
  /// @notice Get the status of the specified bit within the `JBBitmapWord` struct.
24
10
  /// @dev The `index` is the index that the bit would have if the bitmap were reshaped to a 1*n matrix.
25
11
  /// @return The boolean value at the specified index, which indicates whether the corresponding tier has been
@@ -35,12 +21,18 @@ library JBBitmap {
35
21
  return isTierIdRemoved({self: JBBitmapWord({currentWord: self[depth], currentDepth: depth}), index: index});
36
22
  }
37
23
 
38
- /// @notice Set the bit at the given index to true, indicating that the corresponding tier has been removed.
39
- /// @dev This is a one-way operation.
40
- function removeTier(mapping(uint256 => uint256) storage self, uint256 index) internal {
24
+ /// @notice Initialize a `JBBitmapWord` struct based on a mapping storage pointer and an index.
25
+ function readId(
26
+ mapping(uint256 => uint256) storage self,
27
+ uint256 index
28
+ )
29
+ internal
30
+ view
31
+ returns (JBBitmapWord memory)
32
+ {
41
33
  uint256 depth = _retrieveDepth(index);
42
- // forge-lint: disable-next-line(incorrect-shift)
43
- self[depth] |= uint256(1 << (index % 256));
34
+
35
+ return JBBitmapWord({currentWord: self[depth], currentDepth: depth});
44
36
  }
45
37
 
46
38
  /// @notice Check if the specified index is at a different depth than the current depth of the `JBBitmapWord`
@@ -51,6 +43,14 @@ library JBBitmap {
51
43
  return _retrieveDepth(index) != self.currentDepth;
52
44
  }
53
45
 
46
+ /// @notice Set the bit at the given index to true, indicating that the corresponding tier has been removed.
47
+ /// @dev This is a one-way operation.
48
+ function removeTier(mapping(uint256 => uint256) storage self, uint256 index) internal {
49
+ uint256 depth = _retrieveDepth(index);
50
+ // forge-lint: disable-next-line(incorrect-shift)
51
+ self[depth] |= uint256(1 << (index % 256));
52
+ }
53
+
54
54
  /// @notice Return the line number (depth) of a given index within the bitmap matrix.
55
55
  function _retrieveDepth(uint256 index) internal pure returns (uint256) {
56
56
  return index >> 8; // div by 256
@@ -29,8 +29,48 @@ library JBIpfsDecoder {
29
29
  return string(abi.encodePacked(baseUri, ipfsHash));
30
30
  }
31
31
 
32
- /// @notice Convert a hex string to base58
33
- /// @notice Written by Martin Ludfall - Licence: MIT
32
+ /// @notice Return a new array containing the elements of `input` in reverse order.
33
+ /// @dev Used by `_toBase58` after the base-58 digit accumulator is finalised — the conversion algorithm
34
+ /// emits least-significant digits first, but base-58 strings are read most-significant first.
35
+ /// @param input The array to reverse.
36
+ /// @return output A new array of the same length with elements in reverse order.
37
+ function _reverse(uint8[] memory input) private pure returns (uint8[] memory) {
38
+ uint256 inputLength = input.length;
39
+ uint8[] memory output = new uint8[](inputLength);
40
+ for (uint256 i; i < inputLength;) {
41
+ unchecked {
42
+ // Read from the tail of `input` and write to the head of `output`.
43
+ output[i] = input[input.length - 1 - i];
44
+ ++i;
45
+ }
46
+ }
47
+ return output;
48
+ }
49
+
50
+ /// @notice Map each base-58 digit (0–57) to its corresponding character in `ALPHABET`.
51
+ /// @dev Final stage of `_toBase58`: turns the numeric digit array into the canonical base-58 string bytes.
52
+ /// @param indices Each element must satisfy `0 <= indices[i] < 58`; out-of-range values revert via index OOB.
53
+ /// @return output ASCII bytes with `output[i] = ALPHABET[indices[i]]`.
54
+ function _toAlphabet(uint8[] memory indices) private pure returns (bytes memory) {
55
+ uint256 indicesLength = indices.length;
56
+ bytes memory output = new bytes(indicesLength);
57
+ for (uint256 i; i < indicesLength;) {
58
+ output[i] = ALPHABET[indices[i]];
59
+
60
+ unchecked {
61
+ ++i;
62
+ }
63
+ }
64
+ return output;
65
+ }
66
+
67
+ /// @notice Convert a hex byte string to its base-58 string representation.
68
+ /// @notice Written by Martin Ludfall — Licence: MIT.
69
+ /// @dev Classic "long division by 58" base conversion: iterate the source bytes high-to-low, carrying remainders
70
+ /// through the digit accumulator. After the loop, `digits[0..digitlength)` holds the base-58 representation in
71
+ /// little-endian order; the final composition reverses and maps to ASCII via `_toAlphabet(_reverse(...))`.
72
+ /// @param source The source bytes to convert (multibase-prefixed IPFS hash, in this library's usage).
73
+ /// @return The base-58 encoded string.
34
74
  function _toBase58(bytes memory source) private pure returns (string memory) {
35
75
  if (source.length == 0) return new string(0);
36
76
 
@@ -72,6 +112,12 @@ library JBIpfsDecoder {
72
112
  return string(_toAlphabet(_reverse(_truncate({array: digits, length: digitlength}))));
73
113
  }
74
114
 
115
+ /// @notice Copy the first `length` elements of `array` into a new, exactly-sized array.
116
+ /// @dev `_toBase58` allocates a fixed 46-byte scratch buffer but only fills `digitlength` of it; this trims the
117
+ /// trailing zeros so downstream stages (`_reverse`, `_toAlphabet`) see only the meaningful digits.
118
+ /// @param array The source array. Must have `array.length >= length`.
119
+ /// @param length Number of leading elements to copy.
120
+ /// @return output A new array of exactly `length` elements containing the prefix of `array`.
75
121
  function _truncate(uint8[] memory array, uint8 length) private pure returns (uint8[] memory) {
76
122
  uint8[] memory output = new uint8[](length);
77
123
  for (uint256 i; i < length;) {
@@ -83,29 +129,4 @@ library JBIpfsDecoder {
83
129
  }
84
130
  return output;
85
131
  }
86
-
87
- function _reverse(uint8[] memory input) private pure returns (uint8[] memory) {
88
- uint256 inputLength = input.length;
89
- uint8[] memory output = new uint8[](inputLength);
90
- for (uint256 i; i < inputLength;) {
91
- unchecked {
92
- output[i] = input[input.length - 1 - i];
93
- ++i;
94
- }
95
- }
96
- return output;
97
- }
98
-
99
- function _toAlphabet(uint8[] memory indices) private pure returns (bytes memory) {
100
- uint256 indicesLength = indices.length;
101
- bytes memory output = new bytes(indicesLength);
102
- for (uint256 i; i < indicesLength;) {
103
- output[i] = ALPHABET[indices[i]];
104
-
105
- unchecked {
106
- ++i;
107
- }
108
- }
109
- return output;
110
- }
111
132
  }
@@ -32,6 +32,8 @@ interface IJB721TiersHookStore_ForTest is IJB721TiersHookStore {
32
32
  // forge-lint: disable-next-line(mixed-case-function)
33
33
  function ForTest_dumpTiersList(address nft) external view returns (JB721Tier[] memory tiers);
34
34
  // forge-lint: disable-next-line(mixed-case-function)
35
+ function ForTest_lastSortedTierIdOf(address nft) external view returns (uint256 tierId);
36
+ // forge-lint: disable-next-line(mixed-case-function)
35
37
  function ForTest_setTier(address hook, uint256 index, JBStored721Tier calldata newTier) external;
36
38
  // forge-lint: disable-next-line(mixed-case-function)
37
39
  function ForTest_setTierVotingUnits(address hook, uint256 tierId, uint32 votingUnits) external;
@@ -191,6 +193,11 @@ contract ForTest_JB721TiersHookStore is JB721TiersHookStore, IJB721TiersHookStor
191
193
  }
192
194
  }
193
195
 
196
+ // forge-lint: disable-next-line(mixed-case-function)
197
+ function ForTest_lastSortedTierIdOf(address nft) public view override returns (uint256 tierId) {
198
+ tierId = _lastSortedTierIdOf(nft);
199
+ }
200
+
194
201
  // forge-lint: disable-next-line(mixed-case-function)
195
202
  function ForTest_setTier(address hook, uint256 index, JBStored721Tier calldata newTier) public override {
196
203
  _storedTierOf[address(hook)][index] = newTier;
package/CHANGELOG.md DELETED
@@ -1,83 +0,0 @@
1
- # Changelog
2
-
3
- ## Scope
4
-
5
- This file describes the verified change from `nana-721-hook-v5` to the current `nana-721-hook-v6` repo.
6
-
7
- ## Current v6 surface
8
-
9
- - `JB721TiersHook`
10
- - `JB721TiersHookStore`
11
- - `JB721TiersHookDeployer`
12
- - `JB721TiersHookProjectDeployer`
13
- - `JB721TiersHookLib`
14
-
15
- ## 0.0.50 — Bump nana-core-v6 to 0.0.53
16
-
17
- `@bananapus/core-v6@0.0.53` ([nana-core-v6 PR #145](https://github.com/Bananapus/nana-core-v6/pull/145)) drops the `via_ir` requirement on `JBCashOutHookSpecsLib`, which lets this package consume the cross-project cashout work (`payAfterCashOutTokensOf` / `addToBalanceAfterCashOutTokensOf`) without needing `via_ir = true` in its own foundry profile. `JB721TiersHookStore.tiersOf` is not via-ir-tolerant under solc 0.8.28 (its category loop trips the Yul stack ceiling), so this dep release is what makes the bump possible at all.
18
-
19
- - `JBPayDataHookRulesetMetadata` mirrors the new core `pauseCrossProjectFeeFreeInflows` field (bit 80 in the packed metadata word). Forwarded into the canonical `JBRulesetMetadata` at the three call sites in `JB721TiersHookProjectDeployer` (`_launchProjectFor`, `_launchRulesetsFor`, `_queueRulesetsFor`).
20
- - All `JBRulesetMetadata` test literals patched to include `pauseCrossProjectFeeFreeInflows: false`.
21
-
22
- `package.json`: version `0.0.49 → 0.0.50`, core dep `^0.0.48 → ^0.0.53`.
23
-
24
- ## Summary
25
-
26
- - v6 adds tier-level split routing. `JB721TierConfig` and the surrounding minting logic now support `splitPercent` and `splits`.
27
- - Collection metadata is more flexible than in v5. The hook can update name and symbol through the v6 metadata flow.
28
- - Pricing context is cleaner. The hook no longer exposes prices through the old return shape, and pricing assumptions should be rebuilt from the current interfaces.
29
- - The repo now carries a dedicated helper library to keep the hook surface manageable and to support the larger v6 feature set.
30
- - The repo was upgraded from the v5 Solidity baseline to `0.8.28`.
31
-
32
- ## Local review remediations
33
-
34
- - `JB721TiersHookProjectDeployer.launchRulesetsFor` now checks `LAUNCH_RULESETS` instead of `QUEUE_RULESETS`. The previous check was semantically wrong — launching active rulesets should require the launch permission, not the queue permission.
35
-
36
- ## Verified deltas
37
-
38
- - `IJB721TiersHook.pricingContext()` changed from a three-value return to `(currency, decimals)`.
39
- - `IJB721TiersHook.PRICES()` is now an explicit getter instead of being bundled into `pricingContext()`.
40
- - `IJB721TiersHook.SPLITS()` is new and matches the new tier-splits feature.
41
- - `IJB721TiersHook.setMetadata(...)` now takes `name` and `symbol` before the URI fields.
42
- - The interface gained new event surface around split payout failure handling and collection metadata updates.
43
-
44
- ## Breaking ABI changes
45
-
46
- - `pricingContext()` return shape changed.
47
- - `setMetadata(...)` argument order changed and now includes `name` and `symbol`.
48
- - `JB721TierConfig` gained `cantBuyWithCredits`, `splitPercent`, and `splits`. Boolean flags (`allowOwnerMint`, `useReserveBeneficiaryAsDefault`, `transfersPausable`, `useVotingUnits`, `cantBeRemoved`, `cantIncreaseDiscountPercent`, `cantBuyWithCredits`) are nested in a `flags` field of type `JB721TierConfigFlags`.
49
- - `JB721Tier` boolean flags (`allowOwnerMint`, `transfersPausable`, `cantBeRemoved`, `cantIncreaseDiscountPercent`, `cantBuyWithCredits`) are nested in a `flags` field of type `JB721TierFlags`.
50
- - `JBStored721Tier` replaced packed `votingUnits` storage with `splitPercent` in the stored struct layout.
51
- - `SPLITS()` and `PRICES()` are explicit interface getters.
52
-
53
- ## Indexer impact
54
-
55
- - New events: `SetName`, `SetSymbol`, `SplitPayoutReverted`.
56
- - Tier config decoding changed because `JB721TierConfig` is no longer v5-compatible.
57
- - Collection metadata can now change after deployment, so one-time indexing of `name` and `symbol` is no longer sufficient.
58
-
59
- ## Migration notes
60
-
61
- - Rebuild integrations around the current `IJB721TiersHook` and related structs. This is not a selector-stable upgrade.
62
- - Any indexer or frontend that decoded tier config data must account for tier splits.
63
- - If you relied on v5 pricing-context return shapes or older metadata argument ordering, update those assumptions before shipping.
64
-
65
- ## ABI appendix
66
-
67
- - Added functions
68
- - `PRICES()`
69
- - `SPLITS()`
70
- - Changed functions
71
- - `pricingContext()`
72
- - `setMetadata(...)`
73
- - Added events
74
- - `SetName`
75
- - `SetSymbol`
76
- - `SplitPayoutReverted`
77
- - Changed structs
78
- - `JB721TierConfig` (boolean flags moved to nested `JB721TierConfigFlags flags`)
79
- - `JB721Tier` (boolean flags moved to nested `JB721TierFlags flags`)
80
- - `JBStored721Tier`
81
- - Added structs
82
- - `JB721TierConfigFlags`
83
- - `JB721TierFlags`
package/foundry.lock DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "lib/forge-std": {
3
- "rev": "77876f8a5b44b770a935621bb331660c90ac928e"
4
- }
5
- }
package/sphinx.lock DELETED
@@ -1,476 +0,0 @@
1
- {
2
- "warning": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
3
- "format": "sphinx-lock-1.0.0",
4
- "orgId": "ea165b21-7cdc-4d7b-be59-ecdd4c26bee4",
5
- "projects": {
6
- "nana-omnichain-deployers": {
7
- "projectId": "4c8b18a7-99c8-431a-b575-e6817503fbd2",
8
- "projectName": "nana-omnichain-deployers",
9
- "defaultSafe": {
10
- "safeName": "nana-core-small",
11
- "owners": [
12
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
13
- "0x34aA3F359A9D614239015126635CE7732c18fDF3",
14
- "0x5a3f5ac3D6f1a0061D3bB91f38606F7103eCdBe8",
15
- "0x5EE9F1cdD9588A3c800441CBd7A38Ffeff40cBc2",
16
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
17
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
18
- "0x721b19e30EF791FF2A67FF4b375E591aAf84136B",
19
- "0x73aEd5a32E898644Acb841C3Ac40663202CfD485",
20
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
21
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
22
- "0x99368d83F73b803Caf924956C5EE6E0b8f86Fb3B",
23
- "0xc109636a2b47f8b290cc134dd446Fcd7d7e0cC94",
24
- "0xCa81360a91504500674E926b1b301165b2CA9807",
25
- "0xD78285eef93E13D1F96062265b68099C480121b8",
26
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
27
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1",
28
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
29
- ],
30
- "threshold": "5",
31
- "saltNonce": "0"
32
- }
33
- },
34
- "nana-address-registry-v5": {
35
- "projectId": "cc6ec42f-5bb5-451a-a66a-928fd3231d2f",
36
- "projectName": "nana-address-registry-v5",
37
- "defaultSafe": {
38
- "safeName": "nana-core-v5",
39
- "owners": [
40
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
41
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
42
- "0xCa81360a91504500674E926b1b301165b2CA9807",
43
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651"
44
- ],
45
- "threshold": "2",
46
- "saltNonce": "0"
47
- }
48
- },
49
- "nana-buyback-hook-v5": {
50
- "projectId": "cf0b6f77-d870-4ccf-bbdc-6b22dceb11b6",
51
- "projectName": "nana-buyback-hook-v5",
52
- "defaultSafe": {
53
- "safeName": "nana-core-v5",
54
- "owners": [
55
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
56
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
57
- "0xCa81360a91504500674E926b1b301165b2CA9807",
58
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651"
59
- ],
60
- "threshold": "2",
61
- "saltNonce": "0"
62
- }
63
- },
64
- "nana-swap-terminal": {
65
- "projectId": "a804c33d-fd0c-4dea-930b-ab72fec9f557",
66
- "projectName": "nana-swap-terminal",
67
- "defaultSafe": {
68
- "safeName": "nana-core-small",
69
- "owners": [
70
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
71
- "0x34aA3F359A9D614239015126635CE7732c18fDF3",
72
- "0x5a3f5ac3D6f1a0061D3bB91f38606F7103eCdBe8",
73
- "0x5EE9F1cdD9588A3c800441CBd7A38Ffeff40cBc2",
74
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
75
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
76
- "0x721b19e30EF791FF2A67FF4b375E591aAf84136B",
77
- "0x73aEd5a32E898644Acb841C3Ac40663202CfD485",
78
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
79
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
80
- "0x99368d83F73b803Caf924956C5EE6E0b8f86Fb3B",
81
- "0xc109636a2b47f8b290cc134dd446Fcd7d7e0cC94",
82
- "0xCa81360a91504500674E926b1b301165b2CA9807",
83
- "0xD78285eef93E13D1F96062265b68099C480121b8",
84
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
85
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1",
86
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
87
- ],
88
- "threshold": "5",
89
- "saltNonce": "0"
90
- }
91
- },
92
- "nana-core": {
93
- "projectId": "290d6007-345d-4bcc-af08-5e5a26ca2dc5",
94
- "projectName": "nana-core",
95
- "defaultSafe": {
96
- "safeName": "nana-core",
97
- "owners": [
98
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
99
- "0x34aA3F359A9D614239015126635CE7732c18fDF3",
100
- "0x5a3f5ac3D6f1a0061D3bB91f38606F7103eCdBe8",
101
- "0x5EE9F1cdD9588A3c800441CBd7A38Ffeff40cBc2",
102
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
103
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
104
- "0x721b19e30EF791FF2A67FF4b375E591aAf84136B",
105
- "0x73aEd5a32E898644Acb841C3Ac40663202CfD485",
106
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
107
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
108
- "0x99368d83F73b803Caf924956C5EE6E0b8f86Fb3B",
109
- "0xc109636a2b47f8b290cc134dd446Fcd7d7e0cC94",
110
- "0xCa81360a91504500674E926b1b301165b2CA9807",
111
- "0xD78285eef93E13D1F96062265b68099C480121b8",
112
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
113
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1",
114
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
115
- ],
116
- "threshold": "9",
117
- "saltNonce": "0"
118
- }
119
- },
120
- "nana-buyback-hook": {
121
- "projectId": "f348713c-83c9-4a85-9b34-acce562d5593",
122
- "projectName": "nana-buyback-hook",
123
- "defaultSafe": {
124
- "safeName": "nana-core-small",
125
- "owners": [
126
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
127
- "0x34aA3F359A9D614239015126635CE7732c18fDF3",
128
- "0x5a3f5ac3D6f1a0061D3bB91f38606F7103eCdBe8",
129
- "0x5EE9F1cdD9588A3c800441CBd7A38Ffeff40cBc2",
130
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
131
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
132
- "0x721b19e30EF791FF2A67FF4b375E591aAf84136B",
133
- "0x73aEd5a32E898644Acb841C3Ac40663202CfD485",
134
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
135
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
136
- "0x99368d83F73b803Caf924956C5EE6E0b8f86Fb3B",
137
- "0xc109636a2b47f8b290cc134dd446Fcd7d7e0cC94",
138
- "0xCa81360a91504500674E926b1b301165b2CA9807",
139
- "0xD78285eef93E13D1F96062265b68099C480121b8",
140
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
141
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1",
142
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
143
- ],
144
- "threshold": "5",
145
- "saltNonce": "0"
146
- }
147
- },
148
- "croptop-core": {
149
- "projectId": "0c213583-47a4-4212-a7cb-b2c0cfdcdac4",
150
- "projectName": "croptop-core",
151
- "defaultSafe": {
152
- "safeName": "croptop",
153
- "owners": [
154
- "0x14293560A2dde4fFA136A647b7a2f927b0774AB6",
155
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
156
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
157
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
158
- "0xCa81360a91504500674E926b1b301165b2CA9807"
159
- ],
160
- "threshold": "2",
161
- "saltNonce": "0"
162
- }
163
- },
164
- "banny-core": {
165
- "projectId": "26678812-e6ca-443d-a5e0-7b62fcdd455f",
166
- "projectName": "banny-core",
167
- "defaultSafe": {
168
- "safeName": "banny-core",
169
- "owners": [
170
- "0x14293560A2dde4fFA136A647b7a2f927b0774AB6",
171
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
172
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
173
- "0xCa81360a91504500674E926b1b301165b2CA9807",
174
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1"
175
- ],
176
- "threshold": "2",
177
- "saltNonce": "0"
178
- }
179
- },
180
- "nana-fee-project": {
181
- "projectId": "8420d3da-9977-4908-be04-d600a090744d",
182
- "projectName": "nana-fee-project",
183
- "defaultSafe": {
184
- "safeName": "nana-core",
185
- "owners": [
186
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
187
- "0x34aA3F359A9D614239015126635CE7732c18fDF3",
188
- "0x5a3f5ac3D6f1a0061D3bB91f38606F7103eCdBe8",
189
- "0x5EE9F1cdD9588A3c800441CBd7A38Ffeff40cBc2",
190
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
191
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
192
- "0x721b19e30EF791FF2A67FF4b375E591aAf84136B",
193
- "0x73aEd5a32E898644Acb841C3Ac40663202CfD485",
194
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
195
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
196
- "0x99368d83F73b803Caf924956C5EE6E0b8f86Fb3B",
197
- "0xc109636a2b47f8b290cc134dd446Fcd7d7e0cC94",
198
- "0xCa81360a91504500674E926b1b301165b2CA9807",
199
- "0xD78285eef93E13D1F96062265b68099C480121b8",
200
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
201
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1",
202
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
203
- ],
204
- "threshold": "9",
205
- "saltNonce": "0"
206
- }
207
- },
208
- "nana-suckers-v5": {
209
- "projectId": "55b45d45-a209-4197-83e1-aa096e19ddbc",
210
- "projectName": "nana-suckers-v5",
211
- "defaultSafe": {
212
- "safeName": "nana-core-v5",
213
- "owners": [
214
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
215
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
216
- "0xCa81360a91504500674E926b1b301165b2CA9807",
217
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651"
218
- ],
219
- "threshold": "2",
220
- "saltNonce": "0"
221
- }
222
- },
223
- "revnet-core-v5": {
224
- "projectId": "cf581f7f-8bab-4773-b1bf-6389b6891056",
225
- "projectName": "revnet-core-v5",
226
- "defaultSafe": {
227
- "safeName": "revnet",
228
- "owners": [
229
- "0x14293560A2dde4fFA136A647b7a2f927b0774AB6",
230
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
231
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
232
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
233
- "0xCa81360a91504500674E926b1b301165b2CA9807",
234
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
235
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
236
- ],
237
- "threshold": "3",
238
- "saltNonce": "0"
239
- }
240
- },
241
- "revnet-core": {
242
- "projectId": "ff72a6d2-9324-49ef-a415-57e253550e9e",
243
- "projectName": "revnet-core",
244
- "defaultSafe": {
245
- "safeName": "revnet",
246
- "owners": [
247
- "0x14293560A2dde4fFA136A647b7a2f927b0774AB6",
248
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
249
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
250
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
251
- "0xCa81360a91504500674E926b1b301165b2CA9807",
252
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
253
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
254
- ],
255
- "threshold": "3",
256
- "saltNonce": "0"
257
- }
258
- },
259
- "nana-project-handles-v5": {
260
- "projectId": "8795935f-e0ba-4b84-9ec2-44315fbdf4d8",
261
- "projectName": "nana-project-handles-v5",
262
- "defaultSafe": {
263
- "safeName": "nana-core-v5",
264
- "owners": [
265
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
266
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
267
- "0xCa81360a91504500674E926b1b301165b2CA9807",
268
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651"
269
- ],
270
- "threshold": "2",
271
- "saltNonce": "0"
272
- }
273
- },
274
- "nana-721-hook": {
275
- "projectId": "67cfcad1-d38b-4b4d-b137-a24797c31991",
276
- "projectName": "nana-721-hook",
277
- "defaultSafe": {
278
- "safeName": "nana-core",
279
- "owners": [
280
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
281
- "0x34aA3F359A9D614239015126635CE7732c18fDF3",
282
- "0x5a3f5ac3D6f1a0061D3bB91f38606F7103eCdBe8",
283
- "0x5EE9F1cdD9588A3c800441CBd7A38Ffeff40cBc2",
284
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
285
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
286
- "0x721b19e30EF791FF2A67FF4b375E591aAf84136B",
287
- "0x73aEd5a32E898644Acb841C3Ac40663202CfD485",
288
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
289
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
290
- "0x99368d83F73b803Caf924956C5EE6E0b8f86Fb3B",
291
- "0xc109636a2b47f8b290cc134dd446Fcd7d7e0cC94",
292
- "0xCa81360a91504500674E926b1b301165b2CA9807",
293
- "0xD78285eef93E13D1F96062265b68099C480121b8",
294
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
295
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1",
296
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
297
- ],
298
- "threshold": "9",
299
- "saltNonce": "0"
300
- }
301
- },
302
- "nana-swap-terminal-v5": {
303
- "projectId": "b476ccb3-4857-4d11-87cf-9b5cb3ac27c2",
304
- "projectName": "nana-swap-terminal-v5",
305
- "defaultSafe": {
306
- "safeName": "nana-core-v5",
307
- "owners": [
308
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
309
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
310
- "0xCa81360a91504500674E926b1b301165b2CA9807",
311
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651"
312
- ],
313
- "threshold": "2",
314
- "saltNonce": "0"
315
- }
316
- },
317
- "banny-core-v5": {
318
- "projectId": "47a1f9c8-f418-4907-8402-bfc456ada246",
319
- "projectName": "banny-core-v5",
320
- "defaultSafe": {
321
- "safeName": "banny-core",
322
- "owners": [
323
- "0x14293560A2dde4fFA136A647b7a2f927b0774AB6",
324
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
325
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
326
- "0xCa81360a91504500674E926b1b301165b2CA9807",
327
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1"
328
- ],
329
- "threshold": "2",
330
- "saltNonce": "0"
331
- }
332
- },
333
- "nana-address-registry": {
334
- "projectId": "b1c7e214-2927-4042-a3c9-d5751940ce28",
335
- "projectName": "nana-address-registry",
336
- "defaultSafe": {
337
- "safeName": "nana-core",
338
- "owners": [
339
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
340
- "0x34aA3F359A9D614239015126635CE7732c18fDF3",
341
- "0x5a3f5ac3D6f1a0061D3bB91f38606F7103eCdBe8",
342
- "0x5EE9F1cdD9588A3c800441CBd7A38Ffeff40cBc2",
343
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
344
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
345
- "0x721b19e30EF791FF2A67FF4b375E591aAf84136B",
346
- "0x73aEd5a32E898644Acb841C3Ac40663202CfD485",
347
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
348
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
349
- "0x99368d83F73b803Caf924956C5EE6E0b8f86Fb3B",
350
- "0xc109636a2b47f8b290cc134dd446Fcd7d7e0cC94",
351
- "0xCa81360a91504500674E926b1b301165b2CA9807",
352
- "0xD78285eef93E13D1F96062265b68099C480121b8",
353
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
354
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1",
355
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
356
- ],
357
- "threshold": "9",
358
- "saltNonce": "0"
359
- }
360
- },
361
- "nana-core-v5": {
362
- "projectId": "43d1f453-3129-4383-a056-d1da4f3b1ee8",
363
- "projectName": "nana-core-v5",
364
- "defaultSafe": {
365
- "safeName": "nana-core-v5",
366
- "owners": [
367
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
368
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
369
- "0xCa81360a91504500674E926b1b301165b2CA9807",
370
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651"
371
- ],
372
- "threshold": "2",
373
- "saltNonce": "0"
374
- }
375
- },
376
- "nana-721-hook-v5": {
377
- "projectId": "b29a3b81-3722-40ad-b831-66472be6d6a8",
378
- "projectName": "nana-721-hook-v5",
379
- "defaultSafe": {
380
- "safeName": "nana-core-v5",
381
- "owners": [
382
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
383
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
384
- "0xCa81360a91504500674E926b1b301165b2CA9807",
385
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651"
386
- ],
387
- "threshold": "2",
388
- "saltNonce": "0"
389
- }
390
- },
391
- "nana-periphery": {
392
- "projectId": "0de1ae41-0a43-4bc3-8eec-208718afaa51",
393
- "projectName": "nana-periphery",
394
- "defaultSafe": {
395
- "safeName": "nana-core",
396
- "owners": [
397
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
398
- "0x34aA3F359A9D614239015126635CE7732c18fDF3",
399
- "0x5a3f5ac3D6f1a0061D3bB91f38606F7103eCdBe8",
400
- "0x5EE9F1cdD9588A3c800441CBd7A38Ffeff40cBc2",
401
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
402
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
403
- "0x721b19e30EF791FF2A67FF4b375E591aAf84136B",
404
- "0x73aEd5a32E898644Acb841C3Ac40663202CfD485",
405
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
406
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
407
- "0x99368d83F73b803Caf924956C5EE6E0b8f86Fb3B",
408
- "0xc109636a2b47f8b290cc134dd446Fcd7d7e0cC94",
409
- "0xCa81360a91504500674E926b1b301165b2CA9807",
410
- "0xD78285eef93E13D1F96062265b68099C480121b8",
411
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
412
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1",
413
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
414
- ],
415
- "threshold": "9",
416
- "saltNonce": "0"
417
- }
418
- },
419
- "nana-project-handles": {
420
- "projectId": "67c86da0-a089-4b0f-a04d-4dffda844ff9",
421
- "projectName": "nana-project-handles",
422
- "defaultSafe": {
423
- "safeName": "nana-core-small",
424
- "owners": [
425
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
426
- "0x34aA3F359A9D614239015126635CE7732c18fDF3",
427
- "0x5a3f5ac3D6f1a0061D3bB91f38606F7103eCdBe8",
428
- "0x5EE9F1cdD9588A3c800441CBd7A38Ffeff40cBc2",
429
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
430
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
431
- "0x721b19e30EF791FF2A67FF4b375E591aAf84136B",
432
- "0x73aEd5a32E898644Acb841C3Ac40663202CfD485",
433
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
434
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
435
- "0x99368d83F73b803Caf924956C5EE6E0b8f86Fb3B",
436
- "0xc109636a2b47f8b290cc134dd446Fcd7d7e0cC94",
437
- "0xCa81360a91504500674E926b1b301165b2CA9807",
438
- "0xD78285eef93E13D1F96062265b68099C480121b8",
439
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
440
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1",
441
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
442
- ],
443
- "threshold": "5",
444
- "saltNonce": "0"
445
- }
446
- },
447
- "nana-suckers": {
448
- "projectId": "1b040a9e-0764-4173-880e-b5ebf312bc44",
449
- "projectName": "nana-suckers",
450
- "defaultSafe": {
451
- "safeName": "nana-core",
452
- "owners": [
453
- "0x1bb1e3F6818FeB7c1F1674e6E7D6c30BA2725643",
454
- "0x34aA3F359A9D614239015126635CE7732c18fDF3",
455
- "0x5a3f5ac3D6f1a0061D3bB91f38606F7103eCdBe8",
456
- "0x5EE9F1cdD9588A3c800441CBd7A38Ffeff40cBc2",
457
- "0x63A2368F4B509438ca90186cb1C15156713D5834",
458
- "0x6849310926127F819d48894DeA667f3ECD18a07c",
459
- "0x721b19e30EF791FF2A67FF4b375E591aAf84136B",
460
- "0x73aEd5a32E898644Acb841C3Ac40663202CfD485",
461
- "0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD",
462
- "0x8d3CC5b1a5268Ff0C119c5c03252EB8c1bFEBbB2",
463
- "0x99368d83F73b803Caf924956C5EE6E0b8f86Fb3B",
464
- "0xc109636a2b47f8b290cc134dd446Fcd7d7e0cC94",
465
- "0xCa81360a91504500674E926b1b301165b2CA9807",
466
- "0xD78285eef93E13D1F96062265b68099C480121b8",
467
- "0xDc6Dd6Bc601448541A4862a91De1B86291839651",
468
- "0xe7879a2D05dBA966Fcca34EE9C3F99eEe7eDEFd1",
469
- "0xf33CFe55655B0190eAF5aC2749F954c64E06d887"
470
- ],
471
- "threshold": "9",
472
- "saltNonce": "0"
473
- }
474
- }
475
- }
476
- }