@bananapus/omnichain-deployers-v6 0.0.19 → 0.0.21
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 +30 -2
- package/ARCHITECTURE.md +48 -85
- package/AUDIT_INSTRUCTIONS.md +52 -366
- package/CHANGELOG.md +61 -0
- package/README.md +45 -189
- package/RISKS.md +23 -6
- package/SKILLS.md +27 -240
- package/STYLE_GUIDE.md +71 -19
- package/USER_JOURNEYS.md +45 -417
- package/package.json +4 -5
- package/references/operations.md +28 -0
- package/references/runtime.md +28 -0
- package/src/JBOmnichainDeployer.sol +7 -2
- package/src/interfaces/IJBOmnichainDeployer.sol +3 -0
- package/test/JBOmnichainDeployer.t.sol +23 -0
- package/test/OmnichainDeployerEdgeCases.t.sol +10 -1
- package/test/TestAuditGaps.sol +23 -0
- package/test/audit/CarryForwardRejectedHook.t.sol +305 -0
- package/test/audit/JBOmnichainDeployer.t.sol +10 -0
- package/test/fork/OmnichainForkTestBase.sol +10 -7
- package/test/fork/TestOmnichain721QueueAndAdjust.t.sol +28 -21
- package/CHANGE_LOG.md +0 -341
- package/assets/findings/nana-omnichain-deployers-v6-pashov-ai-audit-report-20260330-103536.md +0 -39
package/ADMINISTRATION.md
CHANGED
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
Admin privileges and their scope in nana-omnichain-deployers-v6.
|
|
4
4
|
|
|
5
|
+
## At A Glance
|
|
6
|
+
|
|
7
|
+
| Item | Details |
|
|
8
|
+
|------|---------|
|
|
9
|
+
| Scope | Omnichain project launch, hook composition, sucker deployment, and the deployer's data-hook proxy behavior. |
|
|
10
|
+
| Operators | Project owners and delegates, the `JBOmnichainDeployer`, and the configured `JBSuckerRegistry` with its wildcard token-mapping grant. |
|
|
11
|
+
| Highest-risk actions | Launching a project with the wrong hook composition, terminal configuration, or cross-chain setup, then assuming it can be rewritten later. |
|
|
12
|
+
| Recovery posture | The deployer's immutable dependencies cannot be edited in place. Project-level recovery usually means launching corrected rulesets or redeploying the broader project path. |
|
|
13
|
+
|
|
14
|
+
## Routine Operations
|
|
15
|
+
|
|
16
|
+
- Validate all deploy-time hook choices, 721 settings, and sucker configuration before using `launchProjectFor` or `launchRulesetsFor`.
|
|
17
|
+
- Keep the distinction clear between per-ruleset composed hooks and the deployer's permanent proxy role.
|
|
18
|
+
- Use the deployer when you want its tax-free sucker and mint-permission behavior; otherwise, do not assume it is a drop-in replacement for arbitrary hook wiring.
|
|
19
|
+
|
|
20
|
+
## One-Way Or High-Risk Actions
|
|
21
|
+
|
|
22
|
+
- Constructor-time wildcard permissions and immutable references on the deployer cannot be changed afterward.
|
|
23
|
+
- Launch-time hook composition choices determine how future pay and cash-out flows are merged for that ruleset.
|
|
24
|
+
- A bad omnichain deployment can leave a project with a cross-chain shape that is expensive to unwind operationally.
|
|
25
|
+
|
|
26
|
+
## Recovery Notes
|
|
27
|
+
|
|
28
|
+
- If the project is still administratively flexible, queue new rulesets or use project-level migration paths to move to corrected hook composition.
|
|
29
|
+
- If the deployer's own immutable assumptions are wrong, recovery means deploying a new deployer path rather than trying to hot-fix the existing one.
|
|
30
|
+
|
|
5
31
|
## Roles
|
|
6
32
|
|
|
7
33
|
| Role | How Assigned | Scope |
|
|
@@ -17,7 +43,7 @@ Admin privileges and their scope in nana-omnichain-deployers-v6.
|
|
|
17
43
|
|
|
18
44
|
| Function | Required Role | Permission ID | Scope | What It Does |
|
|
19
45
|
|----------|--------------|---------------|-------|--------------|
|
|
20
|
-
| `deploySuckersFor` | Project owner or operator | `DEPLOY_SUCKERS` | Per-project | Deploys new cross-chain suckers for an existing project via the sucker registry. |
|
|
46
|
+
| `deploySuckersFor` | Project owner or operator | `DEPLOY_SUCKERS` | Per-project | Deploys new cross-chain suckers for an existing project via the sucker registry. The same operation also applies token mappings on the new suckers, so existing projects must already have the registry arranged as an authorized `MAP_SUCKER_TOKEN` operator for that project. |
|
|
21
47
|
| `launchRulesetsFor` | Project owner or operator | `LAUNCH_RULESETS` + `SET_TERMINALS` | Per-project | Deploys a 721 tiers hook, launches new rulesets with terminal configuration for an existing project. Has a simplified overload without `deploy721Config`. |
|
|
22
48
|
| `queueRulesetsOf` | Project owner or operator | `QUEUE_RULESETS` | Per-project | Queues new rulesets for an existing project. If tiers provided, deploys a new 721 hook. Otherwise, carries forward the 721 hook from the latest ruleset. Has a simplified overload without `deploy721Config`. |
|
|
23
49
|
|
|
@@ -55,12 +81,14 @@ Admin privileges and their scope in nana-omnichain-deployers-v6.
|
|
|
55
81
|
|
|
56
82
|
| Action | Who | Mechanism |
|
|
57
83
|
|--------|-----|-----------|
|
|
58
|
-
| Deploy suckers for existing project | Project owner or DEPLOY_SUCKERS operator | `deploySuckersFor` calls `SUCKER_REGISTRY.deploySuckersFor` |
|
|
84
|
+
| Deploy suckers for existing project | Project owner or DEPLOY_SUCKERS operator | `deploySuckersFor` calls `SUCKER_REGISTRY.deploySuckersFor`; because the registry also applies the initial mappings, existing projects must pair this with a project-level `MAP_SUCKER_TOKEN` arrangement for the registry |
|
|
59
85
|
| Deploy suckers during project launch | Project deployer (anyone) | Included in `launchProjectFor` if `salt != bytes32(0)` |
|
|
60
86
|
| Map sucker tokens | JBSuckerRegistry | Granted MAP_SUCKER_TOKEN at construction with projectId=0 wildcard |
|
|
61
87
|
| Grant 0% cash-out tax to suckers | Automatic | `beforeCashOutRecordedWith` checks `SUCKER_REGISTRY.isSuckerOf` |
|
|
62
88
|
| Grant mint permission to suckers | Automatic | `hasMintPermissionFor` checks `SUCKER_REGISTRY.isSuckerOf` |
|
|
63
89
|
|
|
90
|
+
**Existing-project operator note:** `deploySuckersFor` looks like a deployment-only action at the top level, but it is intentionally a deploy-and-map flow. If an existing project delegates `DEPLOY_SUCKERS` without also arranging `MAP_SUCKER_TOKEN` for the registry, the transaction will fail once the registry reaches the mapping step.
|
|
91
|
+
|
|
64
92
|
**Cross-chain determinism:** The salt for sucker deployment is combined with `_msgSender()` (`keccak256(abi.encode(salt, _msgSender()))`). Deploying from the same sender address with the same salt on each chain produces matching sucker addresses.
|
|
65
93
|
|
|
66
94
|
## Data Hook Proxy Pattern
|
package/ARCHITECTURE.md
CHANGED
|
@@ -1,107 +1,70 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Architecture
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`nana-omnichain-deployers-v6` launches Juicebox projects that are ready for both tiered NFTs and cross-chain suckers from day one. It also acts as a wrapper data hook so it can compose a 721 hook with an optional extra data hook while granting suckers tax-free cash outs and mint permission.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Boundaries
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
├── interfaces/
|
|
13
|
-
│ └── IJBOmnichainDeployer.sol — Interface
|
|
14
|
-
└── structs/
|
|
15
|
-
├── JBDeployerHookConfig.sol — Custom hook configuration for deployment
|
|
16
|
-
├── JBOmnichain721Config.sol — 721 hook deployment config (tiers + cashout flag + salt)
|
|
17
|
-
├── JBTiered721HookConfig.sol — Per-ruleset 721 hook configuration
|
|
18
|
-
└── JBSuckerDeploymentConfig.sol — Sucker deployment parameters
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Hook Storage Mappings
|
|
9
|
+
- `JBOmnichainDeployer` is both a deployer and a live hook wrapper. Those two roles are inseparable.
|
|
10
|
+
- The repo composes `nana-721-hook-v6` and `nana-suckers-v6`; it should not duplicate their internal logic.
|
|
11
|
+
- Project accounting still happens in the core protocol.
|
|
22
12
|
|
|
23
|
-
|
|
13
|
+
## Main Components
|
|
24
14
|
|
|
25
|
-
|
|
15
|
+
| Component | Responsibility |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `JBOmnichainDeployer` | Project launch, ruleset queueing, hook composition, and sucker-safe cash-out policy |
|
|
18
|
+
| config structs | 721 hook config, extra hook config, and sucker deployment config |
|
|
19
|
+
| `IJBOmnichainDeployer` | Public deployer and inspection interface |
|
|
26
20
|
|
|
27
|
-
|
|
21
|
+
## Runtime Model
|
|
28
22
|
|
|
29
|
-
|
|
23
|
+
### Launch
|
|
30
24
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
→ Launch JB project via controller.launchProjectFor
|
|
39
|
-
→ Transfer 721 hook ownership to project (after project NFT exists)
|
|
40
|
-
→ Deploy suckers via JBSuckerRegistry
|
|
41
|
-
→ Transfer project NFT to owner
|
|
25
|
+
```text
|
|
26
|
+
caller
|
|
27
|
+
-> launch project or queue rulesets through the deployer
|
|
28
|
+
-> deployer installs itself as the ruleset data hook
|
|
29
|
+
-> deployer deploys or carries forward the 721 hook
|
|
30
|
+
-> deployer optionally deploys sucker pairs with deterministic salts
|
|
31
|
+
-> project ownership is transferred to the intended owner
|
|
42
32
|
```
|
|
43
33
|
|
|
44
|
-
###
|
|
45
|
-
```
|
|
46
|
-
Payment → JBOmnichainDeployer.beforePayRecordedWith()
|
|
47
|
-
→ Calls 721 hook first (from _tiered721HookOf) for specs/split amounts
|
|
48
|
-
→ If 721 hook returned specs: include in merged output
|
|
49
|
-
→ Calls custom hook from _extraDataHookOf (if useDataHookForPay=true)
|
|
50
|
-
→ Custom hook receives reduced amount (payment - splitAmount)
|
|
51
|
-
→ Uses 721 hook's split-adjusted weight directly
|
|
52
|
-
→ Merges both hook specs (721 first if any, then custom)
|
|
53
|
-
|
|
54
|
-
Cash Out → JBOmnichainDeployer.beforeCashOutRecordedWith()
|
|
55
|
-
→ If caller is a registered sucker: return 0% cash-out tax (early return)
|
|
56
|
-
→ Calls 721 hook (from _tiered721HookOf, if useDataHookForCashOut=true)
|
|
57
|
-
→ Updates cashOutTaxRate, cashOutCount, totalSupply from 721 hook response
|
|
58
|
-
→ Calls custom hook (from _extraDataHookOf, if useDataHookForCashOut=true)
|
|
59
|
-
→ Receives already-updated values from 721 hook
|
|
60
|
-
→ Further updates cashOutTaxRate, cashOutCount, totalSupply
|
|
61
|
-
→ Merges both hooks' specifications (721 specs first, then custom hook specs)
|
|
62
|
-
→ If 721 hook has flag=true and reverts (fungible cashout): revert propagates
|
|
63
|
-
→ If neither hook has the flag set: return original values
|
|
64
|
-
```
|
|
34
|
+
### Pay And Cash-Out Wrapping
|
|
65
35
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
→ Queue new rulesets via JBController
|
|
73
|
-
|
|
74
|
-
Owner → JBOmnichainDeployer.launchRulesetsFor()
|
|
75
|
-
→ Deploy new 721 hook
|
|
76
|
-
→ Launch rulesets for an existing project
|
|
77
|
-
→ Configure terminal integration
|
|
36
|
+
```text
|
|
37
|
+
runtime callback
|
|
38
|
+
-> if the actor is a registered sucker, return the special tax-free / mint-enabled path
|
|
39
|
+
-> otherwise call the 721 hook first when configured
|
|
40
|
+
-> then call the extra data hook when configured
|
|
41
|
+
-> merge hook specs in order and return the combined result
|
|
78
42
|
```
|
|
79
43
|
|
|
80
|
-
##
|
|
81
|
-
|
|
82
|
-
| Point | Interface | Purpose |
|
|
83
|
-
|-------|-----------|---------|
|
|
84
|
-
| Data hook (pay) | `IJBRulesetDataHook.beforePayRecordedWith` | Compose 721 + custom hook for payments |
|
|
85
|
-
| Data hook (cashout) | `IJBRulesetDataHook.beforeCashOutRecordedWith` | 0% tax for suckers, forward to hooks |
|
|
86
|
-
| Sucker registry | `IJBSuckerRegistry` | Sucker deployment and discovery |
|
|
87
|
-
| 721 hook deployer | `IJB721TiersHookDeployer` | 721 tiers hook deployment (always used) |
|
|
44
|
+
## Critical Invariants
|
|
88
45
|
|
|
89
|
-
|
|
46
|
+
- Suckers must be able to bridge without getting trapped behind custom cash-out policies.
|
|
47
|
+
- Hook order matters: the 721 hook runs first, and the extra hook receives the updated context.
|
|
48
|
+
- The deployer's predicted ruleset IDs must stay aligned with `JBRulesets` behavior; the storage keys depend on it.
|
|
49
|
+
- Every project launched through this repo gets a 721 hook surface, even if it starts with zero tiers.
|
|
90
50
|
|
|
91
|
-
|
|
51
|
+
## Where Complexity Lives
|
|
92
52
|
|
|
93
|
-
|
|
53
|
+
- This repo hides composition complexity behind a simple launch surface, which makes stale assumptions dangerous.
|
|
54
|
+
- Ruleset ID prediction is a subtle but central storage keying mechanism.
|
|
55
|
+
- The sucker exception path intentionally short-circuits normal hook composition and must stay easy to reason about.
|
|
94
56
|
|
|
95
|
-
|
|
57
|
+
## Dependencies
|
|
96
58
|
|
|
97
|
-
|
|
59
|
+
- `nana-core-v6` for project launch and hook interfaces
|
|
60
|
+
- `nana-721-hook-v6` for tiered NFT behavior
|
|
61
|
+
- `nana-suckers-v6` for cross-chain transport
|
|
62
|
+
- `nana-ownable-v6` for project-following hook ownership
|
|
98
63
|
|
|
99
|
-
|
|
64
|
+
## Safe Change Guide
|
|
100
65
|
|
|
101
|
-
|
|
102
|
-
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
-
|
|
106
|
-
- `@bananapus/suckers-v6` — Cross-chain sucker registry
|
|
107
|
-
- `@openzeppelin/contracts` — ERC2771, ERC721Receiver
|
|
66
|
+
- Review launch-time logic and runtime-hook logic together. This repo is easy to break by fixing only one side.
|
|
67
|
+
- When changing hook composition, verify both payment and cash-out ordering.
|
|
68
|
+
- If you touch ruleset ID prediction, test same-block and queued-ruleset edge cases explicitly.
|
|
69
|
+
- Keep deterministic salt handling stable across chains; address predictability is part of the feature.
|
|
70
|
+
- Treat "transparent wrapper" claims as something to prove continuously, not assume.
|