@bananapus/distributor-v6 0.0.7 → 0.0.9

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/ARCHITECTURE.md DELETED
@@ -1,89 +0,0 @@
1
- # Architecture
2
-
3
- ## Purpose
4
-
5
- `nana-distributor-v6` provides round-based vesting and claiming for already-owned assets. It supports both `IVotes`-based ERC-20 distributions and 721-based distributions without becoming a treasury or accounting layer.
6
-
7
- ## System Overview
8
-
9
- `JBDistributor` is the shared vesting engine. `JBTokenDistributor` changes stake measurement to checkpointed voting power. `JB721Distributor` changes stake measurement to checkpointed voting power from the hook's `CHECKPOINTS()` module, ensuring only NFTs held at round start are eligible.
10
-
11
- Both variants can be used as `IJBSplitHook` receivers.
12
-
13
- ## Core Invariants
14
-
15
- - snapshot timing must stay coherent
16
- - tracked funded balance must cover current vesting obligations
17
- - claim authority must match the distributor type
18
- - 721 forfeiture handling must not over-allocate or burn value accidentally
19
- - token and 721 variants must preserve the same core vesting math
20
-
21
- ## Modules
22
-
23
- | Module | Responsibility | Notes |
24
- | --- | --- | --- |
25
- | `JBDistributor` | Shared rounds, vesting, snapshots, and claims | Economic core |
26
- | `JBTokenDistributor` | ERC-20 distribution using `IVotes` checkpoints | Token stake source |
27
- | `JB721Distributor` | NFT distribution using checkpointed voting power | 721 stake source |
28
-
29
- ## Trust Boundaries
30
-
31
- - split-hook caller authentication depends on `JBDirectory`
32
- - `JBTokenDistributor` trusts `IVotes` checkpoint history
33
- - `JB721Distributor` trusts the 721 hook's `CHECKPOINTS()` module for historical voting power and the store for tier metadata
34
- - upstream entitlement logic still lives outside this repo
35
-
36
- ## Critical Flows
37
-
38
- ### Begin Vesting
39
-
40
- ```text
41
- funded distributor
42
- -> begin a round
43
- -> snapshot stake and tracked balance for that round
44
- -> record vesting entries for the requested token IDs
45
- ```
46
-
47
- ### Collect
48
-
49
- ```text
50
- claimant
51
- -> prove authority for the token ID or encoded claimant slot
52
- -> compute unlocked share
53
- -> transfer the vested amount
54
- ```
55
-
56
- ## Accounting Model
57
-
58
- This repo owns vesting-round accounting. It does not own upstream treasury accounting or entitlement creation.
59
-
60
- The main variables are snapshot balance, total vesting amount, and the stake source used to split each round.
61
-
62
- ## Security Model
63
-
64
- - wrong snapshots can misallocate a whole round
65
- - bad constructor parameters can brick a distributor instance
66
- - split-funding caller assumptions matter because `processSplitWith` distinguishes pull and pre-sent flows
67
- - 721 and token variants intentionally differ in authority and forfeiture behavior
68
-
69
- ## Safe Change Guide
70
-
71
- - review snapshot timing and vesting math together
72
- - if claim authority changes, re-check both distributor variants separately
73
- - if funding semantics change, test terminal-style and controller-style flows explicitly
74
-
75
- ## Canonical Checks
76
-
77
- - token distribution behavior:
78
- `test/JBTokenDistributor.t.sol`
79
- - 721 distribution behavior:
80
- `test/JB721Distributor.t.sol`
81
- - 721 invariants:
82
- `test/invariant/JB721DistributorInvariant.t.sol`
83
-
84
- ## Source Map
85
-
86
- - `src/JBDistributor.sol`
87
- - `src/JBTokenDistributor.sol`
88
- - `src/JB721Distributor.sol`
89
- - `src/interfaces/IJBDistributor.sol`
@@ -1,52 +0,0 @@
1
- # Audit Instructions
2
-
3
- This repo is a shared vesting engine plus two concrete distributor variants. Audit it as payout logic whose main risks are snapshot timing, stake measurement, and funding assumptions.
4
-
5
- ## Audit Objective
6
-
7
- Find issues that:
8
-
9
- - misallocate rewards because the snapshot or stake source is wrong
10
- - break vesting or claiming because parameters are invalid
11
- - let caller or claim authority drift from the intended model
12
- - make split-funding assumptions unsafe
13
-
14
- ## Scope
15
-
16
- In scope:
17
-
18
- - `src/JBDistributor.sol`
19
- - `src/JBTokenDistributor.sol`
20
- - `src/JB721Distributor.sol`
21
- - interfaces and structs under `src/`
22
-
23
- ## Start Here
24
-
25
- 1. `src/JBDistributor.sol`
26
- 2. `src/JBTokenDistributor.sol`
27
- 3. `src/JB721Distributor.sol`
28
-
29
- ## Security Model
30
-
31
- The shared distributor:
32
-
33
- - snapshots balance and stake for a round
34
- - tracks vesting obligations
35
- - lets authorized claimants collect what has unlocked
36
-
37
- The concrete variants only change how stake and claimant authority are measured.
38
-
39
- ## Critical Invariants
40
-
41
- 1. Snapshot and stake source stay coherent.
42
- A round should not allocate more or less than the chosen stake source supports.
43
- 2. Tracked balance covers vesting obligations.
44
- Current and future vesting must reconcile with funded inventory.
45
- 3. Claim authority matches distributor type.
46
- The token and 721 variants must enforce their distinct authority models correctly.
47
-
48
- ## Verification
49
-
50
- - `npm install`
51
- - `forge build`
52
- - `forge test`
package/RISKS.md DELETED
@@ -1,78 +0,0 @@
1
- # Distributor Risk Register
2
-
3
- This file covers the shared vesting engine in `JBDistributor` and the two concrete payout-split receivers, `JB721Distributor` and `JBTokenDistributor`.
4
-
5
- ## How To Use This File
6
-
7
- - Read `Priority risks` first. Those are the failure modes with the highest payout-integrity impact.
8
- - Treat the shared `JBDistributor` logic as the economic core.
9
- - Use `Invariants to verify` as the minimum test envelope before routing live splits through a distributor.
10
-
11
- ## Priority Risks
12
-
13
- | Priority | Risk | Why it matters | Primary controls |
14
- |----------|------|----------------|------------------|
15
- | P0 | Wrong stake snapshot or stale stake source | A bad stake reading misallocates rewards for an entire round. | Snapshot review, invariants, and careful integration with the chosen hook or `IVotes` token. |
16
- | P1 | Zero-stake or bad-parameter deployment | Bad constructor inputs or zero total stake can make core flows revert. | Deployment-time validation and operator runbooks. |
17
- | P1 | Split funding trust mismatch | `processSplitWith` distinguishes terminal-style pull flows from controller-style pre-sent flows. | Restrict callers and test both paths. |
18
-
19
- ## 1. Trust Assumptions
20
-
21
- - **`JBDirectory` is trusted.**
22
- - **Stake sources are trusted.**
23
- - **Deployment parameters must be sane.**
24
-
25
- ## 2. Economic Risks
26
-
27
- - **Round snapshot timing has a zero-balance edge case.**
28
- - **Unclaimed value stays in the pool.**
29
- - **Partial-round claims are linear, not cliff-based.**
30
- - **Forfeited 721 rewards are recycled, not burned.**
31
- - **Undelegated `IVotes` balances can dilute participation.**
32
-
33
- ## 3. Access Control And Caller Risks
34
-
35
- - **Vesting is permissionless.**
36
- - **Claim authority differs by distributor type.**
37
- - **721 claim batches are brittle to invalid token IDs.**
38
- - **Forfeiture release is effectively 721-only.**
39
- - **Split-hook entry is tightly gated.**
40
-
41
- ## 4. DoS And Liveness Risks
42
-
43
- - **Zero stake reverts vesting.**
44
- - **Zero distributable balance reverts vesting.** The `beginVesting` call reverts with `JBDistributor_NothingToDistribute` if the distributable balance for a token is zero.
45
- - **Bad constructor parameters can brick the instance.**
46
- - **Resolver or token callback failures can block collection.**
47
-
48
- ## 5. Integration Risks
49
-
50
- - **Controller-vs-terminal split funding heuristic matters.**
51
- - **Fee-on-transfer handling uses balance-delta accounting.** Both terminal-pull and controller-pre-send paths measure `balanceAfter - balanceBefore` to credit the actual received amount.
52
- - **721 stake weights depend on checkpointed voting power at round start.** The `CHECKPOINTS()` module must be deployed and delegates must be set before the round snapshot block, or stakers receive zero weight.
53
- - **721 vesting and claiming treat burned tokens differently.**
54
- - **Checkpoint availability matters for both `IVotes` token distributors and 721 distributors.**
55
- - **Token distributor rejects token IDs with non-zero upper bits** (above 160) to prevent aliasing to the same staker address.
56
-
57
- ## 6. Invariants To Verify
58
-
59
- - `totalVestingAmountOf <= _balanceOf`
60
- - collections plus remaining vesting plus future distributable balance never exceed tracked funded balance
61
- - non-zero round snapshots stay stable within a round
62
- - `latestVestedIndexOf` advances contiguously
63
- - burned NFTs are excluded from 721 stake (via zero checkpointed votes) and only recycled through the explicit forfeiture path
64
- - only the encoded address can collect from the token distributor
65
-
66
- ## 7. Accepted Behaviors
67
-
68
- ### 7.1 Anyone can trigger a round snapshot
69
-
70
- This improves liveness, but it also means operators do not fully control the exact block when a round is crystallized.
71
-
72
- ### 7.2 Rewards can remain undistributed when stake is missing
73
-
74
- If some potential participants have zero effective stake for a round, the corresponding value stays in the distributor for future rounds.
75
-
76
- ### 7.3 721 and `IVotes` variants intentionally differ
77
-
78
- They share the vesting engine but not the same ownership model.
package/SKILLS.md DELETED
@@ -1,36 +0,0 @@
1
- # Juicebox Distributor
2
-
3
- ## Use This File For
4
-
5
- - Use this file when the task involves round-based vesting, split-hook distribution, or snapshot-based payout allocation.
6
- - Start here, then decide whether the issue is in shared vesting logic, `IVotes`-based stake measurement, or 721-based stake measurement.
7
-
8
- ## Read This Next
9
-
10
- | If you need... | Open this next |
11
- |---|---|
12
- | Repo overview and architecture | [`README.md`](./README.md), [`ARCHITECTURE.md`](./ARCHITECTURE.md) |
13
- | Shared vesting engine | [`src/JBDistributor.sol`](./src/JBDistributor.sol), [`src/interfaces/IJBDistributor.sol`](./src/interfaces/IJBDistributor.sol) |
14
- | Token distributor behavior | [`src/JBTokenDistributor.sol`](./src/JBTokenDistributor.sol) |
15
- | 721 distributor behavior | [`src/JB721Distributor.sol`](./src/JB721Distributor.sol) |
16
- | Types and structs | [`src/structs/`](./src/structs/) |
17
- | Main tests | [`test/JBTokenDistributor.t.sol`](./test/JBTokenDistributor.t.sol), [`test/JB721Distributor.t.sol`](./test/JB721Distributor.t.sol), [`test/invariant/JB721DistributorInvariant.t.sol`](./test/invariant/JB721DistributorInvariant.t.sol) |
18
-
19
- ## Repo Map
20
-
21
- | Area | Where to look |
22
- |---|---|
23
- | Main contracts | [`src/`](./src/) |
24
- | Structs and interfaces | [`src/structs/`](./src/structs/), [`src/interfaces/`](./src/interfaces/) |
25
- | Tests | [`test/`](./test/) |
26
-
27
- ## Purpose
28
-
29
- Shared vesting and distribution engine for ERC-20 and 721-based payout flows.
30
-
31
- ## Working Rules
32
-
33
- - Start in [`src/JBDistributor.sol`](./src/JBDistributor.sol) for shared round logic.
34
- - Treat snapshot timing as part of correctness.
35
- - `JBTokenDistributor` and `JB721Distributor` share a vesting engine but not the same ownership model.
36
- - Verify the distributor actually holds the asset it is meant to vest before reasoning about payout correctness.
package/USER_JOURNEYS.md DELETED
@@ -1,122 +0,0 @@
1
- # User Journeys
2
-
3
- ## Repo Purpose
4
-
5
- This repo distributes already-owned assets over time. It snapshots stake, starts vesting rounds, and lets eligible recipients collect what has unlocked.
6
-
7
- ## Primary Actors
8
-
9
- - teams funding a distributor from a split or post-mint allocation
10
- - token holders or NFT holders collecting vested rewards
11
- - operators configuring round timing and deployment shape
12
- - auditors reviewing snapshot timing and stake-accounting correctness
13
-
14
- ## Key Surfaces
15
-
16
- - `JBDistributor`: shared round and vesting engine
17
- - `JBTokenDistributor`: ERC-20 distributor using `IVotes`
18
- - `JB721Distributor`: NFT distributor using tier voting units
19
-
20
- ## Journey 1: Fund A Distributor
21
-
22
- **Actor:** project or payout flow.
23
-
24
- **Intent:** move owned assets into a distributor that will vest them over time.
25
-
26
- **Preconditions**
27
- - the correct asset and distributor type are chosen
28
- - the distributor actually receives the inventory it is expected to vest
29
-
30
- **Main Flow**
31
- 1. Fund the distributor directly or through a payout split.
32
- 2. Confirm the tracked balance matches what the distributor received.
33
- 3. Use the distributor as the vesting surface, not as the source of entitlement logic.
34
-
35
- **Failure Modes**
36
- - wrong asset funded
37
- - underfunded distributor
38
- - caller assumes funding alone starts vesting
39
-
40
- **Postconditions**
41
- - the distributor holds the asset inventory for future rounds
42
-
43
- ## Journey 2: Start A Vesting Round
44
-
45
- **Actor:** any caller.
46
-
47
- **Intent:** snapshot the current round and begin vesting.
48
-
49
- **Preconditions**
50
- - the round timing and parameters are valid
51
- - the stake source is usable and non-zero
52
-
53
- **Main Flow**
54
- 1. Call `beginVesting`.
55
- 2. The distributor snapshots the relevant balance and stake source.
56
- 3. Vesting entries become claimable over the configured schedule.
57
-
58
- **Snapshot timing:** The snapshot for each round is taken when the previous round first sees activity (`poke`, `beginVesting`, or `collectVestedRewards`). To be included in round N's distribution, make sure your tokens are held and delegated before anyone interacts with round N-1. In practice, keep your delegation current — if it is set before the previous round's activity begins, your voting power will be counted for the next round.
59
-
60
- **Failure Modes**
61
- - zero total stake
62
- - bad deployment parameters such as zero round duration or zero vesting rounds
63
- - stake snapshot is stale or surprising to operators
64
-
65
- **Postconditions**
66
- - a new vesting round exists with fixed snapshot assumptions
67
-
68
- ## Journey 3: Collect Vested Rewards
69
-
70
- **Actor:** eligible recipient.
71
-
72
- **Intent:** collect the share that has unlocked for a round.
73
-
74
- **Preconditions**
75
- - the recipient is authorized under the distributor type
76
- - some share has already vested
77
-
78
- **Main Flow**
79
- 1. Call the relevant claim function.
80
- 2. The distributor checks authority and unlocked amount.
81
- 3. The vested share transfers to the claimant.
82
-
83
- **Failure Modes**
84
- - invalid claimant
85
- - claim batch includes invalid 721 token IDs
86
- - reward token transfer fails
87
-
88
- **Postconditions**
89
- - vested rewards move to the claimant
90
-
91
- ## Journey 4: Recycle Forfeited 721 Rewards
92
-
93
- **Actor:** caller using the 721 distributor path.
94
-
95
- **Intent:** release rewards tied to burned NFTs back into the future distribution pool.
96
-
97
- **Preconditions**
98
- - the distributor type is 721-based
99
- - the relevant NFTs are burned or otherwise forfeited under the configured rules
100
-
101
- **Main Flow**
102
- 1. Call the forfeiture-release path.
103
- 2. The distributor reduces current vesting obligations for those forfeited claims.
104
- 3. The value remains in the distributor for future rounds instead of being destroyed.
105
-
106
- **Failure Modes**
107
- - caller expects the same behavior from the token distributor
108
- - off-chain systems treat forfeited value as burned instead of recycled
109
-
110
- **Postconditions**
111
- - forfeited 721 rewards return to the future distributable pool
112
-
113
- ## Trust Boundaries
114
-
115
- - this repo trusts `JBDirectory` for authenticated split-hook caller checks
116
- - `JBTokenDistributor` trusts `IVotes` checkpoints
117
- - `JB721Distributor` trusts the 721 hook's `CHECKPOINTS()` module for historical voting power and the store for tier metadata
118
-
119
- ## Hand-Offs
120
-
121
- - Use the upstream repo that funded the distributor when the question is about why an allocation exists.
122
- - Use [nana-721-hook-v6](../nana-721-hook-v6/USER_JOURNEYS.md) when the stake source is a tiered 721 hook.
@@ -1,10 +0,0 @@
1
- {
2
- "detectors_to_exclude": "timestamp,uninitialized-local,naming-convention,solc-version,shadowing-local",
3
- "exclude_informational": true,
4
- "exclude_low": false,
5
- "exclude_medium": false,
6
- "exclude_high": false,
7
- "disable_color": false,
8
- "filter_paths": "(mocks/|test/|node_modules/|lib/)",
9
- "legacy_ast": false
10
- }