@bananapus/permission-ids-v6 0.0.13 → 0.0.15

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/ADMINISTRATION.md CHANGED
@@ -10,7 +10,7 @@ There are no ownable contracts, no upgrade mechanisms, and no mutable state. The
10
10
 
11
11
  ## Permission IDs
12
12
 
13
- All 33 defined permission IDs and what they control:
13
+ All 34 defined permission IDs and what they control:
14
14
 
15
15
  | ID | Constant | Used By | What It Controls |
16
16
  |----|----------|---------|-----------------|
@@ -29,26 +29,27 @@ All 33 defined permission IDs and what they control:
29
29
  | 13 | `TRANSFER_CREDITS` | nana-core (`JBController`) | `JBController.transferCreditsFrom` -- transfer internal credits. Checked against the **token holder**. |
30
30
  | 14 | `SET_CONTROLLER` | nana-core (`JBDirectory`) | `JBDirectory.setControllerOf` -- set a project's controller. |
31
31
  | 15 | `SET_TERMINALS` | nana-core (`JBDirectory`) | `JBDirectory.setTerminalsOf` -- set a project's terminals. **Warning:** can remove the primary terminal. |
32
- | 16 | `SET_PRIMARY_TERMINAL` | nana-core (`JBDirectory`) | `JBDirectory.setPrimaryTerminalOf` -- set the primary terminal for a token. |
33
- | 17 | `USE_ALLOWANCE` | nana-core (`JBMultiTerminal`) | `JBMultiTerminal.useAllowanceOf` -- spend surplus allowance to an arbitrary address. |
34
- | 18 | `SET_SPLIT_GROUPS` | nana-core (`JBController`) | `JBController.setSplitGroupsOf` -- configure payout and reserved token splits. |
35
- | 19 | `ADD_PRICE_FEED` | nana-core (`JBController`) | `JBController.addPriceFeedFor` (which internally calls `JBPrices.addPriceFeedFor`) -- add a price feed for a project. |
36
- | 20 | `ADD_ACCOUNTING_CONTEXTS` | nana-core (`JBMultiTerminal`) | `JBMultiTerminal.addAccountingContextsFor` -- add accepted tokens to a terminal. |
37
- | 21 | `SET_TOKEN_METADATA` | nana-core (`JBController`) | `JBController.setTokenMetadataOf` -- set a project token's name and symbol. |
38
- | 22 | `ADJUST_721_TIERS` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.adjustTiers` -- add or remove NFT tiers. |
39
- | 23 | `SET_721_METADATA` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.setMetadata` -- set NFT metadata URIs. |
40
- | 24 | `MINT_721` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.mintFor` -- manually mint NFTs to a beneficiary. |
41
- | 25 | `SET_721_DISCOUNT_PERCENT` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.setDiscountPercentOf` -- set discount percent on NFT tiers. |
42
- | 26 | `SET_BUYBACK_TWAP` | nana-buyback-hook (`JBBuybackHook`) | `JBBuybackHook.setTwapWindowOf` -- configure the TWAP oracle window. |
43
- | 27 | `SET_BUYBACK_POOL` | nana-buyback-hook (`JBBuybackHook`) | `JBBuybackHook.setPoolFor` -- set the Uniswap pool for buybacks. |
44
- | 28 | `SET_BUYBACK_HOOK` | nana-buyback-hook (`JBBuybackHookRegistry`) | `JBBuybackHookRegistry.setHookFor` and `lockHookFor` -- configure and permanently lock the buyback hook. |
45
- | 29 | `SET_ROUTER_TERMINAL` | nana-router-terminal (`JBRouterTerminalRegistry`) | `JBRouterTerminalRegistry.setTerminalFor` and `lockTerminalFor` -- configure and permanently lock the router terminal. |
46
- | 30 | `MAP_SUCKER_TOKEN` | nana-suckers (`JBSucker`) | `JBSucker.mapToken` -- map an ERC-20 to its remote chain counterpart. Immutable once the outbox tree has entries. |
47
- | 31 | `DEPLOY_SUCKERS` | nana-suckers (`JBSuckerRegistry`) | `JBSuckerRegistry.deploySuckersFor` -- deploy sucker contracts for cross-chain bridging. |
48
- | 32 | `SUCKER_SAFETY` | nana-suckers (`JBSucker`) | `JBSucker.enableEmergencyHatchFor` -- enable the emergency hatch to recover stuck tokens. |
49
- | 33 | `SET_SUCKER_DEPRECATION` | nana-suckers (`JBSucker`) | `JBSucker.setDeprecation` -- set deprecation status (ENABLED, DEPRECATION_PENDING, SENDING_DISABLED, DEPRECATED). |
50
-
51
- IDs 0 and 34-255 are unused. ID 0 is reserved and cannot be set. IDs 34-255 are available for future ecosystem extensions.
32
+ | 16 | `ADD_TERMINALS` | nana-core (`JBDirectory`) | `JBDirectory.setPrimaryTerminalOf` -- add a new terminal when `setPrimaryTerminalOf` implicitly adds it. |
33
+ | 17 | `SET_PRIMARY_TERMINAL` | nana-core (`JBDirectory`) | `JBDirectory.setPrimaryTerminalOf` -- set the primary terminal for a token. |
34
+ | 18 | `USE_ALLOWANCE` | nana-core (`JBMultiTerminal`) | `JBMultiTerminal.useAllowanceOf` -- spend surplus allowance to an arbitrary address. |
35
+ | 19 | `SET_SPLIT_GROUPS` | nana-core (`JBController`) | `JBController.setSplitGroupsOf` -- configure payout and reserved token splits. |
36
+ | 20 | `ADD_PRICE_FEED` | nana-core (`JBController`) | `JBController.addPriceFeedFor` (which internally calls `JBPrices.addPriceFeedFor`) -- add a price feed for a project. |
37
+ | 21 | `ADD_ACCOUNTING_CONTEXTS` | nana-core (`JBMultiTerminal`) | `JBMultiTerminal.addAccountingContextsFor` -- add accepted tokens to a terminal. |
38
+ | 22 | `SET_TOKEN_METADATA` | nana-core (`JBController`) | `JBController.setTokenMetadataOf` -- set a project token's name and symbol. |
39
+ | 23 | `ADJUST_721_TIERS` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.adjustTiers` -- add or remove NFT tiers. |
40
+ | 24 | `SET_721_METADATA` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.setMetadata` -- set NFT metadata URIs. |
41
+ | 25 | `MINT_721` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.mintFor` -- manually mint NFTs to a beneficiary. |
42
+ | 26 | `SET_721_DISCOUNT_PERCENT` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.setDiscountPercentOf` -- set discount percent on NFT tiers. |
43
+ | 27 | `SET_BUYBACK_TWAP` | nana-buyback-hook (`JBBuybackHook`) | `JBBuybackHook.setTwapWindowOf` -- configure the TWAP oracle window. |
44
+ | 28 | `SET_BUYBACK_POOL` | nana-buyback-hook (`JBBuybackHook`) | `JBBuybackHook.setPoolFor` -- set the Uniswap pool for buybacks. |
45
+ | 29 | `SET_BUYBACK_HOOK` | nana-buyback-hook (`JBBuybackHookRegistry`) | `JBBuybackHookRegistry.setHookFor` and `lockHookFor` -- configure and permanently lock the buyback hook. |
46
+ | 30 | `SET_ROUTER_TERMINAL` | nana-router-terminal (`JBRouterTerminalRegistry`) | `JBRouterTerminalRegistry.setTerminalFor` and `lockTerminalFor` -- configure and permanently lock the router terminal. |
47
+ | 31 | `MAP_SUCKER_TOKEN` | nana-suckers (`JBSucker`) | `JBSucker.mapToken` -- map an ERC-20 to its remote chain counterpart. Immutable once the outbox tree has entries. |
48
+ | 32 | `DEPLOY_SUCKERS` | nana-suckers (`JBSuckerRegistry`) | `JBSuckerRegistry.deploySuckersFor` -- deploy sucker contracts for cross-chain bridging. |
49
+ | 33 | `SUCKER_SAFETY` | nana-suckers (`JBSucker`) | `JBSucker.enableEmergencyHatchFor` -- enable the emergency hatch to recover stuck tokens. |
50
+ | 34 | `SET_SUCKER_DEPRECATION` | nana-suckers (`JBSucker`) | `JBSucker.setDeprecation` -- set deprecation status (ENABLED, DEPRECATION_PENDING, SENDING_DISABLED, DEPRECATED). |
51
+
52
+ IDs 0 and 35-255 are unused. ID 0 is reserved and cannot be set. IDs 35-255 are available for future ecosystem extensions.
52
53
 
53
54
  ## ROOT Permission
54
55
 
@@ -91,9 +92,9 @@ Some permissions warrant extra caution when granting:
91
92
 
92
93
  - **`ROOT` (1):** Full access to all gated functions for a project.
93
94
  - **`SET_TERMINALS` (15):** Can remove the primary terminal, breaking payments and cashouts.
94
- - **`USE_ALLOWANCE` (17):** Can send surplus funds to any address.
95
- - **`SET_BUYBACK_HOOK` (28):** Can permanently lock the buyback hook configuration.
96
- - **`SET_ROUTER_TERMINAL` (29):** Can permanently lock the router terminal configuration.
95
+ - **`USE_ALLOWANCE` (18):** Can send surplus funds to any address.
96
+ - **`SET_BUYBACK_HOOK` (29):** Can permanently lock the buyback hook configuration.
97
+ - **`SET_ROUTER_TERMINAL` (30):** Can permanently lock the router terminal configuration.
97
98
  - **`MINT_TOKENS` (10):** Can inflate token supply (subject to ruleset allowing owner minting).
98
99
 
99
100
  ## Holder vs. Owner Permissions
package/ARCHITECTURE.md CHANGED
@@ -42,24 +42,25 @@ src/
42
42
  | 13 | `TRANSFER_CREDITS` | nana-core | `JBController.transferCreditsFrom` |
43
43
  | 14 | `SET_CONTROLLER` | nana-core | `JBDirectory.setControllerOf` |
44
44
  | 15 | `SET_TERMINALS` | nana-core | `JBDirectory.setTerminalsOf` |
45
- | 16 | `SET_PRIMARY_TERMINAL` | nana-core | `JBDirectory.setPrimaryTerminalOf` |
46
- | 17 | `USE_ALLOWANCE` | nana-core | `JBMultiTerminal.useAllowanceOf` |
47
- | 18 | `SET_SPLIT_GROUPS` | nana-core | `JBController.setSplitGroupsOf` |
48
- | 19 | `ADD_PRICE_FEED` | nana-core | `JBController.addPriceFeedFor` |
49
- | 20 | `ADD_ACCOUNTING_CONTEXTS` | nana-core | `JBMultiTerminal.addAccountingContextsFor` |
50
- | 21 | `SET_TOKEN_METADATA` | nana-core | `JBController.setTokenMetadataOf` |
51
- | 22 | `ADJUST_721_TIERS` | nana-721-hook | `JB721TiersHook.adjustTiers` |
52
- | 23 | `SET_721_METADATA` | nana-721-hook | `JB721TiersHook.setMetadata` |
53
- | 24 | `MINT_721` | nana-721-hook | `JB721TiersHook.mintFor` |
54
- | 25 | `SET_721_DISCOUNT_PERCENT` | nana-721-hook | `JB721TiersHook.setDiscountPercentOf` |
55
- | 26 | `SET_BUYBACK_TWAP` | nana-buyback-hook | `JBBuybackHook.setTwapWindowOf` |
56
- | 27 | `SET_BUYBACK_POOL` | nana-buyback-hook | `JBBuybackHook.setPoolFor` |
57
- | 28 | `SET_BUYBACK_HOOK` | nana-buyback-hook | `JBBuybackHookRegistry.setHookFor` + `lockHookFor` |
58
- | 29 | `SET_ROUTER_TERMINAL` | nana-router-terminal | `JBRouterTerminalRegistry.setTerminalFor` + `lockTerminalFor` |
59
- | 30 | `MAP_SUCKER_TOKEN` | nana-suckers | `JBSucker.mapToken` |
60
- | 31 | `DEPLOY_SUCKERS` | nana-suckers | `JBSuckerRegistry.deploySuckersFor` |
61
- | 32 | `SUCKER_SAFETY` | nana-suckers | `JBSucker.enableEmergencyHatchFor` |
62
- | 33 | `SET_SUCKER_DEPRECATION` | nana-suckers | `JBSucker.setDeprecation` |
45
+ | 16 | `ADD_TERMINALS` | nana-core | `JBDirectory.setPrimaryTerminalOf` (implicit add) |
46
+ | 17 | `SET_PRIMARY_TERMINAL` | nana-core | `JBDirectory.setPrimaryTerminalOf` |
47
+ | 18 | `USE_ALLOWANCE` | nana-core | `JBMultiTerminal.useAllowanceOf` |
48
+ | 19 | `SET_SPLIT_GROUPS` | nana-core | `JBController.setSplitGroupsOf` |
49
+ | 20 | `ADD_PRICE_FEED` | nana-core | `JBController.addPriceFeedFor` |
50
+ | 21 | `ADD_ACCOUNTING_CONTEXTS` | nana-core | `JBMultiTerminal.addAccountingContextsFor` |
51
+ | 22 | `SET_TOKEN_METADATA` | nana-core | `JBController.setTokenMetadataOf` |
52
+ | 23 | `ADJUST_721_TIERS` | nana-721-hook | `JB721TiersHook.adjustTiers` |
53
+ | 24 | `SET_721_METADATA` | nana-721-hook | `JB721TiersHook.setMetadata` |
54
+ | 25 | `MINT_721` | nana-721-hook | `JB721TiersHook.mintFor` |
55
+ | 26 | `SET_721_DISCOUNT_PERCENT` | nana-721-hook | `JB721TiersHook.setDiscountPercentOf` |
56
+ | 27 | `SET_BUYBACK_TWAP` | nana-buyback-hook | `JBBuybackHook.setTwapWindowOf` |
57
+ | 28 | `SET_BUYBACK_POOL` | nana-buyback-hook | `JBBuybackHook.setPoolFor` |
58
+ | 29 | `SET_BUYBACK_HOOK` | nana-buyback-hook | `JBBuybackHookRegistry.setHookFor` + `lockHookFor` |
59
+ | 30 | `SET_ROUTER_TERMINAL` | nana-router-terminal | `JBRouterTerminalRegistry.setTerminalFor` + `lockTerminalFor` |
60
+ | 31 | `MAP_SUCKER_TOKEN` | nana-suckers | `JBSucker.mapToken` |
61
+ | 32 | `DEPLOY_SUCKERS` | nana-suckers | `JBSuckerRegistry.deploySuckersFor` |
62
+ | 33 | `SUCKER_SAFETY` | nana-suckers | `JBSucker.enableEmergencyHatchFor` |
63
+ | 34 | `SET_SUCKER_DEPRECATION` | nana-suckers | `JBSucker.setDeprecation` |
63
64
 
64
65
  ## Dependencies
65
66
 
@@ -1,13 +1,13 @@
1
1
  # Audit Instructions -- nana-permission-ids-v6
2
2
 
3
- You are auditing a constants-only library that defines all permission IDs used across the Juicebox V6 ecosystem. The library has no state, no functions, no constructors, and no dependencies. The entire audit surface is the correctness and consistency of 33 `uint8` constants. Read [RISKS.md](./RISKS.md) first -- it documents all known risks and trust assumptions. Then come back here.
3
+ You are auditing a constants-only library that defines all permission IDs used across the Juicebox V6 ecosystem. The library has no state, no functions, no constructors, and no dependencies. The entire audit surface is the correctness and consistency of 34 `uint8` constants. Read [RISKS.md](./RISKS.md) first -- it documents all known risks and trust assumptions. Then come back here.
4
4
 
5
5
  ## Quick Verification
6
6
 
7
- Run this one-liner from the repo root to verify all 33 permission IDs are unique, sequential (1-33), and have no gaps or duplicates:
7
+ Run this one-liner from the repo root to verify all 34 permission IDs are unique, sequential (1-34), and have no gaps or duplicates:
8
8
 
9
9
  ```bash
10
- grep 'constant.*=' src/JBPermissionIds.sol | sed 's/.*= \([0-9]*\).*/\1/' | sort -n | diff - <(seq 1 33) && echo "PASS: All 33 IDs are unique and sequential (1-33)" || echo "FAIL: ID mismatch detected"
10
+ grep 'constant.*=' src/JBPermissionIds.sol | sed 's/.*= \([0-9]*\).*/\1/' | sort -n | diff - <(seq 1 34) && echo "PASS: All 34 IDs are unique and sequential (1-34)" || echo "FAIL: ID mismatch detected"
11
11
  ```
12
12
 
13
13
  If `PASS` is printed, the constants are correctly assigned. If `FAIL` is printed, inspect the diff output to identify which IDs are missing, duplicated, or out of range.
@@ -18,12 +18,12 @@ From `foundry.toml`:
18
18
 
19
19
  | Setting | Value |
20
20
  |---------|-------|
21
- | Solidity version | `^0.8.28` |
21
+ | Solidity version | `0.8.28` |
22
22
  | EVM target | `cancun` |
23
23
  | Optimizer | Enabled, 200 runs |
24
- | Pragma in source | `^0.8.0` (flexible, compiled with ^0.8.28) |
24
+ | Pragma in source | `^0.8.0` (flexible, compiled with 0.8.28) |
25
25
 
26
- Note: The library pragma is `^0.8.0` rather than a fixed version, since consuming contracts may compile it with their own Solidity version. The `foundry.toml` pins `^0.8.28` for local builds.
26
+ Note: The library pragma is `^0.8.0` rather than a fixed version, since consuming contracts may compile it with their own Solidity version. The `foundry.toml` pins `0.8.28` for local builds.
27
27
 
28
28
  ## Previous Audit Findings
29
29
 
@@ -42,14 +42,14 @@ Both findings were comment-only inaccuracies with no security impact. All 5 inva
42
42
 
43
43
  **In scope:**
44
44
  ```
45
- src/JBPermissionIds.sol # Constants library (~67 lines, 33 permission IDs)
45
+ src/JBPermissionIds.sol # Constants library (~69 lines, 34 permission IDs)
46
46
  ```
47
47
 
48
48
  **Out of scope:** All consuming contracts (nana-core, nana-721-hook, nana-buyback-hook, nana-router-terminal, nana-suckers, revnet-core, croptop-core). The constants library has no dependencies.
49
49
 
50
50
  ## Architecture
51
51
 
52
- `JBPermissionIds` is a Solidity library containing 33 `uint8 internal constant` values numbered 1 through 33. These IDs are used with `JBPermissions.setPermissionsFor()` to grant scoped access to protocol functions. The permission system stores permissions as a 256-bit packed integer (`uint256`), with each bit corresponding to a permission ID.
52
+ `JBPermissionIds` is a Solidity library containing 34 `uint8 internal constant` values numbered 1 through 34. These IDs are used with `JBPermissions.setPermissionsFor()` to grant scoped access to protocol functions. The permission system stores permissions as a 256-bit packed integer (`uint256`), with each bit corresponding to a permission ID.
53
53
 
54
54
  ### Permission System Overview
55
55
 
@@ -59,8 +59,8 @@ permissionsOf[operator][account][projectId] => uint256 (one bit per permission I
59
59
 
60
60
  - **Bit 0 (ID 0):** Reserved, cannot be set. `JBPermissions` reverts if bit 0 is included.
61
61
  - **Bit 1 (ID 1, ROOT):** Grants all permissions across all contracts. Cannot be granted for wildcard `projectId = 0`.
62
- - **Bits 2-33:** Individual permissions, each gating a specific function (or set of functions) in the ecosystem.
63
- - **Bits 34-255:** Unassigned, available for future extensions.
62
+ - **Bits 2-34:** Individual permissions, each gating a specific function (or set of functions) in the ecosystem.
63
+ - **Bits 35-255:** Unassigned, available for future extensions.
64
64
 
65
65
  ### All Permission IDs
66
66
 
@@ -81,24 +81,25 @@ permissionsOf[operator][account][projectId] => uint256 (one bit per permission I
81
81
  | 13 | `TRANSFER_CREDITS` | `JBController.transferCreditsFrom` | **Token holder** |
82
82
  | 14 | `SET_CONTROLLER` | `JBDirectory.setControllerOf` | Project owner |
83
83
  | 15 | `SET_TERMINALS` | `JBDirectory.setTerminalsOf` (WARNING: can remove primary terminal) | Project owner |
84
- | 16 | `SET_PRIMARY_TERMINAL` | `JBDirectory.setPrimaryTerminalOf` | Project owner |
85
- | 17 | `USE_ALLOWANCE` | `JBMultiTerminal.useAllowanceOf` | Project owner |
86
- | 18 | `SET_SPLIT_GROUPS` | `JBController.setSplitGroupsOf` | Project owner |
87
- | 19 | `ADD_PRICE_FEED` | `JBController.addPriceFeedFor` (not `JBPrices` directly) | Project owner |
88
- | 20 | `ADD_ACCOUNTING_CONTEXTS` | `JBMultiTerminal.addAccountingContextsFor` | Project owner |
89
- | 21 | `SET_TOKEN_METADATA` | `JBController.setTokenMetadataOf` | Project owner |
90
- | 22 | `ADJUST_721_TIERS` | `JB721TiersHook.adjustTiers` | Hook owner |
91
- | 23 | `SET_721_METADATA` | `JB721TiersHook.setMetadata` | Hook owner |
92
- | 24 | `MINT_721` | `JB721TiersHook.mintFor` | Hook owner |
93
- | 25 | `SET_721_DISCOUNT_PERCENT` | `JB721TiersHook.setDiscountPercentOf` | Hook owner |
94
- | 26 | `SET_BUYBACK_TWAP` | `JBBuybackHook.setTwapWindowOf` | Project owner |
95
- | 27 | `SET_BUYBACK_POOL` | `JBBuybackHook.setPoolFor` | Project owner |
96
- | 28 | `SET_BUYBACK_HOOK` | `JBBuybackHookRegistry.setHookFor` + `lockHookFor` | Project owner |
97
- | 29 | `SET_ROUTER_TERMINAL` | `JBRouterTerminalRegistry.setTerminalFor` + `lockTerminalFor` | Project owner |
98
- | 30 | `MAP_SUCKER_TOKEN` | `JBSucker.mapToken` | Project owner |
99
- | 31 | `DEPLOY_SUCKERS` | `JBSuckerRegistry.deploySuckersFor` | Project owner |
100
- | 32 | `SUCKER_SAFETY` | `JBSucker.enableEmergencyHatchFor` | Project owner |
101
- | 33 | `SET_SUCKER_DEPRECATION` | `JBSucker.setDeprecation` | Project owner |
84
+ | 16 | `ADD_TERMINALS` | `JBDirectory.setPrimaryTerminalOf` (implicit add) | Project owner |
85
+ | 17 | `SET_PRIMARY_TERMINAL` | `JBDirectory.setPrimaryTerminalOf` | Project owner |
86
+ | 18 | `USE_ALLOWANCE` | `JBMultiTerminal.useAllowanceOf` | Project owner |
87
+ | 19 | `SET_SPLIT_GROUPS` | `JBController.setSplitGroupsOf` | Project owner |
88
+ | 20 | `ADD_PRICE_FEED` | `JBController.addPriceFeedFor` (not `JBPrices` directly) | Project owner |
89
+ | 21 | `ADD_ACCOUNTING_CONTEXTS` | `JBMultiTerminal.addAccountingContextsFor` | Project owner |
90
+ | 22 | `SET_TOKEN_METADATA` | `JBController.setTokenMetadataOf` | Project owner |
91
+ | 23 | `ADJUST_721_TIERS` | `JB721TiersHook.adjustTiers` | Hook owner |
92
+ | 24 | `SET_721_METADATA` | `JB721TiersHook.setMetadata` | Hook owner |
93
+ | 25 | `MINT_721` | `JB721TiersHook.mintFor` | Hook owner |
94
+ | 26 | `SET_721_DISCOUNT_PERCENT` | `JB721TiersHook.setDiscountPercentOf` | Hook owner |
95
+ | 27 | `SET_BUYBACK_TWAP` | `JBBuybackHook.setTwapWindowOf` | Project owner |
96
+ | 28 | `SET_BUYBACK_POOL` | `JBBuybackHook.setPoolFor` | Project owner |
97
+ | 29 | `SET_BUYBACK_HOOK` | `JBBuybackHookRegistry.setHookFor` + `lockHookFor` | Project owner |
98
+ | 30 | `SET_ROUTER_TERMINAL` | `JBRouterTerminalRegistry.setTerminalFor` + `lockTerminalFor` | Project owner |
99
+ | 31 | `MAP_SUCKER_TOKEN` | `JBSucker.mapToken` | Project owner |
100
+ | 32 | `DEPLOY_SUCKERS` | `JBSuckerRegistry.deploySuckersFor` | Project owner |
101
+ | 33 | `SUCKER_SAFETY` | `JBSucker.enableEmergencyHatchFor` | Project owner |
102
+ | 34 | `SET_SUCKER_DEPRECATION` | `JBSucker.setDeprecation` | Project owner |
102
103
 
103
104
  ## Priority Audit Areas
104
105
 
@@ -106,19 +107,19 @@ permissionsOf[operator][account][projectId] => uint256 (one bit per permission I
106
107
 
107
108
  Every permission ID must be unique. Two different constants with the same numeric value would cause one permission grant to silently authorize a different action. Verify:
108
109
 
109
- - All 33 constants have distinct values.
110
- - Values are sequential from 1 to 33 with no gaps and no duplicates.
110
+ - All 34 constants have distinct values.
111
+ - Values are sequential from 1 to 34 with no gaps and no duplicates.
111
112
  - No other file in the ecosystem defines additional permission ID constants that could collide with these.
112
113
 
113
114
  ### 2. ID-to-Function Mapping Correctness
114
115
 
115
116
  Each constant's doc comment claims it gates a specific function. Verify against the actual source code of each consuming contract:
116
117
 
117
- - **nana-core-v6**: IDs 2-21 should match the `_requirePermissionFrom` calls in `JBController`, `JBMultiTerminal`, and `JBDirectory`.
118
- - **nana-721-hook-v6**: IDs 22-25 should match permission checks in `JB721TiersHook`.
119
- - **nana-buyback-hook-v6**: IDs 26-28 should match permission checks in `JBBuybackHook` and `JBBuybackHookRegistry`.
120
- - **nana-router-terminal-v6**: ID 29 should match permission checks in `JBRouterTerminalRegistry`.
121
- - **nana-suckers-v6**: IDs 30-33 should match permission checks in `JBSucker` and `JBSuckerRegistry`.
118
+ - **nana-core-v6**: IDs 2-22 should match the `_requirePermissionFrom` calls in `JBController`, `JBMultiTerminal`, and `JBDirectory`.
119
+ - **nana-721-hook-v6**: IDs 23-26 should match permission checks in `JB721TiersHook`.
120
+ - **nana-buyback-hook-v6**: IDs 27-29 should match permission checks in `JBBuybackHook` and `JBBuybackHookRegistry`.
121
+ - **nana-router-terminal-v6**: ID 30 should match permission checks in `JBRouterTerminalRegistry`.
122
+ - **nana-suckers-v6**: IDs 31-34 should match permission checks in `JBSucker` and `JBSuckerRegistry`.
122
123
 
123
124
  ### 3. Holder-Scoped vs Owner-Scoped Permissions
124
125
 
@@ -135,8 +136,8 @@ Verify that no consuming contract incorrectly checks these against the project o
135
136
 
136
137
  Two IDs intentionally gate both a "set" and a "lock" operation:
137
138
 
138
- - **SET_BUYBACK_HOOK (28)**: Gates both `setHookFor` (configurable) and `lockHookFor` (permanent). An operator with this permission can permanently lock the hook configuration.
139
- - **SET_ROUTER_TERMINAL (29)**: Gates both `setTerminalFor` (configurable) and `lockTerminalFor` (permanent). An operator with this permission can permanently lock the terminal configuration.
139
+ - **SET_BUYBACK_HOOK (29)**: Gates both `setHookFor` (configurable) and `lockHookFor` (permanent). An operator with this permission can permanently lock the hook configuration.
140
+ - **SET_ROUTER_TERMINAL (30)**: Gates both `setTerminalFor` (configurable) and `lockTerminalFor` (permanent). An operator with this permission can permanently lock the terminal configuration.
140
141
 
141
142
  Verify that project owners are aware of the locking implication when granting these permissions. The source code includes `@dev` documentation, but this is a significant trust escalation.
142
143
 
@@ -159,11 +160,11 @@ The source comment warns: "Be careful - `SET_TERMINALS` can be used to remove th
159
160
 
160
161
  ## Invariants to Verify
161
162
 
162
- 1. **Uniqueness**: All 33 constants have unique values in the range [1, 33].
163
+ 1. **Uniqueness**: All 34 constants have unique values in the range [1, 34].
163
164
  2. **Completeness**: Every `_requirePermissionFrom` call in the ecosystem uses one of these constants (no magic numbers).
164
165
  3. **Type consistency**: All constants are `uint8`, matching the parameter type of `JBPermissions.hasPermission`.
165
166
  4. **No ID 0**: No constant has value 0 (reserved and forbidden by `JBPermissions`).
166
- 5. **Sequential assignment**: IDs are assigned 1 through 33 with no gaps.
167
+ 5. **Sequential assignment**: IDs are assigned 1 through 34 with no gaps.
167
168
 
168
169
  ## Testing Setup
169
170
 
package/CHANGE_LOG.md CHANGED
@@ -6,7 +6,7 @@ This document describes all changes between `nana-permission-ids` (v5) and `nana
6
6
 
7
7
  - **All numeric IDs shifted** — the insertion of `LAUNCH_RULESETS` at ID 3 cascades through every subsequent permission. Any code using hardcoded numeric values will break.
8
8
  - **Two permissions split**: `QUEUE_RULESETS` → `QUEUE_RULESETS` + `LAUNCH_RULESETS`; `SUCKER_SAFETY` → `SUCKER_SAFETY` + `SET_SUCKER_DEPRECATION`.
9
- - **5 new permissions** added: `LAUNCH_RULESETS` (3), `SET_TOKEN_METADATA` (21), `SET_BUYBACK_HOOK` (28), `SET_ROUTER_TERMINAL` (29), `SET_SUCKER_DEPRECATION` (33).
9
+ - **6 new permissions** added: `LAUNCH_RULESETS` (3), `ADD_TERMINALS` (16), `SET_TOKEN_METADATA` (22), `SET_BUYBACK_HOOK` (29), `SET_ROUTER_TERMINAL` (30), `SET_SUCKER_DEPRECATION` (34).
10
10
  - **2 swap terminal permissions removed**: `ADD_SWAP_TERMINAL_POOL` and `ADD_SWAP_TERMINAL_TWAP_PARAMS` (swap terminal replaced by router terminal).
11
11
 
12
12
  > **⚠️ WARNING: All numeric permission IDs have shifted.** If your contracts, scripts, or frontends hardcode permission ID numbers (e.g., `permissions.setPermissionsFor(..., 3, ...)` for `CASH_OUT_TOKENS`), they MUST be updated. `CASH_OUT_TOKENS` moved from 3 → 4, `SEND_PAYOUTS` from 4 → 5, and so on. Always reference the named constants from `JBPermissionIds` rather than raw numbers.
@@ -35,20 +35,20 @@ The insertion of `LAUNCH_RULESETS` at ID 3 pushed every subsequent permission ID
35
35
  | `TRANSFER_CREDITS` | 12 | 13 |
36
36
  | `SET_CONTROLLER` | 13 | 14 |
37
37
  | `SET_TERMINALS` | 14 | 15 |
38
- | `SET_PRIMARY_TERMINAL` | 15 | 16 |
39
- | `USE_ALLOWANCE` | 16 | 17 |
40
- | `SET_SPLIT_GROUPS` | 17 | 18 |
41
- | `ADD_PRICE_FEED` | 18 | 19 |
42
- | `ADD_ACCOUNTING_CONTEXTS` | 19 | 20 |
43
- | `ADJUST_721_TIERS` | 20 | 22 |
44
- | `SET_721_METADATA` | 21 | 23 |
45
- | `MINT_721` | 22 | 24 |
46
- | `SET_721_DISCOUNT_PERCENT` | 23 | 25 |
47
- | `SET_BUYBACK_TWAP` | 24 | 26 |
48
- | `SET_BUYBACK_POOL` | 25 | 27 |
49
- | `MAP_SUCKER_TOKEN` | 28 | 30 |
50
- | `DEPLOY_SUCKERS` | 29 | 31 |
51
- | `SUCKER_SAFETY` | 30 | 32 |
38
+ | `SET_PRIMARY_TERMINAL` | 15 | 17 |
39
+ | `USE_ALLOWANCE` | 16 | 18 |
40
+ | `SET_SPLIT_GROUPS` | 17 | 19 |
41
+ | `ADD_PRICE_FEED` | 18 | 20 |
42
+ | `ADD_ACCOUNTING_CONTEXTS` | 19 | 21 |
43
+ | `ADJUST_721_TIERS` | 20 | 23 |
44
+ | `SET_721_METADATA` | 21 | 24 |
45
+ | `MINT_721` | 22 | 25 |
46
+ | `SET_721_DISCOUNT_PERCENT` | 23 | 26 |
47
+ | `SET_BUYBACK_TWAP` | 24 | 27 |
48
+ | `SET_BUYBACK_POOL` | 25 | 28 |
49
+ | `MAP_SUCKER_TOKEN` | 28 | 31 |
50
+ | `DEPLOY_SUCKERS` | 29 | 32 |
51
+ | `SUCKER_SAFETY` | 30 | 33 |
52
52
 
53
53
  ### `QUEUE_RULESETS` split into two permissions
54
54
 
@@ -63,8 +63,8 @@ In v5, `QUEUE_RULESETS` (2) granted permission to call both `JBController.queueR
63
63
 
64
64
  In v5, `SUCKER_SAFETY` (30) granted permission to call both `BPSucker.enableEmergencyHatchFor` and `BPSucker.setDeprecation`. In v6, these are separate:
65
65
 
66
- - `SUCKER_SAFETY` (32) -- only `JBSucker.enableEmergencyHatchFor`
67
- - `SET_SUCKER_DEPRECATION` (33) -- only `JBSucker.setDeprecation`
66
+ - `SUCKER_SAFETY` (33) -- only `JBSucker.enableEmergencyHatchFor`
67
+ - `SET_SUCKER_DEPRECATION` (34) -- only `JBSucker.setDeprecation`
68
68
 
69
69
  ### Swap terminal permissions removed
70
70
 
@@ -75,7 +75,7 @@ The following permissions from `nana-swap-terminal` no longer exist in v6:
75
75
  | `ADD_SWAP_TERMINAL_POOL` | 26 | Was for `JBSwapTerminal.addDefaultPool` |
76
76
  | `ADD_SWAP_TERMINAL_TWAP_PARAMS` | 27 | Was for `JBSwapTerminal.addTwapParamsFor` |
77
77
 
78
- > **Cross-repo impact**: `nana-router-terminal-v6` (the replacement for swap terminal) uses the new `SET_ROUTER_TERMINAL` (29) permission instead.
78
+ > **Cross-repo impact**: `nana-router-terminal-v6` (the replacement for swap terminal) uses the new `SET_ROUTER_TERMINAL` (30) permission instead.
79
79
 
80
80
  ### Contract prefix rename (suckers)
81
81
 
@@ -96,19 +96,23 @@ In v5, the comment stated this gates both `JBBuybackHook.setTwapWindowOf` and `J
96
96
 
97
97
  New permission split from `QUEUE_RULESETS`. Gates `JBController.launchRulesetsFor` independently.
98
98
 
99
- ### `SET_TOKEN_METADATA` (21)
99
+ ### `ADD_TERMINALS` (16)
100
100
 
101
- New core permission. Gates `JBController.setMetadataOf` for setting project token metadata.
101
+ New core permission. Gates `JBDirectory.setPrimaryTerminalOf` when it implicitly adds a new terminal that is not already in the project's terminal list. This is a narrower alternative to `SET_TERMINALS` (15), which replaces the entire terminal list.
102
102
 
103
- ### `SET_BUYBACK_HOOK` (28)
103
+ ### `SET_TOKEN_METADATA` (22)
104
+
105
+ New core permission. Gates `JBController.setTokenMetadataOf` for setting project token metadata.
106
+
107
+ ### `SET_BUYBACK_HOOK` (29)
104
108
 
105
109
  New buyback hook permission. Gates both `JBBuybackHookRegistry.setHookFor` and `JBBuybackHookRegistry.lockHookFor`. Note: granting this permission allows the operator to permanently lock the hook configuration.
106
110
 
107
- ### `SET_ROUTER_TERMINAL` (29)
111
+ ### `SET_ROUTER_TERMINAL` (30)
108
112
 
109
113
  New router terminal permission. Gates both `JBRouterTerminalRegistry.setTerminalFor` and `JBRouterTerminalRegistry.lockTerminalFor`. Note: granting this permission allows the operator to permanently lock the terminal configuration.
110
114
 
111
- ### `SET_SUCKER_DEPRECATION` (33)
115
+ ### `SET_SUCKER_DEPRECATION` (34)
112
116
 
113
117
  New permission split from `SUCKER_SAFETY`. Gates `JBSucker.setDeprecation` independently.
114
118
 
@@ -133,23 +137,24 @@ New permission split from `SUCKER_SAFETY`. Gates `JBSucker.setDeprecation` indep
133
137
  | `TRANSFER_CREDITS` | 12 | `TRANSFER_CREDITS` | 13 | ID changed |
134
138
  | `SET_CONTROLLER` | 13 | `SET_CONTROLLER` | 14 | ID changed |
135
139
  | `SET_TERMINALS` | 14 | `SET_TERMINALS` | 15 | ID changed |
136
- | `SET_PRIMARY_TERMINAL` | 15 | `SET_PRIMARY_TERMINAL` | 16 | ID changed |
137
- | `USE_ALLOWANCE` | 16 | `USE_ALLOWANCE` | 17 | ID changed |
138
- | `SET_SPLIT_GROUPS` | 17 | `SET_SPLIT_GROUPS` | 18 | ID changed |
139
- | `ADD_PRICE_FEED` | 18 | `ADD_PRICE_FEED` | 19 | ID changed |
140
- | `ADD_ACCOUNTING_CONTEXTS` | 19 | `ADD_ACCOUNTING_CONTEXTS` | 20 | ID changed |
141
- | -- | -- | `SET_TOKEN_METADATA` | 21 | **New** |
142
- | `ADJUST_721_TIERS` | 20 | `ADJUST_721_TIERS` | 22 | ID changed |
143
- | `SET_721_METADATA` | 21 | `SET_721_METADATA` | 23 | ID changed |
144
- | `MINT_721` | 22 | `MINT_721` | 24 | ID changed |
145
- | `SET_721_DISCOUNT_PERCENT` | 23 | `SET_721_DISCOUNT_PERCENT` | 25 | ID changed |
146
- | `SET_BUYBACK_TWAP` | 24 | `SET_BUYBACK_TWAP` | 26 | ID changed, comment narrowed |
147
- | `SET_BUYBACK_POOL` | 25 | `SET_BUYBACK_POOL` | 27 | ID changed |
140
+ | -- | -- | `ADD_TERMINALS` | 16 | **New** |
141
+ | `SET_PRIMARY_TERMINAL` | 15 | `SET_PRIMARY_TERMINAL` | 17 | ID changed |
142
+ | `USE_ALLOWANCE` | 16 | `USE_ALLOWANCE` | 18 | ID changed |
143
+ | `SET_SPLIT_GROUPS` | 17 | `SET_SPLIT_GROUPS` | 19 | ID changed |
144
+ | `ADD_PRICE_FEED` | 18 | `ADD_PRICE_FEED` | 20 | ID changed |
145
+ | `ADD_ACCOUNTING_CONTEXTS` | 19 | `ADD_ACCOUNTING_CONTEXTS` | 21 | ID changed |
146
+ | -- | -- | `SET_TOKEN_METADATA` | 22 | **New** |
147
+ | `ADJUST_721_TIERS` | 20 | `ADJUST_721_TIERS` | 23 | ID changed |
148
+ | `SET_721_METADATA` | 21 | `SET_721_METADATA` | 24 | ID changed |
149
+ | `MINT_721` | 22 | `MINT_721` | 25 | ID changed |
150
+ | `SET_721_DISCOUNT_PERCENT` | 23 | `SET_721_DISCOUNT_PERCENT` | 26 | ID changed |
151
+ | `SET_BUYBACK_TWAP` | 24 | `SET_BUYBACK_TWAP` | 27 | ID changed, comment narrowed |
152
+ | `SET_BUYBACK_POOL` | 25 | `SET_BUYBACK_POOL` | 28 | ID changed |
148
153
  | `ADD_SWAP_TERMINAL_POOL` | 26 | -- | -- | **Removed** |
149
154
  | `ADD_SWAP_TERMINAL_TWAP_PARAMS` | 27 | -- | -- | **Removed** |
150
- | -- | -- | `SET_BUYBACK_HOOK` | 28 | **New** |
151
- | -- | -- | `SET_ROUTER_TERMINAL` | 29 | **New** |
152
- | `MAP_SUCKER_TOKEN` | 28 | `MAP_SUCKER_TOKEN` | 30 | ID changed, `BPSucker` → `JBSucker` |
153
- | `DEPLOY_SUCKERS` | 29 | `DEPLOY_SUCKERS` | 31 | ID changed, `BPSuckerRegistry` → `JBSuckerRegistry` |
154
- | `SUCKER_SAFETY` | 30 | `SUCKER_SAFETY` | 32 | ID changed, narrowed (no longer includes deprecation) |
155
- | -- | -- | `SET_SUCKER_DEPRECATION` | 33 | **New** (split from `SUCKER_SAFETY`) |
155
+ | -- | -- | `SET_BUYBACK_HOOK` | 29 | **New** |
156
+ | -- | -- | `SET_ROUTER_TERMINAL` | 30 | **New** |
157
+ | `MAP_SUCKER_TOKEN` | 28 | `MAP_SUCKER_TOKEN` | 31 | ID changed, `BPSucker` → `JBSucker` |
158
+ | `DEPLOY_SUCKERS` | 29 | `DEPLOY_SUCKERS` | 32 | ID changed, `BPSuckerRegistry` → `JBSuckerRegistry` |
159
+ | `SUCKER_SAFETY` | 30 | `SUCKER_SAFETY` | 33 | ID changed, narrowed (no longer includes deprecation) |
160
+ | -- | -- | `SET_SUCKER_DEPRECATION` | 34 | **New** (split from `SUCKER_SAFETY`) |
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Juicebox Permission IDs
2
2
 
3
- The single source of truth for access control across the Juicebox V6 ecosystem. This library defines 33 `uint8` constants -- one for each permission ID used with [`JBPermissions`](https://github.com/Bananapus/nana-core-v6/blob/main/src/JBPermissions.sol) -- ensuring every contract references the same IDs.
3
+ The single source of truth for access control across the Juicebox V6 ecosystem. This library defines 34 `uint8` constants -- one for each permission ID used with [`JBPermissions`](https://github.com/Bananapus/nana-core-v6/blob/main/src/JBPermissions.sol) -- ensuring every contract references the same IDs.
4
4
 
5
5
  ## How permissions work
6
6
 
@@ -16,13 +16,13 @@ permissionsOf[operator][account][projectId] => uint256 (packed bits)
16
16
 
17
17
  | Contract | Description |
18
18
  |----------|-------------|
19
- | `JBPermissionIds` | Solidity library with 33 `uint8 internal constant` permission IDs (values 1--33). No state, no functions, no dependencies. Pragma `^0.8.0` for maximum compatibility. |
19
+ | `JBPermissionIds` | Solidity library with 34 `uint8 internal constant` permission IDs (values 1--34). No state, no functions, no dependencies. Pragma `^0.8.0` for maximum compatibility. |
20
20
 
21
21
  ## Repository Layout
22
22
 
23
23
  ```
24
24
  src/
25
- └── JBPermissionIds.sol ── 33 uint8 constants (the only source file)
25
+ └── JBPermissionIds.sol ── 34 uint8 constants (the only source file)
26
26
  ```
27
27
 
28
28
  No tests, interfaces, or deployment scripts -- this repo is a pure constant library.
@@ -35,7 +35,7 @@ No tests, interfaces, or deployment scripts -- this repo is a pure constant libr
35
35
  |----|------|-------------|
36
36
  | 1 | `ROOT` | Grants **all** permissions across every contract. An operator with ROOT can call any permissioned function on behalf of the account. Must be granted with extreme care. See [Gotchas](#gotchas) for restrictions. |
37
37
 
38
- ### Core (IDs 2--21) -- [nana-core-v6](https://github.com/Bananapus/nana-core-v6)
38
+ ### Core (IDs 2--22) -- [nana-core-v6](https://github.com/Bananapus/nana-core-v6)
39
39
 
40
40
  | ID | Name | Checked in | Description |
41
41
  |----|------|------------|-------------|
@@ -53,44 +53,45 @@ No tests, interfaces, or deployment scripts -- this repo is a pure constant libr
53
53
  | 13 | `TRANSFER_CREDITS` | `JBController.transferCreditsFrom` | Transfer a holder's internal credit balance to another address. Checked against the **token holder**. |
54
54
  | 14 | `SET_CONTROLLER` | `JBDirectory.setControllerOf` | Set a project's controller in the directory. |
55
55
  | 15 | `SET_TERMINALS` | `JBDirectory.setTerminalsOf` | Set a project's terminals. **Warning:** can remove the primary terminal. Also required by `LAUNCH_RULESETS` (ID 3). |
56
- | 16 | `SET_PRIMARY_TERMINAL` | `JBDirectory.setPrimaryTerminalOf` | Set a project's primary terminal for a given token. |
57
- | 17 | `USE_ALLOWANCE` | `JBMultiTerminal.useAllowanceOf` | Use a project's surplus allowance to send funds to an arbitrary address. |
58
- | 18 | `SET_SPLIT_GROUPS` | `JBController.setSplitGroupsOf` | Set a project's split groups (how payouts and reserved tokens are distributed). |
59
- | 19 | `ADD_PRICE_FEED` | `JBController.addPriceFeedFor` | Add a price feed for a project. The controller checks this permission before calling `JBPrices.addPriceFeedFor`. |
60
- | 20 | `ADD_ACCOUNTING_CONTEXTS` | `JBMultiTerminal.addAccountingContextsFor` | Add accounting contexts (accepted tokens) to a terminal for a project. |
61
- | 21 | `SET_TOKEN_METADATA` | `JBController.setTokenMetadataOf` | Set a project token's name and symbol. Checked against the project owner. |
56
+ | 16 | `ADD_TERMINALS` | `JBDirectory.setPrimaryTerminalOf` | Add a new terminal to a project when `setPrimaryTerminalOf` implicitly adds it. |
57
+ | 17 | `SET_PRIMARY_TERMINAL` | `JBDirectory.setPrimaryTerminalOf` | Set a project's primary terminal for a given token. |
58
+ | 18 | `USE_ALLOWANCE` | `JBMultiTerminal.useAllowanceOf` | Use a project's surplus allowance to send funds to an arbitrary address. |
59
+ | 19 | `SET_SPLIT_GROUPS` | `JBController.setSplitGroupsOf` | Set a project's split groups (how payouts and reserved tokens are distributed). |
60
+ | 20 | `ADD_PRICE_FEED` | `JBController.addPriceFeedFor` | Add a price feed for a project. The controller checks this permission before calling `JBPrices.addPriceFeedFor`. |
61
+ | 21 | `ADD_ACCOUNTING_CONTEXTS` | `JBMultiTerminal.addAccountingContextsFor` | Add accounting contexts (accepted tokens) to a terminal for a project. |
62
+ | 22 | `SET_TOKEN_METADATA` | `JBController.setTokenMetadataOf` | Set a project token's name and symbol. Checked against the project owner. |
62
63
 
63
- ### 721 Hook (IDs 22--25) -- [nana-721-hook-v6](https://github.com/Bananapus/nana-721-hook-v6)
64
+ ### 721 Hook (IDs 23--26) -- [nana-721-hook-v6](https://github.com/Bananapus/nana-721-hook-v6)
64
65
 
65
66
  | ID | Name | Checked in | Description |
66
67
  |----|------|------------|-------------|
67
- | 22 | `ADJUST_721_TIERS` | `JB721TiersHook.adjustTiers` | Add or remove NFT tiers. Also used by `CTPublisher` and `CTProjectOwner` in croptop-core-v6. |
68
- | 23 | `SET_721_METADATA` | `JB721TiersHook.setMetadata` | Set the metadata (base URI, contract URI, token URI resolver) for a 721 hook. |
69
- | 24 | `MINT_721` | `JB721TiersHook.mintFor` | Manually mint NFTs from specific tiers to a beneficiary. |
70
- | 25 | `SET_721_DISCOUNT_PERCENT` | `JB721TiersHook.setDiscountPercentOf` | Set the discount percent for one or more NFT tiers. |
68
+ | 23 | `ADJUST_721_TIERS` | `JB721TiersHook.adjustTiers` | Add or remove NFT tiers. Also used by `CTPublisher` and `CTProjectOwner` in croptop-core-v6. |
69
+ | 24 | `SET_721_METADATA` | `JB721TiersHook.setMetadata` | Set the metadata (base URI, contract URI, token URI resolver) for a 721 hook. |
70
+ | 25 | `MINT_721` | `JB721TiersHook.mintFor` | Manually mint NFTs from specific tiers to a beneficiary. |
71
+ | 26 | `SET_721_DISCOUNT_PERCENT` | `JB721TiersHook.setDiscountPercentOf` | Set the discount percent for one or more NFT tiers. |
71
72
 
72
- ### Buyback Hook (IDs 26--28) -- [nana-buyback-hook-v6](https://github.com/Bananapus/nana-buyback-hook-v6)
73
+ ### Buyback Hook (IDs 27--29) -- [nana-buyback-hook-v6](https://github.com/Bananapus/nana-buyback-hook-v6)
73
74
 
74
75
  | ID | Name | Checked in | Description |
75
76
  |----|------|------------|-------------|
76
- | 26 | `SET_BUYBACK_TWAP` | `JBBuybackHook.setTwapWindowOf` | Set the TWAP (time-weighted average price) oracle window for a project's buyback hook. |
77
- | 27 | `SET_BUYBACK_POOL` | `JBBuybackHook.setPoolFor`, `JBBuybackHook.initializePoolFor`, `JBBuybackHookRegistry.setPoolFor`, `JBBuybackHookRegistry.initializePoolFor` | Set the Uniswap pool for a project's buyback hook. |
78
- | 28 | `SET_BUYBACK_HOOK` | `JBBuybackHookRegistry.setHookFor`, `JBBuybackHookRegistry.lockHookFor` | Set or lock the buyback hook in the registry. Also used by `REVDeployer` as an operator permission grant. |
77
+ | 27 | `SET_BUYBACK_TWAP` | `JBBuybackHook.setTwapWindowOf` | Set the TWAP (time-weighted average price) oracle window for a project's buyback hook. |
78
+ | 28 | `SET_BUYBACK_POOL` | `JBBuybackHook.setPoolFor`, `JBBuybackHook.initializePoolFor`, `JBBuybackHookRegistry.setPoolFor`, `JBBuybackHookRegistry.initializePoolFor` | Set the Uniswap pool for a project's buyback hook. |
79
+ | 29 | `SET_BUYBACK_HOOK` | `JBBuybackHookRegistry.setHookFor`, `JBBuybackHookRegistry.lockHookFor` | Set or lock the buyback hook in the registry. Also used by `REVDeployer` as an operator permission grant. |
79
80
 
80
- ### Router Terminal (ID 29) -- [nana-router-terminal-v6](https://github.com/Bananapus/nana-router-terminal-v6)
81
+ ### Router Terminal (ID 30) -- [nana-router-terminal-v6](https://github.com/Bananapus/nana-router-terminal-v6)
81
82
 
82
83
  | ID | Name | Checked in | Description |
83
84
  |----|------|------------|-------------|
84
- | 29 | `SET_ROUTER_TERMINAL` | `JBRouterTerminalRegistry.setTerminalFor`, `JBRouterTerminalRegistry.lockTerminalFor` | Set or lock the router terminal for a project. |
85
+ | 30 | `SET_ROUTER_TERMINAL` | `JBRouterTerminalRegistry.setTerminalFor`, `JBRouterTerminalRegistry.lockTerminalFor` | Set or lock the router terminal for a project. |
85
86
 
86
- ### Suckers / Omnichain (IDs 30--33) -- [nana-suckers-v6](https://github.com/Bananapus/nana-suckers-v6)
87
+ ### Suckers / Omnichain (IDs 31--34) -- [nana-suckers-v6](https://github.com/Bananapus/nana-suckers-v6)
87
88
 
88
89
  | ID | Name | Checked in | Description |
89
90
  |----|------|------------|-------------|
90
- | 30 | `MAP_SUCKER_TOKEN` | `JBSucker.mapToken` | Map an ERC-20 token to its remote chain counterpart in a sucker. Mapping is immutable once the outbox tree has entries. |
91
- | 31 | `DEPLOY_SUCKERS` | `JBSuckerRegistry.deploySuckersFor` | Deploy new sucker contracts for a project. Also checked by `JBOmnichainDeployer` and `CTDeployer`. |
92
- | 32 | `SUCKER_SAFETY` | `JBSucker.enableEmergencyHatchFor` | Enable the emergency hatch for a sucker, allowing the project owner to recover stuck tokens. |
93
- | 33 | `SET_SUCKER_DEPRECATION` | `JBSucker.setDeprecation` | Set the deprecation status of a sucker (ENABLED, DEPRECATION_PENDING, SENDING_DISABLED, DEPRECATED). |
91
+ | 31 | `MAP_SUCKER_TOKEN` | `JBSucker.mapToken` | Map an ERC-20 token to its remote chain counterpart in a sucker. Mapping is immutable once the outbox tree has entries. |
92
+ | 32 | `DEPLOY_SUCKERS` | `JBSuckerRegistry.deploySuckersFor` | Deploy new sucker contracts for a project. Also checked by `JBOmnichainDeployer` and `CTDeployer`. |
93
+ | 33 | `SUCKER_SAFETY` | `JBSucker.enableEmergencyHatchFor` | Enable the emergency hatch for a sucker, allowing the project owner to recover stuck tokens. |
94
+ | 34 | `SET_SUCKER_DEPRECATION` | `JBSucker.setDeprecation` | Set the deprecation status of a sucker (ENABLED, DEPRECATION_PENDING, SENDING_DISABLED, DEPRECATED). |
94
95
 
95
96
  ## Gotchas
96
97
 
@@ -102,7 +103,8 @@ No tests, interfaces, or deployment scripts -- this repo is a pure constant libr
102
103
  - **SET_TERMINALS can remove the primary terminal.** The source code warns about this. Replacing the terminal list can drop the primary terminal, breaking payments and cashouts.
103
104
  - **LAUNCH_RULESETS requires SET_TERMINALS.** `launchRulesetsFor` enforces both `LAUNCH_RULESETS` and `SET_TERMINALS` because it configures terminals as part of the launch.
104
105
  - **Holder vs. owner permissions.** Most permissions are checked against the project owner, but `CASH_OUT_TOKENS`, `BURN_TOKENS`, `CLAIM_TOKENS`, and `TRANSFER_CREDITS` are checked against the **token holder**. This means a holder can grant an operator permission to cash out or burn their own tokens.
105
- - **The uint8 type limits IDs to 0--255.** Currently 33 are defined (1--33), leaving room for future extensions.
106
+ - **ADD_TERMINALS (16) vs SET_TERMINALS (15).** `SET_TERMINALS` replaces the entire terminal list and can remove the primary terminal. `ADD_TERMINALS` is a narrower permission checked when `setPrimaryTerminalOf` implicitly adds a new terminal that is not already in the project's terminal list.
107
+ - **The uint8 type limits IDs to 0--255.** Currently 34 are defined (1--34), leaving room for future extensions.
106
108
 
107
109
  ## Install
108
110
 
package/RISKS.md CHANGED
@@ -5,17 +5,17 @@ Constants-only library defining permission ID values used throughout the Bananap
5
5
  ## 1. Known Risks
6
6
 
7
7
  - **ROOT permission (ID 1).** ROOT grants all permissions across every contract. Any address granted ROOT can perform any permissioned operation on any project. Should never be granted to untrusted addresses.
8
- - **SET_BUYBACK_HOOK includes lock (ID 28).** Gates both `setHookFor` and `lockHookFor`. An operator with this permission can permanently lock the buyback hook configuration.
9
- - **SET_ROUTER_TERMINAL includes lock (ID 29).** Gates both `setTerminalFor` and `lockTerminalFor`. An operator can permanently lock the router terminal.
8
+ - **SET_BUYBACK_HOOK includes lock (ID 29).** Gates both `setHookFor` and `lockHookFor`. An operator with this permission can permanently lock the buyback hook configuration.
9
+ - **SET_ROUTER_TERMINAL includes lock (ID 30).** Gates both `setTerminalFor` and `lockTerminalFor`. An operator can permanently lock the router terminal.
10
10
  - **ID collision risk.** Permission IDs are manually assigned sequential uint8 values. Adding new IDs requires coordination to avoid collision. Library is append-only.
11
11
  - **No runtime enforcement.** This library only defines constants. Enforcement happens in consuming contracts. A mismatch between the ID used here and the ID checked in a consumer would silently fail.
12
- - **High-impact permission IDs (fund-moving).** IDs that control fund flow should receive the most audit scrutiny: `ROOT` (1, grants everything), `CASH_OUT_TOKENS` (4, triggers withdrawals), `SEND_PAYOUTS` (5, triggers payout distribution), `MIGRATE_TERMINAL` (6, moves balances), `SET_TERMINALS` (15, redirects all fund flows), `USE_ALLOWANCE` (17, draws from surplus), `SET_SPLIT_GROUPS` (18, controls where payouts go). Of these, ROOT + SET_TERMINALS + MIGRATE_TERMINAL are the most dangerous — they can redirect all of a project's funds.
12
+ - **High-impact permission IDs (fund-moving).** IDs that control fund flow should receive the most audit scrutiny: `ROOT` (1, grants everything), `CASH_OUT_TOKENS` (4, triggers withdrawals), `SEND_PAYOUTS` (5, triggers payout distribution), `MIGRATE_TERMINAL` (6, moves balances), `SET_TERMINALS` (15, redirects all fund flows), `USE_ALLOWANCE` (18, draws from surplus), `SET_SPLIT_GROUPS` (19, controls where payouts go). Of these, ROOT + SET_TERMINALS + MIGRATE_TERMINAL are the most dangerous — they can redirect all of a project's funds.
13
13
  - **Wildcard `projectId=0` semantics.** When a permission is granted with `projectId=0`, it applies to ALL projects. This is used by system contracts (e.g., `REVLoans` gets `USE_ALLOWANCE` with `projectId=0`). A bug in a contract holding wildcard permissions affects every project in the ecosystem, not just one. Only system-level contracts should hold wildcard permissions.
14
14
 
15
15
  ## 2. Design Notes
16
16
 
17
17
  - Permission 0 is reserved and cannot be set.
18
- - IDs are `uint8` (0-255), with 1-33 currently assigned.
19
- - IDs 34-255 are available for future ecosystem extensions.
20
- - IDs 34-255 are available for ecosystem extensions. Third-party contracts can define their own permission IDs in this range, but must coordinate to avoid collisions. No on-chain registry exists for custom IDs — collision detection is purely social.
18
+ - IDs are `uint8` (0-255), with 1-34 currently assigned.
19
+ - IDs 35-255 are available for future ecosystem extensions.
20
+ - IDs 35-255 are available for ecosystem extensions. Third-party contracts can define their own permission IDs in this range, but must coordinate to avoid collisions. No on-chain registry exists for custom IDs — collision detection is purely social.
21
21
  - This library has zero dependencies -- it is the leaf of the dependency graph.
package/SKILLS.md CHANGED
@@ -8,7 +8,7 @@ Defines all `uint8` permission ID constants used across the Juicebox V6 ecosyste
8
8
 
9
9
  | Contract | Role |
10
10
  |----------|------|
11
- | `JBPermissionIds` | Constants-only library. 33 `uint8 internal constant` values (1--33). Pragma `^0.8.0` for maximum compatibility across all Juicebox contracts. |
11
+ | `JBPermissionIds` | Constants-only library. 34 `uint8 internal constant` values (1--34). Pragma `^0.8.0` for maximum compatibility across all Juicebox contracts. |
12
12
 
13
13
  ## Key Functions
14
14
 
@@ -44,44 +44,45 @@ Permissions are stored as 256-bit packed integers in `JBPermissions`, keyed by `
44
44
  | 13 | `TRANSFER_CREDITS` | `JBController.transferCreditsFrom` | Transfer internal credit balance to another address. Checked against the **token holder**. |
45
45
  | 14 | `SET_CONTROLLER` | `JBDirectory.setControllerOf` | Set a project's controller. Checked against project owner. |
46
46
  | 15 | `SET_TERMINALS` | `JBDirectory.setTerminalsOf` | Set a project's terminals. Checked against project owner. **Warning:** can remove the primary terminal. Also checked by `JBController.launchRulesetsFor` (ID 3) and `JBController.launchProjectFor`. |
47
- | 16 | `SET_PRIMARY_TERMINAL` | `JBDirectory.setPrimaryTerminalOf` | Set the primary terminal for a given token. Checked against project owner. |
48
- | 17 | `USE_ALLOWANCE` | `JBMultiTerminal.useAllowanceOf` | Use surplus allowance to send funds to an arbitrary address. Checked against project owner. |
49
- | 18 | `SET_SPLIT_GROUPS` | `JBController.setSplitGroupsOf` | Set how payouts and reserved tokens are distributed. Checked against project owner. |
50
- | 19 | `ADD_PRICE_FEED` | `JBController.addPriceFeedFor` | Add a price feed for a project. The controller checks this permission, then calls `JBPrices.addPriceFeedFor` internally. Checked against project owner. |
51
- | 20 | `ADD_ACCOUNTING_CONTEXTS` | `JBMultiTerminal.addAccountingContextsFor` | Add accepted token accounting contexts to a terminal. Checked against project owner. |
52
- | 21 | `SET_TOKEN_METADATA` | `JBController.setTokenMetadataOf` | Set a project token's name and symbol. Checked against project owner. |
47
+ | 16 | `ADD_TERMINALS` | `JBDirectory.setPrimaryTerminalOf` | Add a new terminal when `setPrimaryTerminalOf` implicitly adds it to the project's terminal list. Checked against project owner. |
48
+ | 17 | `SET_PRIMARY_TERMINAL` | `JBDirectory.setPrimaryTerminalOf` | Set the primary terminal for a given token. Checked against project owner. |
49
+ | 18 | `USE_ALLOWANCE` | `JBMultiTerminal.useAllowanceOf` | Use surplus allowance to send funds to an arbitrary address. Checked against project owner. |
50
+ | 19 | `SET_SPLIT_GROUPS` | `JBController.setSplitGroupsOf` | Set how payouts and reserved tokens are distributed. Checked against project owner. |
51
+ | 20 | `ADD_PRICE_FEED` | `JBController.addPriceFeedFor` | Add a price feed for a project. The controller checks this permission, then calls `JBPrices.addPriceFeedFor` internally. Checked against project owner. |
52
+ | 21 | `ADD_ACCOUNTING_CONTEXTS` | `JBMultiTerminal.addAccountingContextsFor` | Add accepted token accounting contexts to a terminal. Checked against project owner. |
53
+ | 22 | `SET_TOKEN_METADATA` | `JBController.setTokenMetadataOf` | Set a project token's name and symbol. Checked against project owner. |
53
54
 
54
55
  ### nana-721-hook-v6
55
56
 
56
57
  | ID | Name | Checked in | Permission scope |
57
58
  |----|------|------------|-----------------|
58
- | 22 | `ADJUST_721_TIERS` | `JB721TiersHook.adjustTiers` | Add or remove NFT tiers. Checked against `owner()` (the project's controller). Also used by `CTPublisher`, `CTProjectOwner`, and `REVDeployer`. |
59
- | 23 | `SET_721_METADATA` | `JB721TiersHook.setMetadata` | Set base URI, contract URI, or token URI resolver. Checked against `owner()`. |
60
- | 24 | `MINT_721` | `JB721TiersHook.mintFor` | Manually mint NFTs from specific tiers. Checked against `owner()`. |
61
- | 25 | `SET_721_DISCOUNT_PERCENT` | `JB721TiersHook.setDiscountPercentOf` | Set the discount percent for NFT tiers. Checked against `owner()`. Called twice in the function for two separate code paths. |
59
+ | 23 | `ADJUST_721_TIERS` | `JB721TiersHook.adjustTiers` | Add or remove NFT tiers. Checked against `owner()` (the project's controller). Also used by `CTPublisher`, `CTProjectOwner`, and `REVDeployer`. |
60
+ | 24 | `SET_721_METADATA` | `JB721TiersHook.setMetadata` | Set base URI, contract URI, or token URI resolver. Checked against `owner()`. |
61
+ | 25 | `MINT_721` | `JB721TiersHook.mintFor` | Manually mint NFTs from specific tiers. Checked against `owner()`. |
62
+ | 26 | `SET_721_DISCOUNT_PERCENT` | `JB721TiersHook.setDiscountPercentOf` | Set the discount percent for NFT tiers. Checked against `owner()`. Called twice in the function for two separate code paths. |
62
63
 
63
64
  ### nana-buyback-hook-v6
64
65
 
65
66
  | ID | Name | Checked in | Permission scope |
66
67
  |----|------|------------|-----------------|
67
- | 26 | `SET_BUYBACK_TWAP` | `JBBuybackHook.setTwapWindowOf` | Set the TWAP oracle window duration. Checked against project owner. |
68
- | 27 | `SET_BUYBACK_POOL` | `JBBuybackHook.setPoolFor`, `JBBuybackHook.initializePoolFor`, `JBBuybackHookRegistry.initializePoolFor` | Set the Uniswap pool for a project's buyback. Checked against project owner. |
69
- | 28 | `SET_BUYBACK_HOOK` | `JBBuybackHookRegistry.setHookFor`, `JBBuybackHookRegistry.lockHookFor` | Set or lock the buyback hook implementation for a project. Checked against project owner. Also granted by `REVDeployer` as an operator permission. |
68
+ | 27 | `SET_BUYBACK_TWAP` | `JBBuybackHook.setTwapWindowOf` | Set the TWAP oracle window duration. Checked against project owner. |
69
+ | 28 | `SET_BUYBACK_POOL` | `JBBuybackHook.setPoolFor`, `JBBuybackHook.initializePoolFor`, `JBBuybackHookRegistry.initializePoolFor` | Set the Uniswap pool for a project's buyback. Checked against project owner. |
70
+ | 29 | `SET_BUYBACK_HOOK` | `JBBuybackHookRegistry.setHookFor`, `JBBuybackHookRegistry.lockHookFor` | Set or lock the buyback hook implementation for a project. Checked against project owner. Also granted by `REVDeployer` as an operator permission. |
70
71
 
71
72
  ### nana-router-terminal-v6
72
73
 
73
74
  | ID | Name | Checked in | Permission scope |
74
75
  |----|------|------------|-----------------|
75
- | 29 | `SET_ROUTER_TERMINAL` | `JBRouterTerminalRegistry.setTerminalFor`, `JBRouterTerminalRegistry.lockTerminalFor` | Set or lock the router terminal for a project. Checked against project owner. |
76
+ | 30 | `SET_ROUTER_TERMINAL` | `JBRouterTerminalRegistry.setTerminalFor`, `JBRouterTerminalRegistry.lockTerminalFor` | Set or lock the router terminal for a project. Checked against project owner. |
76
77
 
77
78
  ### nana-suckers-v6
78
79
 
79
80
  | ID | Name | Checked in | Permission scope |
80
81
  |----|------|------------|-----------------|
81
- | 30 | `MAP_SUCKER_TOKEN` | `JBSucker.mapToken` | Map an ERC-20 token to its remote chain counterpart. Immutable once the outbox merkle tree has entries. Checked against project owner. |
82
- | 31 | `DEPLOY_SUCKERS` | `JBSuckerRegistry.deploySuckersFor` | Deploy sucker contracts for cross-chain bridging. Checked against project owner. Also checked by `JBOmnichainDeployer` and `CTDeployer`. |
83
- | 32 | `SUCKER_SAFETY` | `JBSucker.enableEmergencyHatchFor` | Enable the emergency hatch to recover stuck tokens. Checked against project owner. |
84
- | 33 | `SET_SUCKER_DEPRECATION` | `JBSucker.setDeprecation` | Move a sucker through the deprecation lifecycle (ENABLED -> DEPRECATION_PENDING -> SENDING_DISABLED -> DEPRECATED). Checked against project owner. |
82
+ | 31 | `MAP_SUCKER_TOKEN` | `JBSucker.mapToken` | Map an ERC-20 token to its remote chain counterpart. Immutable once the outbox merkle tree has entries. Checked against project owner. |
83
+ | 32 | `DEPLOY_SUCKERS` | `JBSuckerRegistry.deploySuckersFor` | Deploy sucker contracts for cross-chain bridging. Checked against project owner. Also checked by `JBOmnichainDeployer` and `CTDeployer`. |
84
+ | 33 | `SUCKER_SAFETY` | `JBSucker.enableEmergencyHatchFor` | Enable the emergency hatch to recover stuck tokens. Checked against project owner. |
85
+ | 34 | `SET_SUCKER_DEPRECATION` | `JBSucker.setDeprecation` | Move a sucker through the deprecation lifecycle (ENABLED -> DEPRECATION_PENDING -> SENDING_DISABLED -> DEPRECATED). Checked against project owner. |
85
86
 
86
87
  ## Common Permission Bundles
87
88
 
@@ -89,12 +90,12 @@ Typical combinations when granting operator access via `JBPermissions.setPermiss
89
90
 
90
91
  | Bundle | IDs | Use case |
91
92
  |--------|-----|----------|
92
- | **Deployer operator** | `QUEUE_RULESETS` (2), `SET_SPLIT_GROUPS` (18), `SET_FUND_ACCESS_LIMITS` (not in this library -- set via ruleset config) | Operator that manages project rulesets and split configuration on behalf of the owner. |
93
- | **Token manager** | `MINT_TOKENS` (10), `BURN_TOKENS` (11), `SET_TOKEN_METADATA` (21) | Operator that manages token supply and metadata. |
94
- | **Treasury manager** | `SEND_PAYOUTS` (5), `USE_ALLOWANCE` (17), `ADD_ACCOUNTING_CONTEXTS` (20) | Operator that manages outflows from the project treasury. |
95
- | **Project admin** | `SET_PROJECT_URI` (7), `DEPLOY_ERC20` (8), `SET_CONTROLLER` (14), `SET_TERMINALS` (15), `SET_PRIMARY_TERMINAL` (16) | Broad administrative access without ROOT. |
96
- | **NFT manager** | `ADJUST_721_TIERS` (22), `SET_721_METADATA` (23), `MINT_721` (24), `SET_721_DISCOUNT_PERCENT` (25) | Full control over 721 tier configuration. |
97
- | **Cross-chain operator** | `DEPLOY_SUCKERS` (31), `MAP_SUCKER_TOKEN` (30), `SET_SUCKER_DEPRECATION` (33) | Manages cross-chain bridging lifecycle. |
93
+ | **Deployer operator** | `QUEUE_RULESETS` (2), `SET_SPLIT_GROUPS` (19), `SET_FUND_ACCESS_LIMITS` (not in this library -- set via ruleset config) | Operator that manages project rulesets and split configuration on behalf of the owner. |
94
+ | **Token manager** | `MINT_TOKENS` (10), `BURN_TOKENS` (11), `SET_TOKEN_METADATA` (22) | Operator that manages token supply and metadata. |
95
+ | **Treasury manager** | `SEND_PAYOUTS` (5), `USE_ALLOWANCE` (18), `ADD_ACCOUNTING_CONTEXTS` (21) | Operator that manages outflows from the project treasury. |
96
+ | **Project admin** | `SET_PROJECT_URI` (7), `DEPLOY_ERC20` (8), `SET_CONTROLLER` (14), `SET_TERMINALS` (15), `SET_PRIMARY_TERMINAL` (17) | Broad administrative access without ROOT. |
97
+ | **NFT manager** | `ADJUST_721_TIERS` (23), `SET_721_METADATA` (24), `MINT_721` (25), `SET_721_DISCOUNT_PERCENT` (26) | Full control over 721 tier configuration. |
98
+ | **Cross-chain operator** | `DEPLOY_SUCKERS` (32), `MAP_SUCKER_TOKEN` (31), `SET_SUCKER_DEPRECATION` (34) | Manages cross-chain bridging lifecycle. |
98
99
  | **Launch bundle** | `LAUNCH_RULESETS` (3), `SET_TERMINALS` (15) | Both are required for `launchRulesetsFor` -- ID 3 alone is insufficient. |
99
100
 
100
101
  ## Integration Points
@@ -128,11 +129,12 @@ N/A -- no structs or enums. All values are `uint8 internal constant`.
128
129
  - **Permission ID 0 is forbidden.** `JBPermissions` reverts with `JBPermissions_NoZeroPermission()` if bit 0 is set. Valid IDs start at 1.
129
130
  - **Wildcard project ID (0) grants cross-project access.** Granting `QUEUE_RULESETS` with `projectId = 0` means the operator can queue rulesets for *every* project the account owns. This is powerful and should be used sparingly.
130
131
  - **SET_TERMINALS (ID 15) can break a project.** Replacing the terminal list without including the current primary terminal will remove it, breaking payments and cashouts until a new primary is set.
132
+ - **ADD_TERMINALS (ID 16) vs SET_TERMINALS (ID 15).** `ADD_TERMINALS` is a narrower permission checked when `setPrimaryTerminalOf` implicitly adds a new terminal. `SET_TERMINALS` replaces the entire terminal list.
131
133
  - **LAUNCH_RULESETS (ID 3) requires both IDs 3 and 15.** The function enforces two separate permission checks because it configures terminals in addition to launching rulesets.
132
134
  - **Holder-scoped permissions.** IDs 4 (`CASH_OUT_TOKENS`), 11 (`BURN_TOKENS`), 12 (`CLAIM_TOKENS`), and 13 (`TRANSFER_CREDITS`) are checked against the **token holder**, not the project owner. This means a holder grants an operator permission to act on the holder's own tokens.
133
- - **SET_BUYBACK_POOL (ID 27) vs SET_BUYBACK_HOOK (ID 28) — different scopes.** ID 27 guards pool configuration (`setPoolFor`, `initializePoolFor`). ID 28 guards hook selection (`setHookFor`, `lockHookFor`). `setTwapWindowOf` uses ID 26 (`SET_BUYBACK_TWAP`). Grant all three if the operator needs full buyback management.
134
- - **ADD_PRICE_FEED (ID 19) is checked on JBController, not JBPrices.** The permission gate is on `JBController.addPriceFeed`, which then calls `JBPrices.addPriceFeedFor` internally.
135
- - **uint8 range.** IDs are `uint8` (0--255) but the packed storage is `uint256`, so the system supports up to 256 permission bits. Currently 33 are defined (1--33).
135
+ - **SET_BUYBACK_POOL (ID 28) vs SET_BUYBACK_HOOK (ID 29) — different scopes.** ID 28 guards pool configuration (`setPoolFor`, `initializePoolFor`). ID 29 guards hook selection (`setHookFor`, `lockHookFor`). `setTwapWindowOf` uses ID 27 (`SET_BUYBACK_TWAP`). Grant all three if the operator needs full buyback management.
136
+ - **ADD_PRICE_FEED (ID 20) is checked on JBController, not JBPrices.** The permission gate is on `JBController.addPriceFeed`, which then calls `JBPrices.addPriceFeedFor` internally.
137
+ - **uint8 range.** IDs are `uint8` (0--255) but the packed storage is `uint256`, so the system supports up to 256 permission bits. Currently 34 are defined (1--34).
136
138
 
137
139
  ## Example Integration
138
140
 
package/STYLE_GUIDE.md CHANGED
@@ -21,7 +21,7 @@ One contract/interface/struct/enum per file. Name the file after the type it con
21
21
 
22
22
  ```solidity
23
23
  // Contracts — pin to exact version
24
- pragma solidity ^0.8.28;
24
+ pragma solidity 0.8.28;
25
25
 
26
26
  // Interfaces, structs, enums — caret for forward compatibility
27
27
  pragma solidity ^0.8.0;
package/USER_JOURNEYS.md CHANGED
@@ -180,7 +180,7 @@ Since this is a constants-only library with no runtime behavior, these journeys
180
180
  - `JBBuybackHookRegistry.setHookFor(uint256 projectId, IJBRulesetDataHook hook)` -- configures the hook
181
181
  - `JBBuybackHookRegistry.lockHookFor(uint256 projectId, IJBRulesetDataHook expectedHook)` -- permanently locks the configuration
182
182
 
183
- **Who can call**: The project owner, or an address with the owner's `SET_BUYBACK_HOOK` (ID 28) permission for that project. A single permission ID gates both operations.
183
+ **Who can call**: The project owner, or an address with the owner's `SET_BUYBACK_HOOK` (ID 29) permission for that project. A single permission ID gates both operations.
184
184
 
185
185
  **Parameters**:
186
186
  - `projectId` -- The project whose buyback hook is being configured or locked
@@ -188,7 +188,7 @@ Since this is a constants-only library with no runtime behavior, these journeys
188
188
 
189
189
  ### Steps (SET_BUYBACK_HOOK example)
190
190
 
191
- 1. **Operator with SET_BUYBACK_HOOK (ID 28) calls `JBBuybackHookRegistry.setHookFor(5, hookAddress)`**
191
+ 1. **Operator with SET_BUYBACK_HOOK (ID 29) calls `JBBuybackHookRegistry.setHookFor(5, hookAddress)`**
192
192
 
193
193
  - Configures the buyback hook for project 5
194
194
  - This is a reversible operation (can be called again with a different hook)
@@ -206,9 +206,9 @@ Since this is a constants-only library with no runtime behavior, these journeys
206
206
  **Events**: Events are emitted by `JBBuybackHookRegistry` (in nana-buyback-hook-v6), not this library.
207
207
 
208
208
  **Edge cases**:
209
- - A single permission ID (28 or 29) gates BOTH the "set" and "lock" operations. Granting the permission implicitly trusts the operator to potentially lock the configuration.
209
+ - A single permission ID (29 or 30) gates BOTH the "set" and "lock" operations. Granting the permission implicitly trusts the operator to potentially lock the configuration.
210
210
  - The locking is permanent (no unlock mechanism in the registry).
211
- - Project owners should only grant SET_BUYBACK_HOOK (28) or SET_ROUTER_TERMINAL (29) to operators they trust not to lock prematurely.
211
+ - Project owners should only grant SET_BUYBACK_HOOK (29) or SET_ROUTER_TERMINAL (30) to operators they trust not to lock prematurely.
212
212
 
213
213
  ---
214
214
 
@@ -228,20 +228,20 @@ Since this is a constants-only library with no runtime behavior, these journeys
228
228
  ### Steps
229
229
 
230
230
  1. **Deploy suckers: `JBSuckerRegistry.deploySuckersFor(5, salt, configurations)`**
231
- - Permission: `DEPLOY_SUCKERS` (ID 31)
231
+ - Permission: `DEPLOY_SUCKERS` (ID 32)
232
232
  - Creates sucker contracts for cross-chain bridging
233
233
 
234
234
  2. **Map tokens: `JBSucker.mapToken(map)`** where `map` is a `JBTokenMapping` struct
235
- - Permission: `MAP_SUCKER_TOKEN` (ID 30)
235
+ - Permission: `MAP_SUCKER_TOKEN` (ID 31)
236
236
  - Maps a local ERC-20 to its remote chain counterpart
237
237
  - CAUTION: once the outbox merkle tree has entries, the mapping is immutable (can only be disabled, not remapped)
238
238
 
239
239
  3. **Enable emergency hatch: `JBSucker.enableEmergencyHatchFor(tokens)`**
240
- - Permission: `SUCKER_SAFETY` (ID 32)
240
+ - Permission: `SUCKER_SAFETY` (ID 33)
241
241
  - Allows recovery of stuck tokens via the emergency hatch
242
242
 
243
243
  4. **Deprecate sucker: `JBSucker.setDeprecation(timestamp)`**
244
- - Permission: `SET_SUCKER_DEPRECATION` (ID 33)
244
+ - Permission: `SET_SUCKER_DEPRECATION` (ID 34)
245
245
  - The timestamp after which the sucker is deprecated.
246
246
 
247
247
  **State changes** (per step):
@@ -280,21 +280,22 @@ Since this is a constants-only library with no runtime behavior, these journeys
280
280
  | 13 | `TRANSFER_CREDITS` | `JBController.transferCreditsFrom` | Token holder |
281
281
  | 14 | `SET_CONTROLLER` | `JBDirectory.setControllerOf` | Project owner |
282
282
  | 15 | `SET_TERMINALS` | `JBDirectory.setTerminalsOf` | Project owner |
283
- | 16 | `SET_PRIMARY_TERMINAL` | `JBDirectory.setPrimaryTerminalOf` | Project owner |
284
- | 17 | `USE_ALLOWANCE` | `JBMultiTerminal.useAllowanceOf` | Project owner |
285
- | 18 | `SET_SPLIT_GROUPS` | `JBController.setSplitGroupsOf` | Project owner |
286
- | 19 | `ADD_PRICE_FEED` | `JBController.addPriceFeedFor` | Project owner |
287
- | 20 | `ADD_ACCOUNTING_CONTEXTS` | `JBMultiTerminal.addAccountingContextsFor` | Project owner |
288
- | 21 | `SET_TOKEN_METADATA` | `JBController.setTokenMetadataOf` | Project owner |
289
- | 22 | `ADJUST_721_TIERS` | `JB721TiersHook.adjustTiers` | Project owner |
290
- | 23 | `SET_721_METADATA` | `JB721TiersHook.setMetadata` | Project owner |
291
- | 24 | `MINT_721` | `JB721TiersHook.mintFor` | Project owner |
292
- | 25 | `SET_721_DISCOUNT_PERCENT` | `JB721TiersHook.setDiscountPercentOf` | Project owner |
293
- | 26 | `SET_BUYBACK_TWAP` | `JBBuybackHook.setTwapWindowOf` | Project owner |
294
- | 27 | `SET_BUYBACK_POOL` | `JBBuybackHook.setPoolFor` | Project owner |
295
- | 28 | `SET_BUYBACK_HOOK` | `JBBuybackHookRegistry.setHookFor` + `lockHookFor` | Project owner |
296
- | 29 | `SET_ROUTER_TERMINAL` | `JBRouterTerminalRegistry.setTerminalFor` + `lockTerminalFor` | Project owner |
297
- | 30 | `MAP_SUCKER_TOKEN` | `JBSucker.mapToken` | Project owner |
298
- | 31 | `DEPLOY_SUCKERS` | `JBSuckerRegistry.deploySuckersFor` | Project owner |
299
- | 32 | `SUCKER_SAFETY` | `JBSucker.enableEmergencyHatchFor` | Project owner |
300
- | 33 | `SET_SUCKER_DEPRECATION` | `JBSucker.setDeprecation` | Project owner |
283
+ | 16 | `ADD_TERMINALS` | `JBDirectory.setPrimaryTerminalOf` (implicit add) | Project owner |
284
+ | 17 | `SET_PRIMARY_TERMINAL` | `JBDirectory.setPrimaryTerminalOf` | Project owner |
285
+ | 18 | `USE_ALLOWANCE` | `JBMultiTerminal.useAllowanceOf` | Project owner |
286
+ | 19 | `SET_SPLIT_GROUPS` | `JBController.setSplitGroupsOf` | Project owner |
287
+ | 20 | `ADD_PRICE_FEED` | `JBController.addPriceFeedFor` | Project owner |
288
+ | 21 | `ADD_ACCOUNTING_CONTEXTS` | `JBMultiTerminal.addAccountingContextsFor` | Project owner |
289
+ | 22 | `SET_TOKEN_METADATA` | `JBController.setTokenMetadataOf` | Project owner |
290
+ | 23 | `ADJUST_721_TIERS` | `JB721TiersHook.adjustTiers` | Project owner |
291
+ | 24 | `SET_721_METADATA` | `JB721TiersHook.setMetadata` | Project owner |
292
+ | 25 | `MINT_721` | `JB721TiersHook.mintFor` | Project owner |
293
+ | 26 | `SET_721_DISCOUNT_PERCENT` | `JB721TiersHook.setDiscountPercentOf` | Project owner |
294
+ | 27 | `SET_BUYBACK_TWAP` | `JBBuybackHook.setTwapWindowOf` | Project owner |
295
+ | 28 | `SET_BUYBACK_POOL` | `JBBuybackHook.setPoolFor` | Project owner |
296
+ | 29 | `SET_BUYBACK_HOOK` | `JBBuybackHookRegistry.setHookFor` + `lockHookFor` | Project owner |
297
+ | 30 | `SET_ROUTER_TERMINAL` | `JBRouterTerminalRegistry.setTerminalFor` + `lockTerminalFor` | Project owner |
298
+ | 31 | `MAP_SUCKER_TOKEN` | `JBSucker.mapToken` | Project owner |
299
+ | 32 | `DEPLOY_SUCKERS` | `JBSuckerRegistry.deploySuckersFor` | Project owner |
300
+ | 33 | `SUCKER_SAFETY` | `JBSucker.enableEmergencyHatchFor` | Project owner |
301
+ | 34 | `SET_SUCKER_DEPRECATION` | `JBSucker.setDeprecation` | Project owner |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/permission-ids-v6",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,29 +25,31 @@ library JBPermissionIds {
25
25
  uint8 internal constant SET_CONTROLLER = 14; // Permission to call `JBDirectory.setControllerOf`.
26
26
  uint8 internal constant SET_TERMINALS = 15; // Permission to call `JBDirectory.setTerminalsOf`.
27
27
  // Be careful - `SET_TERMINALS` can be used to remove the primary terminal.
28
- uint8 internal constant SET_PRIMARY_TERMINAL = 16; // Permission to call `JBDirectory.setPrimaryTerminalOf`.
29
- uint8 internal constant USE_ALLOWANCE = 17; // Permission to call `JBMultiTerminal.useAllowanceOf`.
30
- uint8 internal constant SET_SPLIT_GROUPS = 18; // Permission to call `JBController.setSplitGroupsOf`.
31
- uint8 internal constant ADD_PRICE_FEED = 19; // Permission to call `JBController.addPriceFeedFor`.
32
- uint8 internal constant ADD_ACCOUNTING_CONTEXTS = 20; // Permission to call
28
+ uint8 internal constant ADD_TERMINALS = 16; // Permission to call `JBDirectory.setPrimaryTerminalOf` when it
29
+ // implicitly adds a new terminal.
30
+ uint8 internal constant SET_PRIMARY_TERMINAL = 17; // Permission to call `JBDirectory.setPrimaryTerminalOf`.
31
+ uint8 internal constant USE_ALLOWANCE = 18; // Permission to call `JBMultiTerminal.useAllowanceOf`.
32
+ uint8 internal constant SET_SPLIT_GROUPS = 19; // Permission to call `JBController.setSplitGroupsOf`.
33
+ uint8 internal constant ADD_PRICE_FEED = 20; // Permission to call `JBController.addPriceFeedFor`.
34
+ uint8 internal constant ADD_ACCOUNTING_CONTEXTS = 21; // Permission to call
33
35
  // `JBMultiTerminal.addAccountingContextsFor`.
34
- uint8 internal constant SET_TOKEN_METADATA = 21; // Permission to call
36
+ uint8 internal constant SET_TOKEN_METADATA = 22; // Permission to call
35
37
  // `JBController.setTokenMetadataOf`.
36
38
 
37
39
  /* Used by `nana-721-hook`: https://github.com/Bananapus/nana-721-hook */
38
- uint8 internal constant ADJUST_721_TIERS = 22; // Permission to call `JB721TiersHook.adjustTiers`.
39
- uint8 internal constant SET_721_METADATA = 23; // Permission to call `JB721TiersHook.setMetadata`.
40
- uint8 internal constant MINT_721 = 24; // Permission to call `JB721TiersHook.mintFor`.
41
- uint8 internal constant SET_721_DISCOUNT_PERCENT = 25; // Permission to call `JB721TiersHook.setDiscountPercentOf`.
40
+ uint8 internal constant ADJUST_721_TIERS = 23; // Permission to call `JB721TiersHook.adjustTiers`.
41
+ uint8 internal constant SET_721_METADATA = 24; // Permission to call `JB721TiersHook.setMetadata`.
42
+ uint8 internal constant MINT_721 = 25; // Permission to call `JB721TiersHook.mintFor`.
43
+ uint8 internal constant SET_721_DISCOUNT_PERCENT = 26; // Permission to call `JB721TiersHook.setDiscountPercentOf`.
42
44
 
43
45
  /* Used by `nana-buyback-hook`: https://github.com/Bananapus/nana-buyback-hook */
44
- uint8 internal constant SET_BUYBACK_TWAP = 26; // Permission to call `JBBuybackHook.setTwapWindowOf`.
45
- uint8 internal constant SET_BUYBACK_POOL = 27; // Permission to call `JBBuybackHook.setPoolFor`.
46
+ uint8 internal constant SET_BUYBACK_TWAP = 27; // Permission to call `JBBuybackHook.setTwapWindowOf`.
47
+ uint8 internal constant SET_BUYBACK_POOL = 28; // Permission to call `JBBuybackHook.setPoolFor`.
46
48
  /// @dev This single ID intentionally gates both setting and locking the buyback hook as a simplification.
47
49
  /// Granting this permission allows the operator to call both `JBBuybackHookRegistry.setHookFor` (to configure the
48
50
  /// hook) and `JBBuybackHookRegistry.lockHookFor` (to permanently lock the hook configuration). Project owners
49
51
  /// should be aware that an operator with this permission can lock the hook, preventing future changes.
50
- uint8 internal constant SET_BUYBACK_HOOK = 28; // Permission to call `JBBuybackHookRegistry.setHookFor` and
52
+ uint8 internal constant SET_BUYBACK_HOOK = 29; // Permission to call `JBBuybackHookRegistry.setHookFor` and
51
53
  // `JBBuybackHookRegistry.lockHookFor`.
52
54
 
53
55
  /* Used by `nana-router-terminal`: https://github.com/Bananapus/nana-router-terminal-v6 */
@@ -56,12 +58,12 @@ library JBPermissionIds {
56
58
  /// configure the terminal) and `JBRouterTerminalRegistry.lockTerminalFor` (to permanently lock the terminal
57
59
  /// configuration). Project owners should be aware that an operator with this permission can lock the terminal,
58
60
  /// preventing future changes.
59
- uint8 internal constant SET_ROUTER_TERMINAL = 29; // Permission to call
61
+ uint8 internal constant SET_ROUTER_TERMINAL = 30; // Permission to call
60
62
  // `JBRouterTerminalRegistry.setTerminalFor` and `JBRouterTerminalRegistry.lockTerminalFor`.
61
63
 
62
64
  /* Used by `nana-suckers`: https://github.com/Bananapus/nana-suckers */
63
- uint8 internal constant MAP_SUCKER_TOKEN = 30; // Permission to call `JBSucker.mapToken`.
64
- uint8 internal constant DEPLOY_SUCKERS = 31; // Permission to call `JBSuckerRegistry.deploySuckersFor`.
65
- uint8 internal constant SUCKER_SAFETY = 32; // Permission to call `JBSucker.enableEmergencyHatchFor`.
66
- uint8 internal constant SET_SUCKER_DEPRECATION = 33; // Permission to call `JBSucker.setDeprecation`.
65
+ uint8 internal constant MAP_SUCKER_TOKEN = 31; // Permission to call `JBSucker.mapToken`.
66
+ uint8 internal constant DEPLOY_SUCKERS = 32; // Permission to call `JBSuckerRegistry.deploySuckersFor`.
67
+ uint8 internal constant SUCKER_SAFETY = 33; // Permission to call `JBSucker.enableEmergencyHatchFor`.
68
+ uint8 internal constant SET_SUCKER_DEPRECATION = 34; // Permission to call `JBSucker.setDeprecation`.
67
69
  }