@bananapus/721-hook-v6 0.0.36 → 0.0.37

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
@@ -4,84 +4,72 @@
4
4
 
5
5
  | Item | Details |
6
6
  | --- | --- |
7
- | Scope | Per-hook ownership, delegated 721 administration, and hook deployment flows |
8
- | Control posture | Per-instance owner or project-owner control with delegated `JBPermissions` |
9
- | Highest-risk actions | Tier adjustments, owner minting, metadata changes, and misassigned hook ownership |
10
- | Recovery posture | Project-specific config can sometimes be superseded with new rulesets, but bad clone wiring usually means replacement hooks |
7
+ | Scope | Tiered NFT hook configuration, tier adjustment, and deployer wiring |
8
+ | Control posture | Mixed project-owner and delegated control |
9
+ | Highest-risk actions | Adjusting tiers, setting discount or metadata behavior, and wiring the wrong hook or resolver |
10
+ | Recovery posture | Some configuration is mutable, but many tier properties are intentionally one-way |
11
11
 
12
12
  ## Purpose
13
13
 
14
- `nana-721-hook-v6` is administered per hook instance. The effective admin is the hook owner resolved through `JBOwnable`, plus any operators granted specific `JBPermissions`. The dangerous surfaces are tier adjustment, metadata changes, owner minting, discount changes, and hook deployment ownership.
14
+ `nana-721-hook-v6` splits control between project-level hook ownership and the tier rules enforced by the store. Many important settings can be changed only in limited ways after launch.
15
15
 
16
16
  ## Control Model
17
17
 
18
- - Each hook instance has its own owner.
19
- - Ownership can follow an EOA or a Juicebox project NFT through `JBOwnable`.
20
- - Fine-grained operator delegation runs through `JBPermissions`.
21
- - Deployers are permissionless for new hooks, but existing-project launch and queue flows are permission-gated.
22
- - The store has no owner role; it trusts `msg.sender`-keyed namespaces.
18
+ - project owners or delegates control hook-level configuration
19
+ - tier creation and mutation are permissioned and partially one-way
20
+ - the store trusts the calling hook for its own state namespace
21
+ - deployers package setup, but do not remove the need for runtime review
23
22
 
24
23
  ## Roles
25
24
 
26
25
  | Role | How Assigned | Scope | Notes |
27
26
  | --- | --- | --- | --- |
28
- | Hook owner | `JBOwnable.owner()` | Per hook | May resolve dynamically through a project NFT |
29
- | Hook operator | Granted by `JBPermissions` | Per project | Usually `ADJUST_721_TIERS`, `MINT_721`, `SET_721_METADATA`, `SET_721_DISCOUNT_PERCENT` |
30
- | Project owner | `JBProjects.ownerOf(projectId)` | Per project | Relevant for project-deployer flows |
31
- | Terminal | `JBDirectory` routing | Per project | Can call pay and cash-out hook entrypoints |
32
- | Deployer caller | Anyone | Per deployment | Can deploy new standalone hooks |
27
+ | Project owner | `owner()` or project control surface | Per hook | Main authority |
28
+ | Tier delegate | `JBPermissions` grant | Per project | Usually tier, mint, discount, or metadata permissions |
29
+ | Reserve beneficiary | Tier config | Per tier | Receives reserve NFTs |
33
30
 
34
31
  ## Privileged Surfaces
35
32
 
36
- | Contract | Function | Who Can Call | Effect |
37
- | --- | --- | --- | --- |
38
- | `JB721TiersHook` | `adjustTiers(...)` | Owner or `ADJUST_721_TIERS` operator | Adds or removes tiers and updates split groups |
39
- | `JB721TiersHook` | `mintFor(...)` | Owner or `MINT_721` operator | Owner mint path, subject to tier flags |
40
- | `JB721TiersHook` | `setMetadata(...)` | Owner or `SET_721_METADATA` operator | Updates collection-level metadata and resolver references |
41
- | `JB721TiersHook` | `setDiscountPercentOf(...)`, `setDiscountPercentsOf(...)` | Owner or `SET_721_DISCOUNT_PERCENT` operator | Changes discount settings where allowed |
42
- | `JB721TiersHook` | `initialize(...)` | Anyone once per clone | One-time hook initialization and ownership setup |
43
- | `JB721TiersHookProjectDeployer` | `launchRulesetsFor(...)` | Project owner or relevant delegates | Launches hook-backed rulesets for an existing project |
44
- | `JB721TiersHookProjectDeployer` | `queueRulesetsOf(...)` | Project owner or `QUEUE_RULESETS` delegate | Queues hook-backed rulesets for an existing project |
33
+ - `adjustTiers(...)`
34
+ - `mintFor(...)`
35
+ - `setDiscountPercentOf(...)`
36
+ - `setMetadata(...)`
37
+ - deployer setup and hook ownership transfer paths
45
38
 
46
39
  ## Immutable And One-Way
47
40
 
48
- - Implementation constructor dependencies are immutable.
49
- - Clone initialization is one-time.
50
- - Per-tier price, reserve frequency, and several flags are effectively set-once semantics.
51
- - Ownership transfers change every permission check because privileged functions check against `owner()`.
41
+ - many tier properties are immutable once created
42
+ - removed tiers do not reduce `maxTierIdOf`
43
+ - pool-like mutable rescue does not exist here; bad tier design is often expensive to unwind
52
44
 
53
45
  ## Operational Notes
54
46
 
55
- - Grant narrow per-project permissions instead of owner-equivalent access where possible.
56
- - Treat `adjustTiers(...)` as an economic change, not just content management.
57
- - Verify hook ownership and pricing context before publishing a clone address.
58
- - When this hook is wrapped by deployers, review hook-order assumptions as part of administration.
47
+ - review tier parameters before launch as if they were economic policy
48
+ - treat discount changes and metadata changes as meaningful authority, not cosmetic controls
49
+ - be explicit about whether the hook participates in pay, cash out, or both
50
+ - separate resolver trust from hook and store trust
59
51
 
60
52
  ## Machine Notes
61
53
 
62
- - Do not assume `owner()` is a static address; it may resolve through a project NFT.
63
- - Treat `src/JB721TiersHook.sol` and `src/JB721TiersHookStore.sol` together as the control-plane source of truth.
64
- - If a downstream deployer changes hook ownership or ruleset ordering, re-evaluate the admin model instead of reusing old assumptions.
54
+ - do not reason from the hook alone when the bug may live in the store
55
+ - if a resolver is involved, inspect it separately
56
+ - if tier counts are large, re-check gas-sensitive reads and writes before operational changes
65
57
 
66
58
  ## Recovery
67
59
 
68
- - If the wrong immutable dependencies or ownership model were deployed, use a new hook clone.
69
- - If a project-specific configuration is bad, prefer migrating future rulesets to a replacement hook over trying to retrofit unsupported behavior.
60
+ - some mistakes can be corrected through allowed metadata or discount changes
61
+ - many tier-design mistakes are effectively permanent once live
62
+ - deployer mistakes may require a new hook path rather than in-place repair
70
63
 
71
64
  ## Admin Boundaries
72
65
 
73
- - The owner cannot change the store's constructor immutables or the clone's one-time initialization.
74
- - The owner cannot overwrite original tier price semantics used for cash-out weight.
75
- - The owner cannot bypass store-level flags such as non-removable tiers or discount increase restrictions.
76
- - There is no global admin who can rewrite every hook instance at once.
66
+ - no one can rewrite immutable tier properties after creation
67
+ - deployers do not bypass runtime permissions after setup
68
+ - resolver behavior cannot fix broken hook accounting
77
69
 
78
70
  ## Source Map
79
71
 
80
72
  - `src/JB721TiersHook.sol`
81
- - `src/JB721TiersHookProjectDeployer.sol`
82
- - `src/JB721TiersHookDeployer.sol`
83
73
  - `src/JB721TiersHookStore.sol`
84
- - `script/Deploy.s.sol`
85
- - `script/helpers/Hook721DeploymentLib.sol`
86
- - `test/E2E/`
87
- - `test/TestAuditGaps.sol`
74
+ - `src/JB721TiersHookDeployer.sol`
75
+ - `src/JB721TiersHookProjectDeployer.sol`
package/ARCHITECTURE.md CHANGED
@@ -2,86 +2,92 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- `nana-721-hook-v6` is the canonical tiered NFT issuance layer for Juicebox V6. It lets a project mint NFTs on payment, manage tier pricing and supply, accumulate NFT credits, lazily mint reserves, and optionally use NFT-aware cash-out behavior.
5
+ `nana-721-hook-v6` is the shared tiered NFT layer for Juicebox V6. It lets projects sell NFT tiers, track reserves, route split payouts, and cash out NFTs without replacing core treasury accounting.
6
6
 
7
7
  ## System Overview
8
8
 
9
- `JB721TiersHook` is the project-facing hook surface. Through the shared `JB721Hook` base, it installs itself as both the ruleset data hook and the post-settlement pay and cash-out hook for the project. `JB721TiersHookStore` is the compact storage and validation backend that defines most tier semantics. The deployers package that behavior for existing projects or one-shot launches. The repo composes `nana-core-v6` rather than replacing terminal, controller, or surplus accounting.
9
+ `JB721TiersHook` is the runtime hook. `JB721TiersHookStore` is the accounting backend for tiers, supply, reserves, and lookup. The deployers package that hook into reusable flows for existing projects and new project launches.
10
+
11
+ Custom token URI resolvers usually live outside this repo, but they still affect the trusted surface seen by users.
10
12
 
11
13
  ## Core Invariants
12
14
 
13
- - Tier ordering, category ordering, and tier IDs are part of storage semantics.
14
- - Original configured tier price drives cash-out weight; discounts affect mint price, not reclaim weight.
15
- - Reserve frequency and owner-mint settings must not combine into duplicate mint authority.
16
- - Pending reserves count in supply-sensitive logic before reserve tokens are lazily minted.
17
- - Preview behavior must stay aligned with live mint and cash-out behavior.
18
- - Tier splits can reduce the fungible-token mint weight before terminal settlement unless `issueTokensForSplits` is enabled.
19
- - If `useDataHookForCashOut` is enabled, NFT cash-out semantics intentionally displace fungible-token cash-out behavior.
15
+ - the hook must not create alternate treasury accounting
16
+ - tier supply, burned counts, and reserves must stay coherent
17
+ - cash-out weight must reflect the intended tier economics
18
+ - reserve minting and split routing must not drift from stored tier state
19
+ - store-linked list and bitmap assumptions must stay valid under tier add, remove, and clean operations
20
+ - deployer wiring must preserve the expected ruleset and hook shape
20
21
 
21
22
  ## Modules
22
23
 
23
24
  | Module | Responsibility | Notes |
24
25
  | --- | --- | --- |
25
- | `JB721TiersHook` | Data-hook, pay-hook, and optional cash-out-hook behavior | Project-facing entrypoint |
26
- | `JB721TiersHookStore` | Tier storage, mint accounting, reserves, validation | Storage-critical |
27
- | `JB721Hook`, `ERC721` | Shared NFT machinery and metadata plumbing | Base abstractions |
28
- | `JB721TiersHookDeployer`, `JB721TiersHookProjectDeployer` | Clone and launch helpers | Deployment surface |
26
+ | `JB721TiersHook` | Pay hook, cash-out hook, permissions, and project-facing execution | Runtime core |
27
+ | `JB721TiersHookStore` | Tier definitions, balances, reserve tracking, and accounting | Shared state |
28
+ | `JB721TiersHookDeployer` | Clone deployer for existing projects | Wiring helper |
29
+ | `JB721TiersHookProjectDeployer` | Project-launch deployer with hook setup | Launch helper |
30
+ | `JB721Hook` | Abstract 721 hook base | Shared behavior |
29
31
 
30
32
  ## Trust Boundaries
31
33
 
32
- - Treasury accounting, controller semantics, and permissions live in `nana-core-v6`.
33
- - Resolver contracts such as Banny are outside this repo and are part of the trusted metadata surface when configured.
34
- - Hook composition order matters when this hook is wrapped by deployers such as `nana-omnichain-deployers-v6`.
34
+ - core accounting, pricing, and terminal authentication remain in `nana-core-v6`
35
+ - metadata resolvers can be project-specific and should be treated as trusted external surfaces
36
+ - the store is trusted by every hook that uses it
37
+ - deployers are trusted to wire the hook into the intended project and ruleset shape
35
38
 
36
39
  ## Critical Flows
37
40
 
38
- ### Payment
39
-
40
- ```text
41
- terminal payment
42
- -> data hook decodes metadata and requested tiers
43
- -> hook computes mintable tiers, split forwarding, beneficiary resolution, and leftover value
44
- -> terminal settles the payment into the project
45
- -> post-settlement pay hook mints NFTs and may store remaining value as credits
46
- ```
47
-
48
- ### Reserve Minting
41
+ ### Pay And Mint
49
42
 
50
43
  ```text
51
- tier purchases
52
- -> accumulate reserve entitlement
53
- -> reserve-mint call later realizes those pending reserve tokens
44
+ payment arrives
45
+ -> hook decodes metadata and tier choices
46
+ -> store records mints, credits, supply changes, and reserve effects
47
+ -> hook may route split payouts from forwarded funds
48
+ -> collection state and balances update for the beneficiary
54
49
  ```
55
50
 
56
51
  ### Cash Out
57
52
 
58
53
  ```text
59
- holder burns NFT
60
- -> data hook overrides fungible-token cash-out inputs when enabled
61
- -> terminal settles the cash out using NFT-derived weight
62
- -> post-settlement cash-out hook burns the specified NFTs
63
- -> reclaim value is derived from the tier's original configured price
54
+ cash out requested
55
+ -> hook checks NFT-specific metadata and selected token IDs
56
+ -> hook burns NFTs
57
+ -> store records burn and supply effects
58
+ -> terminal reclaims value using hook-aware cash-out math
64
59
  ```
65
60
 
66
61
  ## Accounting Model
67
62
 
68
- The repo owns tier accounting, reserve accounting, credit accounting, and NFT-specific cash-out inputs. It also owns the mapping from hook metadata to NFT mint and burn side effects after terminal settlement. It does not own the canonical treasury ledger, which remains in `nana-core-v6`.
63
+ This repo owns tier accounting and NFT lifecycle logic. It does not own the canonical project ledger for balances, fees, or surplus.
64
+
65
+ The most important state lives in the store: remaining supply, burned counts, reserve tracking, and per-tier configuration.
69
66
 
70
67
  ## Security Model
71
68
 
72
- - Store layout changes have repo-wide blast radius because many downstream packages assume stable tier semantics.
73
- - Metadata decoding is part of economic correctness because it chooses tiers, credits, and cash-out behavior.
74
- - Terminal authorization in the base hook is part of the trust model; arbitrary callers must not be able to trigger pay or cash-out hooks.
75
- - Initialization is one-time and ends by transferring ownership to the initializer. Clone deployers and launch flows depend on that handoff being preserved.
76
- - Reserve math and supply math must be reviewed together.
69
+ - store corruption has ecosystem-wide blast radius because many products reuse it
70
+ - reserve logic, discounts, and cash-out weight are the main economic risk surfaces
71
+ - split distribution and fallback behavior are part of correctness, not a secondary concern
72
+ - gas costs matter because some reads and writes scale with tier count
77
73
 
78
74
  ## Safe Change Guide
79
75
 
80
- - Treat store changes as ecosystem-wide changes.
81
- - Keep previews aligned with state-changing behavior.
82
- - If you change split behavior, re-check both NFT mint side effects and the fungible-token weight returned to the terminal.
83
- - When adding metadata fields or flags, update wrapper deployers and downstream integrations in the same change set.
84
- - If reserve logic changes, re-check supply math, reserve minting, and cash-out denominators together.
76
+ - review hook and store behavior together when changing tier lifecycle logic
77
+ - if reserve logic changes, re-check cash-out weight and pending reserve effects together
78
+ - if deployer behavior changes, re-check ruleset wiring and ownership transfer paths
79
+ - do not treat resolver behavior as proof that hook accounting is correct
80
+
81
+ ## Canonical Checks
82
+
83
+ - pay, mint, and redeem end-to-end behavior:
84
+ `test/E2E/Pay_Mint_Redeem_E2E.t.sol`
85
+ - store and lifecycle invariants:
86
+ `test/invariants/TierLifecycleInvariant.t.sol`
87
+ `test/invariants/TieredHookStoreInvariant.t.sol`
88
+ - split-credit and deployer regressions:
89
+ `test/audit/CodexSplitCreditsMismatch.t.sol`
90
+ `test/regression/ProjectDeployerRulesets.t.sol`
85
91
 
86
92
  ## Source Map
87
93
 
@@ -89,3 +95,4 @@ The repo owns tier accounting, reserve accounting, credit accounting, and NFT-sp
89
95
  - `src/JB721TiersHookStore.sol`
90
96
  - `src/JB721TiersHookDeployer.sol`
91
97
  - `src/JB721TiersHookProjectDeployer.sol`
98
+ - `src/libraries/JB721TiersHookLib.sol`
@@ -1,114 +1,74 @@
1
1
  # Audit Instructions
2
2
 
3
- This repo is the tiered ERC-721 hook system for Juicebox payments and NFT cash-outs. Audit it as a shared primitive used by many other repos.
3
+ This repo adds tiered NFT issuance and cash-out behavior to Juicebox projects. Audit it as a shared accounting layer whose mistakes can affect many downstream products.
4
4
 
5
5
  ## Audit Objective
6
6
 
7
7
  Find issues that:
8
- - let users mint tiers more cheaply than intended
9
- - over-mint, under-burn, or miscount reserves, credits, or supply
10
- - route split funds incorrectly or let split paths distort token issuance
11
- - let NFT cash-outs reclaim more value than intended
12
- - corrupt shared store state across different hook instances
8
+
9
+ - corrupt tier supply, reserve state, or burn accounting
10
+ - misprice cash outs or split routing
11
+ - let permissions or deployer wiring create unsafe lifecycle changes
12
+ - create gas or liveness failures in tier-heavy deployments
13
+ - break trust boundaries between hook, store, and resolver behavior
13
14
 
14
15
  ## Scope
15
16
 
16
17
  In scope:
18
+
17
19
  - `src/JB721TiersHook.sol`
18
20
  - `src/JB721TiersHookStore.sol`
19
- - `src/JB721TiersHookDeployer.sol`
20
- - `src/JB721TiersHookProjectDeployer.sol`
21
- - `src/abstract/`
22
- - `src/interfaces/`
23
- - `src/libraries/`
24
- - `src/structs/`
21
+ - deployers, libraries, interfaces, and structs under `src/`
25
22
  - deployment scripts in `script/`
26
23
 
27
- This repo is depended on by Defifa, Croptop, Banny, Revnets, and omnichain deployers. Bugs here often have ecosystem-wide blast radius.
28
-
29
24
  ## Start Here
30
25
 
31
- 1. `src/JB721TiersHookStore.sol`
32
- 2. `src/JB721TiersHook.sol`
33
- 3. `src/JB721TiersHookDeployer.sol` and `src/JB721TiersHookProjectDeployer.sol`
26
+ 1. `src/JB721TiersHook.sol`
27
+ 2. `src/JB721TiersHookStore.sol`
28
+ 3. `src/libraries/JB721TiersHookLib.sol`
34
29
 
35
30
  ## Security Model
36
31
 
37
- The hook can act as:
38
- - a data hook for payment and cash-out accounting inputs
39
- - a pay hook that mints NFTs
40
- - a cash-out hook that burns NFTs and computes reclaim weight
41
-
42
- Key moving parts:
43
- - `JB721TiersHookStore` holds compact tier state
44
- - hook instances read and mutate tier data through the store
45
- - tier prices, discounts, reserves, credits, split percentages, and category order shape mint behavior
46
- - optional token URI resolvers can override metadata generation
32
+ The hook:
47
33
 
48
- The most important design subtlety is that this repo affects both:
49
- - NFT state
50
- - core Juicebox accounting inputs and fulfillment order
51
-
52
- That combination is why small-looking mistakes here often become ecosystem-wide economic bugs.
34
+ - mints and burns tiered NFTs through Juicebox flows
35
+ - records tier lifecycle state in a shared store
36
+ - can route split payouts from forwarded value
37
+ - composes with project-specific metadata resolvers
53
38
 
54
39
  ## Roles And Privileges
55
40
 
56
41
  | Role | Powers | How constrained |
57
42
  |------|--------|-----------------|
58
- | Project authority | Adjust tiers, discounts, and resolver setup | Must not break supply, ordering, or accounting assumptions |
59
- | Hook instance | Mint, burn, and compute accounting inputs | Must stay isolated from other hook instances |
60
- | Store contract | Hold shared tier state | Must not leak or corrupt cross-project data |
61
- | Token URI resolver | Supply metadata only | Must not become a hidden control surface |
43
+ | Project authority | Configure tiers, metadata, and minting policy | Must stay inside explicit permission checks |
44
+ | Store caller | Mutate store state in its own namespace | Must not corrupt tier accounting |
45
+ | Resolver | Serve metadata and URI behavior | Must not be confused with accounting truth |
62
46
 
63
47
  ## Integration Assumptions
64
48
 
65
49
  | Dependency | Assumption | What breaks if wrong |
66
50
  |------------|------------|----------------------|
67
- | `nana-core-v6` | Payment and cash-out semantics remain coherent | Downstream economic routing becomes unsafe |
68
- | Split recipients and hooks | Failures are handled in bounded ways | Mint accounting and treasury routing desync |
51
+ | `nana-core-v6` | Terminal auth and pricing behavior are accurate | Pay and cash-out behavior drift |
52
+ | Resolver repo | Metadata reads behave as expected | UI and marketplace behavior break |
69
53
 
70
54
  ## Critical Invariants
71
55
 
72
- 1. Supply caps hold
73
- No tier may mint beyond its configured total supply once purchases, owner mints, and pending reserves are all considered.
74
-
75
- 2. Reserve accounting is exact
76
- Pending reserves must neither disappear nor inflate reclaim denominators beyond what the design intends.
77
-
78
- 3. Split routing matches accounting
79
- If part of a mint price is routed to splits, token issuance and treasury accounting must reflect only the intended project portion.
80
-
81
- 4. Cash-out weight is consistent
82
- The reclaim value for NFTs must match documented tier economics and must not be manipulable through discounts, credits, cross-currency inputs, or reserve timing.
83
-
84
- 5. Shared store isolation
85
- One hook instance must not corrupt or observe mutable state belonging to another project unexpectedly.
86
-
87
- 6. Credit semantics remain bounded
88
- Unused payment value that becomes credits must not let a user later mint tiers, trigger splits, or receive project-token issuance on terms they did not actually fund.
89
-
90
- 7. Resolver trust stays read-only unless explicitly intended
91
- Token URI resolvers must not become an implicit control plane for mint, burn, or accounting behavior.
56
+ 1. Tier supply stays coherent.
57
+ Remaining supply, burned counts, and outstanding ownership must reconcile.
58
+ 2. Reserve logic stays bounded.
59
+ Pending reserves and reserve minting must not over-allocate.
60
+ 3. Cash-out weight is consistent.
61
+ NFT reclaim value must match the tier model the hook and store intend.
62
+ 4. Split and fallback behavior is safe.
63
+ Failed split paths must not silently corrupt value or lifecycle state.
92
64
 
93
65
  ## Attack Surfaces
94
66
 
95
- - `beforePayRecordedWith`, `afterPayRecordedWith`, and cash-out hooks
96
- - credit handling when `payer != beneficiary`
97
- - discount logic versus cash-out pricing
98
- - pending reserve minting and denominator logic
99
- - `splitPercent` handling and hook distribution fallback behavior
100
- - deployers that transfer ownership or queue rulesets around the hook
101
-
102
- Replay these sequences:
103
- 1. cross-currency payment with missing, stale, or asymmetric prices
104
- 2. leftover credits across different payer and beneficiary arrangements
105
- 3. split-routed tier purchases when downstream hooks or terminals fail
106
- 4. reserve-heavy tiers followed by NFT cash-out before reserves are minted
107
- 5. tier adjustment or discount changes around active minting and cash-out windows
108
-
109
- ## Accepted Risks Or Behaviors
110
-
111
- - Conservative behavior is preferable to optimistic behavior because downstream repos often treat these surfaces as economic truth.
67
+ - pay and cash-out hook entrypoints
68
+ - tier add, remove, and clean flows
69
+ - reserve minting
70
+ - split distribution and fallback paths
71
+ - resolver integration
112
72
 
113
73
  ## Verification
114
74
 
package/README.md CHANGED
@@ -15,15 +15,15 @@ Audit instructions: [AUDIT_INSTRUCTIONS.md](./AUDIT_INSTRUCTIONS.md)
15
15
  This package is the main shared tiered NFT hook used across the V6 ecosystem. Projects use it to:
16
16
 
17
17
  - sell fixed-price NFT tiers through Juicebox payments
18
- - apply tier supply, reserve frequency, voting unit, and discount rules
18
+ - apply tier supply, reserve frequency, voting units, and discount rules
19
19
  - cash out tiers through the Juicebox terminal surface
20
- - compose custom metadata resolvers such as Banny or Defifa
20
+ - plug in custom metadata resolvers such as Banny or Defifa
21
21
 
22
- The deployer helps clone hooks for existing projects, and the project-deployer helps launch new projects with a hook already attached.
22
+ The deployer helps clone hooks for existing projects, and the project deployer helps launch new projects with a hook already attached.
23
23
 
24
- Use this repo when a project's NFT logic should be part of its payment and cash-out flow. Do not use it for collection-specific rendering or game logic; those belong in higher-level packages like Banny or Defifa.
24
+ Use this repo when a project's NFT logic should be part of its payment and cash-out flow. Do not use it for collection-specific rendering or game logic. Those belong in higher-level packages like Banny or Defifa.
25
25
 
26
- The important architectural point is that this repo does not just "mint NFTs on pay." It changes how payment value, tier state, reserves, and cash-out behavior interact.
26
+ This repo does more than "mint NFTs on pay." It changes how payment value, tier state, reserves, and cash-out behavior interact.
27
27
 
28
28
  ## Key Contracts
29
29
 
@@ -41,17 +41,10 @@ Think about the repo in three pieces:
41
41
 
42
42
  1. `JB721TiersHook` defines behavior at the project edge
43
43
  2. `JB721TiersHookStore` is the tier accounting backend
44
- 3. deployers package the hook into reusable project-launch and clone flows
44
+ 3. deployers package the hook into reusable launch and clone flows
45
45
 
46
46
  If a bug affects supply, reserve minting, or tier lookup, it usually lives in the hook-store interaction. If it affects project wiring, it usually lives in the deployer path or in how the hook is attached to rulesets.
47
47
 
48
- The shortest useful reading order is:
49
-
50
- 1. `JB721TiersHook`
51
- 2. `JB721TiersHookStore`
52
- 3. the relevant deployer
53
- 4. the resolver plugged into the hook, if the project uses one
54
-
55
48
  ## Read These Files First
56
49
 
57
50
  1. `src/JB721TiersHook.sol`
@@ -62,18 +55,18 @@ The shortest useful reading order is:
62
55
 
63
56
  ## Integration Traps
64
57
 
65
- - this hook participates in treasury-facing execution, not only metadata. Teams often underestimate the economic implications of tier splits, reserve behavior, and weight adjustments.
66
- - custom token URI resolvers should be treated as part of the project's trusted surface.
67
- - adding a 721 hook through a deployer is easy; carrying forward the right ruleset behavior over time is where mistakes happen.
68
- - projects should be explicit about whether the hook should affect pay, cash out, or only metadata-facing paths.
58
+ - this hook participates in treasury-facing execution, not only metadata
59
+ - custom token URI resolvers should be treated as part of the trusted surface
60
+ - adding a 721 hook through a deployer is easy; carrying the right ruleset behavior forward is where mistakes happen
61
+ - projects should be explicit about whether the hook affects pay, cash out, or only metadata-facing paths
69
62
 
70
63
  ## Where State Lives
71
64
 
72
- - tier definitions and accounting live primarily in `JB721TiersHookStore`
73
- - project-facing execution and permission checks live in `JB721TiersHook`
74
- - collection-specific presentation usually lives outside this repo in a resolver contract
65
+ - tier definitions and accounting: `JB721TiersHookStore`
66
+ - project-facing execution and permission checks: `JB721TiersHook`
67
+ - collection-specific presentation: usually outside this repo in a resolver contract
75
68
 
76
- That split is why UI bugs, economic bugs, and deployment bugs often land in different repos even though users describe them all as "721 hook issues."
69
+ That split is why UI bugs, economic bugs, and deployment bugs often land in different repos even when users describe them all as "721 hook issues."
77
70
 
78
71
  ## High-Signal Tests
79
72
 
@@ -104,7 +97,7 @@ Useful scripts:
104
97
 
105
98
  ## Deployment Notes
106
99
 
107
- Hooks are deployed as clones and typically registered in the address registry. The package is designed to compose with Omnichain, Croptop, Defifa, Banny, and other ecosystem packages that rely on tier-aware NFT issuance.
100
+ Hooks are deployed as clones and typically registered in the address registry. The package is designed to compose with Omnichain, Croptop, Defifa, Banny, and other packages that rely on tier-aware NFT issuance.
108
101
 
109
102
  ## Repository Layout
110
103
 
@@ -128,12 +121,12 @@ script/
128
121
  ## Risks And Notes
129
122
 
130
123
  - tier accounting is sensitive to reserve minting, split routing, and cross-currency normalization
131
- - tiny split allocations can round down to zero recipient amounts; integrations should not rely on dust-sized split routing
132
- - custom token URI resolvers are part of the security surface because they define how metadata is served
133
- - projects need to be deliberate about whether the hook participates in pay, cash-out, or both paths
124
+ - tiny split allocations can round down to zero recipient amounts
125
+ - custom token URI resolvers are part of the security surface
126
+ - projects need to be deliberate about whether the hook participates in pay, cash out, or both paths
134
127
  - tier mutations after launch are powerful and should be permissioned carefully
135
128
 
136
- When people say "the 721 hook," they often mean three different things: the hook contract, the store, and the metadata resolver plugged into it. Audits and integrations should separate those concerns.
129
+ When people say "the 721 hook," they often mean three different things: the hook contract, the store, and the metadata resolver plugged into it.
137
130
 
138
131
  ## For AI Agents
139
132