@bananapus/permission-ids-v6 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -14
- package/SKILLS.md +129 -42
- package/foundry.toml +1 -1
- package/package.json +1 -1
- package/slither-ci.config.json +1 -1
- package/src/JBPermissionIds.sol +9 -0
package/README.md
CHANGED
|
@@ -1,23 +1,98 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Juicebox Permission IDs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The single source of truth for access control across the Juicebox V6 ecosystem. This library defines 32 `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
|
+
|
|
5
|
+
## How permissions work
|
|
6
|
+
|
|
7
|
+
Juicebox V6 access control is built on a simple model: an **account** (typically a project owner) grants an **operator** (any address) a set of permission IDs scoped to a specific **project ID**. When a permissioned function is called, the contract checks that the caller either *is* the account or *has* the required permission ID for that project.
|
|
8
|
+
|
|
9
|
+
Permissions are stored as a 256-bit packed integer in `JBPermissions`, where each bit position corresponds to a permission ID. This library provides human-readable names for those bit positions.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
permissionsOf[operator][account][projectId] => uint256 (packed bits)
|
|
13
|
+
```
|
|
4
14
|
|
|
5
15
|
## Architecture
|
|
6
16
|
|
|
7
17
|
| Contract | Description |
|
|
8
18
|
|----------|-------------|
|
|
9
|
-
| `JBPermissionIds` | Solidity library with 32 `uint8 internal constant` permission IDs. No state, no functions. |
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
|
16
|
-
|
|
17
|
-
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
| `JBPermissionIds` | Solidity library with 32 `uint8 internal constant` permission IDs (values 1--32). No state, no functions, no dependencies. Pragma `^0.8.0` for maximum compatibility. |
|
|
20
|
+
|
|
21
|
+
## All permission IDs
|
|
22
|
+
|
|
23
|
+
### Global (ID 1)
|
|
24
|
+
|
|
25
|
+
| ID | Name | Description |
|
|
26
|
+
|----|------|-------------|
|
|
27
|
+
| 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. |
|
|
28
|
+
|
|
29
|
+
### Core (IDs 2--20) -- [nana-core-v6](https://github.com/Bananapus/nana-core-v6)
|
|
30
|
+
|
|
31
|
+
| ID | Name | Checked in | Description |
|
|
32
|
+
|----|------|------------|-------------|
|
|
33
|
+
| 2 | `QUEUE_RULESETS` | `JBController.queueRulesetsOf` | Queue new rulesets for a project. Also required by `JB721TiersHookProjectDeployer` and `JBOmnichainDeployer`. |
|
|
34
|
+
| 3 | `LAUNCH_RULESETS` | `JBController.launchRulesetsFor` | Launch a project's initial rulesets and terminals. Note: the caller also needs `SET_TERMINALS` (ID 15) since this function configures terminals. |
|
|
35
|
+
| 4 | `CASH_OUT_TOKENS` | `JBMultiTerminal.cashOutTokensOf` | Cash out (redeem) a holder's tokens for a share of the project's surplus. Checked against the **token holder**, not the project owner. |
|
|
36
|
+
| 5 | `SEND_PAYOUTS` | `JBMultiTerminal.sendPayoutsOf` | Send payouts to a project's splits up to its payout limit. |
|
|
37
|
+
| 6 | `MIGRATE_TERMINAL` | `JBMultiTerminal.migrateBalanceOf` | Migrate a project's balance from one terminal to another. |
|
|
38
|
+
| 7 | `SET_PROJECT_URI` | `JBController.setUriOf` | Set a project's metadata URI. |
|
|
39
|
+
| 8 | `DEPLOY_ERC20` | `JBController.deployERC20For` | Deploy a new ERC-20 token for a project. |
|
|
40
|
+
| 9 | `SET_TOKEN` | `JBController.setTokenFor` | Set an existing ERC-20 token for a project. |
|
|
41
|
+
| 10 | `MINT_TOKENS` | `JBController.mintTokensOf` | Mint new project tokens. Only works if the current ruleset allows owner minting. |
|
|
42
|
+
| 11 | `BURN_TOKENS` | `JBController.burnTokensOf` | Burn a holder's project tokens. Checked against the **token holder**, not the project owner. |
|
|
43
|
+
| 12 | `CLAIM_TOKENS` | `JBController.claimTokensFor` | Claim a holder's internal credit balance as ERC-20 tokens. Checked against the **token holder**. |
|
|
44
|
+
| 13 | `TRANSFER_CREDITS` | `JBController.transferCreditsFrom` | Transfer a holder's internal credit balance to another address. Checked against the **token holder**. |
|
|
45
|
+
| 14 | `SET_CONTROLLER` | `JBDirectory.setControllerOf` | Set a project's controller in the directory. |
|
|
46
|
+
| 15 | `SET_TERMINALS` | `JBDirectory.setTerminalsOf` | Set a project's terminals. **Warning:** can remove the primary terminal. Also required by `LAUNCH_RULESETS` (ID 3). |
|
|
47
|
+
| 16 | `SET_PRIMARY_TERMINAL` | `JBDirectory.setPrimaryTerminalOf` | Set a project's primary terminal for a given token. |
|
|
48
|
+
| 17 | `USE_ALLOWANCE` | `JBMultiTerminal.useAllowanceOf` | Use a project's surplus allowance to send funds to an arbitrary address. |
|
|
49
|
+
| 18 | `SET_SPLIT_GROUPS` | `JBController.setSplitGroupsOf` | Set a project's split groups (how payouts and reserved tokens are distributed). |
|
|
50
|
+
| 19 | `ADD_PRICE_FEED` | `JBController.addPriceFeed` | Add a price feed for a project. The controller checks this permission before calling `JBPrices.addPriceFeedFor`. |
|
|
51
|
+
| 20 | `ADD_ACCOUNTING_CONTEXTS` | `JBMultiTerminal.addAccountingContextsFor` | Add accounting contexts (accepted tokens) to a terminal for a project. |
|
|
52
|
+
|
|
53
|
+
### 721 Hook (IDs 21--24) -- [nana-721-hook-v6](https://github.com/Bananapus/nana-721-hook-v6)
|
|
54
|
+
|
|
55
|
+
| ID | Name | Checked in | Description |
|
|
56
|
+
|----|------|------------|-------------|
|
|
57
|
+
| 21 | `ADJUST_721_TIERS` | `JB721TiersHook.adjustTiers` | Add or remove NFT tiers. Also used by `CTPublisher` and `CTProjectOwner` in croptop-core-v6. |
|
|
58
|
+
| 22 | `SET_721_METADATA` | `JB721TiersHook.setMetadata` | Set the metadata (base URI, contract URI, token URI resolver) for a 721 hook. |
|
|
59
|
+
| 23 | `MINT_721` | `JB721TiersHook.mintFor` | Manually mint NFTs from specific tiers to a beneficiary. |
|
|
60
|
+
| 24 | `SET_721_DISCOUNT_PERCENT` | `JB721TiersHook.setDiscountPercentOf` | Set the discount percent for one or more NFT tiers. |
|
|
61
|
+
|
|
62
|
+
### Buyback Hook (IDs 25--27) -- [nana-buyback-hook-v6](https://github.com/Bananapus/nana-buyback-hook-v6)
|
|
63
|
+
|
|
64
|
+
| ID | Name | Checked in | Description |
|
|
65
|
+
|----|------|------------|-------------|
|
|
66
|
+
| 25 | `SET_BUYBACK_TWAP` | `JBBuybackHook.setTwapWindowOf` | Set the TWAP (time-weighted average price) oracle window for a project's buyback hook. |
|
|
67
|
+
| 26 | `SET_BUYBACK_POOL` | `JBBuybackHook.setPoolFor`, `JBBuybackHookRegistry.setHookFor`, `JBBuybackHookRegistry.lockHookFor` | Set the Uniswap pool for a project's buyback. Also guards setting and locking the hook in `JBBuybackHookRegistry`. |
|
|
68
|
+
| 27 | `SET_BUYBACK_HOOK` | *Reserved / revnet-core-v6* | Defined in `JBPermissionIds` for `JBBuybackHookRegistry.setHookFor` and `lockHookFor`, but the registry currently checks `SET_BUYBACK_POOL` (ID 26) for those functions. Used by `REVDeployer` in revnet-core-v6 as an operator permission grant. |
|
|
69
|
+
|
|
70
|
+
### Router Terminal (ID 28) -- [nana-router-terminal-v6](https://github.com/Bananapus/nana-router-terminal-v6)
|
|
71
|
+
|
|
72
|
+
| ID | Name | Checked in | Description |
|
|
73
|
+
|----|------|------------|-------------|
|
|
74
|
+
| 28 | `SET_ROUTER_TERMINAL` | `JBRouterTerminalRegistry.setTerminalFor`, `JBRouterTerminalRegistry.lockTerminalFor` | Set or lock the router terminal for a project. |
|
|
75
|
+
|
|
76
|
+
### Suckers / Omnichain (IDs 29--32) -- [nana-suckers-v6](https://github.com/Bananapus/nana-suckers-v6)
|
|
77
|
+
|
|
78
|
+
| ID | Name | Checked in | Description |
|
|
79
|
+
|----|------|------------|-------------|
|
|
80
|
+
| 29 | `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. |
|
|
81
|
+
| 30 | `DEPLOY_SUCKERS` | `JBSuckerRegistry.deploySuckersFor` | Deploy new sucker contracts for a project. Also checked by `JBOmnichainDeployer` and `CTDeployer`. |
|
|
82
|
+
| 31 | `SUCKER_SAFETY` | `JBSucker.enableEmergencyHatchFor` | Enable the emergency hatch for a sucker, allowing the project owner to recover stuck tokens. |
|
|
83
|
+
| 32 | `SET_SUCKER_DEPRECATION` | `JBSucker.setDeprecation` | Set the deprecation status of a sucker (ENABLED, DEPRECATION_PENDING, SENDING_DISABLED, DEPRECATED). |
|
|
84
|
+
|
|
85
|
+
## Gotchas
|
|
86
|
+
|
|
87
|
+
- **ROOT is dangerous.** It grants every permission on every contract. An operator with ROOT for project 5 can queue rulesets, send payouts, migrate terminals, mint tokens, etc. -- all on behalf of the granting account for that project.
|
|
88
|
+
- **ROOT cannot be granted for the wildcard project ID.** `JBPermissions` reverts with `JBPermissions_CantSetRootPermissionForWildcardProject()` if you try to set ROOT with `projectId = 0`. This prevents a single operator from controlling all of an account's projects.
|
|
89
|
+
- **ROOT operators can set permissions for others, but cannot grant ROOT.** A ROOT operator can call `setPermissionsFor` on behalf of the account, but only if the new permission set does NOT include ROOT and is NOT for the wildcard project ID.
|
|
90
|
+
- **Permission ID 0 is reserved.** `JBPermissions` reverts with `JBPermissions_NoZeroPermission()` if bit 0 is set in any packed permission value. IDs start at 1.
|
|
91
|
+
- **Wildcard project ID (0) applies to all projects.** Granting a permission with `projectId = 0` means the operator has that permission for every project owned by the account. Use with caution.
|
|
92
|
+
- **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.
|
|
93
|
+
- **LAUNCH_RULESETS requires SET_TERMINALS.** `launchRulesetsFor` enforces both `LAUNCH_RULESETS` and `SET_TERMINALS` because it configures terminals as part of the launch.
|
|
94
|
+
- **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.
|
|
95
|
+
- **The uint8 type limits IDs to 0--255.** Currently 32 are defined (1--32), leaving room for future extensions.
|
|
21
96
|
|
|
22
97
|
## Install
|
|
23
98
|
|
package/SKILLS.md
CHANGED
|
@@ -1,75 +1,137 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Juicebox Permission IDs
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
Defines all `uint8` permission ID constants used across the Juicebox
|
|
5
|
+
Defines all `uint8` permission ID constants used across the Juicebox V6 ecosystem. These IDs are passed to `JBPermissions.setPermissionsFor()` to grant scoped access to protocol functions. The library has no state, no functions, and no dependencies -- it exists solely so that every contract references the same numeric IDs by name.
|
|
6
6
|
|
|
7
7
|
## Contracts
|
|
8
8
|
|
|
9
9
|
| Contract | Role |
|
|
10
10
|
|----------|------|
|
|
11
|
-
| `JBPermissionIds` | Constants-only library.
|
|
11
|
+
| `JBPermissionIds` | Constants-only library. 32 `uint8 internal constant` values (1--32). Pragma `^0.8.0` for maximum compatibility across all Juicebox contracts. |
|
|
12
12
|
|
|
13
13
|
## Key Functions
|
|
14
14
|
|
|
15
15
|
N/A -- this is a constants-only library with no callable functions.
|
|
16
16
|
|
|
17
|
+
## How permissions work
|
|
18
|
+
|
|
19
|
+
Permissions are stored in `JBPermissions` as a 256-bit packed integer:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
permissionsOf[operator][account][projectId] => uint256 (one bit per permission ID)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
When a permissioned function is called, the contract checks whether the caller either **is** the account or **has** the required permission ID for that project. The check also considers:
|
|
26
|
+
|
|
27
|
+
1. **ROOT override** -- if the operator has ROOT (ID 1) for the project (or wildcard), all permission checks pass.
|
|
28
|
+
2. **Wildcard project ID** -- permissions granted with `projectId = 0` apply to all projects for that account.
|
|
29
|
+
|
|
17
30
|
## All Permission IDs
|
|
18
31
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
|
22
|
-
|
|
23
|
-
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
|
28
|
-
|
|
29
|
-
|
|
|
30
|
-
|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
32
|
+
### Global
|
|
33
|
+
|
|
34
|
+
| ID | Name | Checked in | Permission scope |
|
|
35
|
+
|----|------|------------|-----------------|
|
|
36
|
+
| 1 | `ROOT` | `JBPermissions` (implicit) | All permissions across every contract. Checked as a fallback in `hasPermission()` and `hasPermissions()`. Cannot be granted for wildcard `projectId = 0`. A ROOT operator can call `setPermissionsFor` on behalf of the account but cannot grant ROOT to others or set wildcard permissions. |
|
|
37
|
+
|
|
38
|
+
### nana-core-v6
|
|
39
|
+
|
|
40
|
+
| ID | Name | Checked in | Permission scope |
|
|
41
|
+
|----|------|------------|-----------------|
|
|
42
|
+
| 2 | `QUEUE_RULESETS` | `JBController.queueRulesetsOf` | Queue new rulesets. Checked against project owner. Also required by `JB721TiersHookProjectDeployer.queueRulesetsOf` and `JBOmnichainDeployer` functions. |
|
|
43
|
+
| 3 | `LAUNCH_RULESETS` | `JBController.launchRulesetsFor` | Launch initial rulesets. Checked against project owner. **Also requires `SET_TERMINALS` (ID 15)** since the function configures terminals. |
|
|
44
|
+
| 4 | `CASH_OUT_TOKENS` | `JBMultiTerminal.cashOutTokensOf` | Cash out tokens for surplus. Checked against the **token holder** (not the project owner). |
|
|
45
|
+
| 5 | `SEND_PAYOUTS` | `JBMultiTerminal.sendPayoutsOf` | Send payouts to splits up to the payout limit. Checked against project owner (inside `_sendPayoutsOf`). |
|
|
46
|
+
| 6 | `MIGRATE_TERMINAL` | `JBMultiTerminal.migrateBalanceOf` | Migrate a project's balance to a different terminal. Checked against project owner. |
|
|
47
|
+
| 7 | `SET_PROJECT_URI` | `JBController.setUriOf` | Set a project's metadata URI. Checked against project owner. |
|
|
48
|
+
| 8 | `DEPLOY_ERC20` | `JBController.deployERC20For` | Deploy a cloneable ERC-20 token for a project. Checked against project owner. |
|
|
49
|
+
| 9 | `SET_TOKEN` | `JBController.setTokenFor` | Set an existing ERC-20 token for a project. Checked against project owner. |
|
|
50
|
+
| 10 | `MINT_TOKENS` | `JBController.mintTokensOf` | Mint new project tokens. Checked against project owner. Only effective if the current ruleset allows owner minting. |
|
|
51
|
+
| 11 | `BURN_TOKENS` | `JBController.burnTokensOf` | Burn project tokens. Checked against the **token holder**. |
|
|
52
|
+
| 12 | `CLAIM_TOKENS` | `JBController.claimTokensFor` | Claim internal credits as ERC-20 tokens. Checked against the **token holder**. |
|
|
53
|
+
| 13 | `TRANSFER_CREDITS` | `JBController.transferCreditsFrom` | Transfer internal credit balance to another address. Checked against the **token holder**. |
|
|
54
|
+
| 14 | `SET_CONTROLLER` | `JBDirectory.setControllerOf` | Set a project's controller. Checked against project owner. |
|
|
55
|
+
| 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`. |
|
|
56
|
+
| 16 | `SET_PRIMARY_TERMINAL` | `JBDirectory.setPrimaryTerminalOf` | Set the primary terminal for a given token. Checked against project owner. |
|
|
57
|
+
| 17 | `USE_ALLOWANCE` | `JBMultiTerminal.useAllowanceOf` | Use surplus allowance to send funds to an arbitrary address. Checked against project owner. |
|
|
58
|
+
| 18 | `SET_SPLIT_GROUPS` | `JBController.setSplitGroupsOf` | Set how payouts and reserved tokens are distributed. Checked against project owner. |
|
|
59
|
+
| 19 | `ADD_PRICE_FEED` | `JBController.addPriceFeed` | Add a price feed for a project. The controller checks this permission, then calls `JBPrices.addPriceFeedFor` internally. Checked against project owner. |
|
|
60
|
+
| 20 | `ADD_ACCOUNTING_CONTEXTS` | `JBMultiTerminal.addAccountingContextsFor` | Add accepted token accounting contexts to a terminal. Checked against project owner. |
|
|
61
|
+
|
|
62
|
+
### nana-721-hook-v6
|
|
63
|
+
|
|
64
|
+
| ID | Name | Checked in | Permission scope |
|
|
65
|
+
|----|------|------------|-----------------|
|
|
66
|
+
| 21 | `ADJUST_721_TIERS` | `JB721TiersHook.adjustTiers` | Add or remove NFT tiers. Checked against `owner()` (the project's controller). Also used by `CTPublisher`, `CTProjectOwner`, and `REVDeployer`. |
|
|
67
|
+
| 22 | `SET_721_METADATA` | `JB721TiersHook.setMetadata` | Set base URI, contract URI, or token URI resolver. Checked against `owner()`. |
|
|
68
|
+
| 23 | `MINT_721` | `JB721TiersHook.mintFor` | Manually mint NFTs from specific tiers. Checked against `owner()`. |
|
|
69
|
+
| 24 | `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. |
|
|
70
|
+
|
|
71
|
+
### nana-buyback-hook-v6
|
|
72
|
+
|
|
73
|
+
| ID | Name | Checked in | Permission scope |
|
|
74
|
+
|----|------|------------|-----------------|
|
|
75
|
+
| 25 | `SET_BUYBACK_TWAP` | `JBBuybackHook.setTwapWindowOf` | Set the TWAP oracle window duration. Checked against project owner. |
|
|
76
|
+
| 26 | `SET_BUYBACK_POOL` | `JBBuybackHook.setPoolFor`, `JBBuybackHookRegistry.setHookFor`, `JBBuybackHookRegistry.lockHookFor` | Set the Uniswap pool for a project's buyback. Also guards setting and locking the hook in `JBBuybackHookRegistry`. Checked against project owner. |
|
|
77
|
+
| 27 | `SET_BUYBACK_HOOK` | *Currently unused in buyback hook code* | Defined for `JBBuybackHookRegistry.setHookFor` and `lockHookFor` per the source comment, but the registry actually checks `SET_BUYBACK_POOL` (ID 26) for those functions. Referenced by `REVDeployer` in revnet-core-v6 as an operator permission grant. |
|
|
78
|
+
|
|
79
|
+
### nana-router-terminal-v6
|
|
80
|
+
|
|
81
|
+
| ID | Name | Checked in | Permission scope |
|
|
82
|
+
|----|------|------------|-----------------|
|
|
83
|
+
| 28 | `SET_ROUTER_TERMINAL` | `JBRouterTerminalRegistry.setTerminalFor`, `JBRouterTerminalRegistry.lockTerminalFor` | Set or lock the router terminal for a project. Checked against project owner. |
|
|
84
|
+
|
|
85
|
+
### nana-suckers-v6
|
|
86
|
+
|
|
87
|
+
| ID | Name | Checked in | Permission scope |
|
|
88
|
+
|----|------|------------|-----------------|
|
|
89
|
+
| 29 | `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. |
|
|
90
|
+
| 30 | `DEPLOY_SUCKERS` | `JBSuckerRegistry.deploySuckersFor` | Deploy sucker contracts for cross-chain bridging. Checked against project owner. Also checked by `JBOmnichainDeployer` and `CTDeployer`. |
|
|
91
|
+
| 31 | `SUCKER_SAFETY` | `JBSucker.enableEmergencyHatchFor` | Enable the emergency hatch to recover stuck tokens. Checked against project owner. |
|
|
92
|
+
| 32 | `SET_SUCKER_DEPRECATION` | `JBSucker.setDeprecation` | Move a sucker through the deprecation lifecycle (ENABLED -> DEPRECATION_PENDING -> SENDING_DISABLED -> DEPRECATED). Checked against project owner. |
|
|
51
93
|
|
|
52
94
|
## Integration Points
|
|
53
95
|
|
|
54
96
|
| Dependency | Import | Used For |
|
|
55
97
|
|------------|--------|----------|
|
|
56
|
-
| None | -- | This library has no dependencies. It is imported by
|
|
98
|
+
| None | -- | This library has no dependencies. It is imported by permission-gated contracts across the ecosystem. |
|
|
99
|
+
|
|
100
|
+
### Repos that import JBPermissionIds
|
|
101
|
+
|
|
102
|
+
| Repository | Contracts |
|
|
103
|
+
|------------|-----------|
|
|
104
|
+
| nana-core-v6 | `JBPermissions`, `JBController`, `JBMultiTerminal`, `JBDirectory` |
|
|
105
|
+
| nana-721-hook-v6 | `JB721TiersHook`, `JB721TiersHookProjectDeployer` |
|
|
106
|
+
| nana-buyback-hook-v6 | `JBBuybackHook`, `JBBuybackHookRegistry` |
|
|
107
|
+
| nana-router-terminal-v6 | `JBRouterTerminalRegistry` |
|
|
108
|
+
| nana-suckers-v6 | `JBSucker`, `JBSuckerRegistry` |
|
|
109
|
+
| nana-omnichain-deployers-v6 | `JBOmnichainDeployer` |
|
|
110
|
+
| revnet-core-v6 | `REVDeployer` |
|
|
111
|
+
| croptop-core-v6 | `CTDeployer`, `CTProjectOwner`, `CTPublisher` |
|
|
57
112
|
|
|
58
113
|
## Key Types
|
|
59
114
|
|
|
60
|
-
N/A -- no structs or enums.
|
|
115
|
+
N/A -- no structs or enums. All values are `uint8 internal constant`.
|
|
61
116
|
|
|
62
117
|
## Gotchas
|
|
63
118
|
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
119
|
+
- **ROOT (ID 1) grants everything.** Any permission check that passes `includeRoot: true` (which all standard `_requirePermissionFrom` calls do) will succeed if the operator has ROOT.
|
|
120
|
+
- **ROOT cannot be granted for wildcard project ID (0).** `JBPermissions.setPermissionsFor` reverts with `JBPermissions_CantSetRootPermissionForWildcardProject()`. This is a critical safety rail.
|
|
121
|
+
- **ROOT operators can delegate, but not escalate.** A ROOT operator can call `setPermissionsFor` on behalf of the account, but the call reverts if the new permission set includes ROOT or targets the wildcard project ID.
|
|
122
|
+
- **Permission ID 0 is forbidden.** `JBPermissions` reverts with `JBPermissions_NoZeroPermission()` if bit 0 is set. Valid IDs start at 1.
|
|
123
|
+
- **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.
|
|
124
|
+
- **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.
|
|
125
|
+
- **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.
|
|
126
|
+
- **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.
|
|
127
|
+
- **SET_BUYBACK_HOOK (ID 27) mismatch.** The source comment says it guards `JBBuybackHookRegistry.setHookFor` and `lockHookFor`, but those functions actually check `SET_BUYBACK_POOL` (ID 26). The ID is still granted by `REVDeployer` as an operator permission.
|
|
128
|
+
- **ADD_PRICE_FEED (ID 19) is checked on JBController, not JBPrices.** The permission gate is on `JBController.addPriceFeed`, which then calls `JBPrices.addPriceFeedFor` internally.
|
|
129
|
+
- **uint8 range.** IDs are `uint8` (0--255) but the packed storage is `uint256`, so the system supports up to 256 permission bits. Currently 32 are defined (1--32).
|
|
68
130
|
|
|
69
131
|
## Example Integration
|
|
70
132
|
|
|
71
133
|
```solidity
|
|
72
|
-
import {JBPermissionIds} from "@bananapus/permission-ids-
|
|
134
|
+
import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
73
135
|
|
|
74
136
|
// Grant an operator permission to queue rulesets for project 5
|
|
75
137
|
uint8[] memory permissionIds = new uint8[](1);
|
|
@@ -80,3 +142,28 @@ permissions.setPermissionsFor(account, JBPermissionsData({
|
|
|
80
142
|
permissionIds: permissionIds
|
|
81
143
|
}));
|
|
82
144
|
```
|
|
145
|
+
|
|
146
|
+
```solidity
|
|
147
|
+
// Grant multiple permissions at once
|
|
148
|
+
uint8[] memory permissionIds = new uint8[](3);
|
|
149
|
+
permissionIds[0] = JBPermissionIds.QUEUE_RULESETS;
|
|
150
|
+
permissionIds[1] = JBPermissionIds.SET_SPLIT_GROUPS;
|
|
151
|
+
permissionIds[2] = JBPermissionIds.SET_PROJECT_URI;
|
|
152
|
+
permissions.setPermissionsFor(account, JBPermissionsData({
|
|
153
|
+
operator: operatorAddress,
|
|
154
|
+
projectId: 5,
|
|
155
|
+
permissionIds: permissionIds
|
|
156
|
+
}));
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
```solidity
|
|
160
|
+
// Check if an operator has a permission
|
|
161
|
+
bool canQueue = permissions.hasPermission({
|
|
162
|
+
operator: operatorAddress,
|
|
163
|
+
account: projectOwner,
|
|
164
|
+
projectId: 5,
|
|
165
|
+
permissionId: JBPermissionIds.QUEUE_RULESETS,
|
|
166
|
+
includeRoot: true, // ROOT holders pass this check
|
|
167
|
+
includeWildcardProjectId: true // Also check projectId=0 grants
|
|
168
|
+
});
|
|
169
|
+
```
|
package/foundry.toml
CHANGED
package/package.json
CHANGED
package/slither-ci.config.json
CHANGED
package/src/JBPermissionIds.sol
CHANGED
|
@@ -41,10 +41,19 @@ library JBPermissionIds {
|
|
|
41
41
|
/* Used by `nana-buyback-hook`: https://github.com/Bananapus/nana-buyback-hook */
|
|
42
42
|
uint8 internal constant SET_BUYBACK_TWAP = 25; // Permission to call `JBBuybackHook.setTwapWindowOf`.
|
|
43
43
|
uint8 internal constant SET_BUYBACK_POOL = 26; // Permission to call `JBBuybackHook.setPoolFor`.
|
|
44
|
+
/// @dev This single ID intentionally gates both setting and locking the buyback hook as a simplification.
|
|
45
|
+
/// Granting this permission allows the operator to call both `JBBuybackHookRegistry.setHookFor` (to configure the
|
|
46
|
+
/// hook) and `JBBuybackHookRegistry.lockHookFor` (to permanently lock the hook configuration). Project owners
|
|
47
|
+
/// should be aware that an operator with this permission can lock the hook, preventing future changes.
|
|
44
48
|
uint8 internal constant SET_BUYBACK_HOOK = 27; // Permission to call `JBBuybackHookRegistry.setHookFor` and
|
|
45
49
|
// `JBBuybackHookRegistry.lockHookFor`.
|
|
46
50
|
|
|
47
51
|
/* Used by `nana-router-terminal`: https://github.com/Bananapus/nana-router-terminal-v6 */
|
|
52
|
+
/// @dev This single ID intentionally gates both setting and locking the router terminal as a simplification.
|
|
53
|
+
/// Granting this permission allows the operator to call both `JBRouterTerminalRegistry.setTerminalFor` (to
|
|
54
|
+
/// configure the terminal) and `JBRouterTerminalRegistry.lockTerminalFor` (to permanently lock the terminal
|
|
55
|
+
/// configuration). Project owners should be aware that an operator with this permission can lock the terminal,
|
|
56
|
+
/// preventing future changes.
|
|
48
57
|
uint8 internal constant SET_ROUTER_TERMINAL = 28; // Permission to call
|
|
49
58
|
// `JBRouterTerminalRegistry.setTerminalFor` and `JBRouterTerminalRegistry.lockTerminalFor`.
|
|
50
59
|
|