@bananapus/core-v6 0.0.34 → 0.0.35
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 +75 -349
- package/ARCHITECTURE.md +86 -44
- package/AUDIT_INSTRUCTIONS.md +29 -42
- package/README.md +22 -3
- package/RISKS.md +7 -0
- package/SKILLS.md +16 -4
- package/USER_JOURNEYS.md +130 -30
- package/foundry.toml +2 -0
- package/package.json +1 -1
- package/src/JBERC20.sol +0 -1
- package/src/structs/JBAccountingContext.sol +0 -1
- package/src/structs/JBAfterCashOutRecordedContext.sol +0 -1
- package/src/structs/JBAfterPayRecordedContext.sol +0 -1
- package/src/structs/JBBeforeCashOutRecordedContext.sol +0 -1
- package/src/structs/JBBeforePayRecordedContext.sol +0 -1
- package/src/structs/JBCashOutHookSpecification.sol +0 -1
- package/src/structs/JBCurrencyAmount.sol +0 -1
- package/src/structs/JBFee.sol +0 -1
- package/src/structs/JBFundAccessLimitGroup.sol +0 -1
- package/src/structs/JBPayHookSpecification.sol +0 -1
- package/src/structs/JBPermissionsData.sol +0 -1
- package/src/structs/JBRuleset.sol +0 -1
- package/src/structs/JBRulesetConfig.sol +0 -1
- package/src/structs/JBRulesetMetadata.sol +0 -1
- package/src/structs/JBRulesetWeightCache.sol +0 -1
- package/src/structs/JBRulesetWithMetadata.sol +0 -1
- package/src/structs/JBSingleAllowance.sol +0 -1
- package/src/structs/JBSplit.sol +0 -1
- package/src/structs/JBSplitGroup.sol +0 -1
- package/src/structs/JBSplitHookContext.sol +0 -1
- package/src/structs/JBTerminalConfig.sol +0 -1
- package/src/structs/JBTokenAmount.sol +0 -1
package/ARCHITECTURE.md
CHANGED
|
@@ -2,49 +2,73 @@
|
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
`nana-core-v6` is the protocol root. It owns project identity, permissions,
|
|
5
|
+
`nana-core-v6` is the protocol root for the V6 stack. It owns project identity, rulesets, permissions, treasury balances, token issuance, fee behavior, payout limits, and the hook interfaces every extension repo composes with.
|
|
6
6
|
|
|
7
|
-
If a change affects accounting, supply, fee
|
|
7
|
+
If a change affects accounting, supply, fee logic, terminal routing, or permission semantics, this repo is the source of truth.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## System Overview
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
- Extensions may adjust economics through hooks, but they should not invent competing ledgers.
|
|
13
|
-
- The core deliberately avoids app-specific behaviors like NFT composition, DEX routing strategy, or bridge-specific message transport.
|
|
11
|
+
`JBController`, `JBMultiTerminal`, and `JBTerminalStore` form the main execution and accounting pipeline. `JBDirectory`, `JBRulesets`, `JBProjects`, `JBTokens`, `JBPermissions`, `JBSplits`, and related contracts provide the routing, identity, and shared state that all downstream repos depend on. `JBTerminalStore` is terminal-scoped through `msg.sender`, so each terminal records its own balances and usage against the shared ruleset and price surfaces. Extensions may influence economics through hook interfaces, but they should not create competing ledgers.
|
|
14
12
|
|
|
15
|
-
##
|
|
13
|
+
## Core Invariants
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
- Preview functions must remain behaviorally aligned with state-changing functions.
|
|
16
|
+
- Data hooks run before settlement and may alter economics; pay and cash-out hooks run after settlement.
|
|
17
|
+
- Reserved tokens and other pending supply affect supply-sensitive math before distribution.
|
|
18
|
+
- Terminal balances, fee accounting, reclaim math, and surplus calculations must agree.
|
|
19
|
+
- Fee logic taxes fund egress, not every internal rebalance. Same-terminal project routing is a special case and must stay coherent with fee-free surplus tracking.
|
|
20
|
+
- Rulesets are time-ordered and approval-aware, and many deployer repos depend on predictable ID progression.
|
|
21
|
+
- Permission checks are protocol validity checks, not UI affordances.
|
|
22
|
+
|
|
23
|
+
## Modules
|
|
24
|
+
|
|
25
|
+
| Module | Responsibility | Notes |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| `JBMultiTerminal` | Payment, cash-out, payout, allowance, and fee entrypoint | Execution surface |
|
|
28
|
+
| `JBTerminalStore` | Shared accounting and preview math | Economic source of truth |
|
|
29
|
+
| `JBController` | Launch, queue rulesets, mint, burn, and split-group updates | Supply and configuration |
|
|
30
|
+
| `JBDirectory`, `JBRulesets` | Project routing and time-based ruleset lifecycle | Coordination layer |
|
|
31
|
+
| `JBProjects`, `JBTokens`, `JBERC20` | Identity and token surfaces | Ownership and tokenization |
|
|
32
|
+
| `JBPermissions`, `JBSplits`, `JBFundAccessLimits`, `JBPrices` | Shared authorization and configuration state | Cross-repo dependencies |
|
|
26
33
|
|
|
27
|
-
##
|
|
34
|
+
## Trust Boundaries
|
|
35
|
+
|
|
36
|
+
- This repo owns canonical balance and supply transitions.
|
|
37
|
+
- Hook repos may adjust inputs and post-settlement side effects, but they should not replace the ledger defined here.
|
|
38
|
+
- External price feeds, Permit2, and ERC-20 behavior are dependencies, but accounting truth stays in core.
|
|
39
|
+
|
|
40
|
+
## Critical Flows
|
|
28
41
|
|
|
29
42
|
### Payment
|
|
30
43
|
|
|
31
44
|
```text
|
|
32
45
|
terminal receives funds
|
|
33
|
-
-> terminal store reads the
|
|
34
|
-
->
|
|
46
|
+
-> terminal store reads the active ruleset and optional data hooks
|
|
47
|
+
-> before-pay data hook can modify weight and return pay-hook specs
|
|
48
|
+
-> terminal store records payment against the terminal-scoped ledger
|
|
35
49
|
-> controller mints beneficiary tokens and accrues reserved tokens
|
|
36
|
-
-> pay hooks
|
|
50
|
+
-> pay hooks run only after settlement
|
|
37
51
|
```
|
|
38
52
|
|
|
39
53
|
### Cash Out
|
|
40
54
|
|
|
41
55
|
```text
|
|
42
56
|
holder requests redemption
|
|
43
|
-
-> terminal store
|
|
44
|
-
->
|
|
57
|
+
-> terminal store reads current ruleset, balances, and supply inputs
|
|
58
|
+
-> before-cash-out data hook can modify reclaim inputs and hook specs
|
|
59
|
+
-> terminal store records the cash out against the terminal-scoped ledger
|
|
45
60
|
-> controller burns tokens
|
|
46
|
-
-> terminal pays
|
|
47
|
-
-> cash-out hooks
|
|
61
|
+
-> terminal pays reclaim value and routes protocol fees
|
|
62
|
+
-> cash-out hooks run only after settlement
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Launch And Queue Rulesets
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
owner, operator, or omnichain ruleset operator
|
|
69
|
+
-> controller launches or queues rulesets
|
|
70
|
+
-> launch path also sets the controller in the directory and configures terminals
|
|
71
|
+
-> rulesets become the source of truth for subsequent pay, cash-out, and admin constraints
|
|
48
72
|
```
|
|
49
73
|
|
|
50
74
|
### Payouts And Allowances
|
|
@@ -53,32 +77,50 @@ holder requests redemption
|
|
|
53
77
|
authorized caller
|
|
54
78
|
-> consumes payout limits or surplus allowances
|
|
55
79
|
-> funds move to splits, projects, hooks, or direct recipients
|
|
80
|
+
-> same-terminal project payouts stay inside terminal accounting, may accrue fee-free surplus, and must not accidentally mint against the payer's own balance
|
|
56
81
|
```
|
|
57
82
|
|
|
58
|
-
##
|
|
59
|
-
|
|
60
|
-
- Preview functions must remain behaviorally aligned with state-changing functions.
|
|
61
|
-
- Data hooks run before settlement and may alter the economics; pay and cash-out hooks run after settlement. That phase boundary is intentional.
|
|
62
|
-
- Reserved tokens and pending reserves affect supply-sensitive math even before distribution.
|
|
63
|
-
- Terminal balances, fee accounting, and surplus calculations must agree. Any drift here contaminates every product repo.
|
|
64
|
-
- Rulesets are time-ordered and approval-aware; deployment wrappers depend on predictable ID progression and activation semantics.
|
|
65
|
-
- Permission checks are not a UI concern. They are part of protocol state transition validity.
|
|
83
|
+
## Accounting Model
|
|
66
84
|
|
|
67
|
-
|
|
85
|
+
This repo owns the canonical ledger for balances, fees, supply-sensitive reclaim math, payout limits, allowances, reserved tokens, and preview calculations. Other repos may wrap or influence these values, but none should duplicate them.
|
|
68
86
|
|
|
69
|
-
-
|
|
70
|
-
- Preview paths deliberately mirror state-changing paths; keeping them aligned is a permanent maintenance burden.
|
|
71
|
-
- Fee-free surplus, held fees, and payout/allowance interactions create edge cases that are small in code size but large in blast radius.
|
|
87
|
+
`JBTerminalStore` keeps terminal balances, payout-limit usage, and surplus-allowance usage. That state is terminal-scoped, but not all reset boundaries are the same: payout-limit usage is tracked by ruleset cycle number, while surplus-allowance usage is tracked by `ruleset.id`. Auto-cycling a duration-based ruleset does not reset allowance usage; queueing a new ruleset does.
|
|
72
88
|
|
|
73
|
-
##
|
|
89
|
+
## Security Model
|
|
74
90
|
|
|
75
|
-
- `
|
|
76
|
-
-
|
|
91
|
+
- `JBMultiTerminal`, `JBTerminalStore`, and `JBController` should be reviewed as one pipeline.
|
|
92
|
+
- `JBTerminalStore` is shared logic but terminal-scoped state. Misunderstanding that split causes bad accounting assumptions.
|
|
93
|
+
- Small changes in fee or surplus logic can affect every downstream repo.
|
|
94
|
+
- Same-terminal project payouts, fee-free surplus capping, and migration cleanup are coupled. Changing one without the others creates fee bypasses or overcharges.
|
|
95
|
+
- `allowOwnerMinting` is not a universal mint kill switch. Terminals, the current data hook, and hook-authorized callers can still mint through the controller path.
|
|
96
|
+
- Hook ordering and preview-execution alignment are permanent maintenance obligations.
|
|
77
97
|
|
|
78
98
|
## Safe Change Guide
|
|
79
99
|
|
|
80
|
-
-
|
|
81
|
-
- Read downstream hook repos before changing hook
|
|
82
|
-
- Keep fee logic, balance logic, and surplus
|
|
83
|
-
-
|
|
84
|
-
- If
|
|
100
|
+
- Trace both preview and state-changing paths for any nontrivial change.
|
|
101
|
+
- Read downstream hook repos before changing hook metadata or interface expectations.
|
|
102
|
+
- Keep fee logic, balance logic, reclaim math, and surplus math synchronized.
|
|
103
|
+
- If you change payouts between projects on the same terminal, re-check self-pay revert behavior, fee-free surplus accumulation, and the post-pay cap against recorded balance.
|
|
104
|
+
- If you change ruleset rollover semantics, re-check which usage counters reset on cycle progression versus new ruleset IDs.
|
|
105
|
+
- If permissions change, update shared docs and downstream assumptions at the same time.
|
|
106
|
+
|
|
107
|
+
## Canonical Checks
|
|
108
|
+
|
|
109
|
+
- fee-free surplus and same-terminal payout behavior:
|
|
110
|
+
`test/TestFeeFreeCashOutBypass.sol`
|
|
111
|
+
- migration and terminal-accounting continuity:
|
|
112
|
+
`test/TestTerminalMigration.sol`
|
|
113
|
+
- ruleset ordering and transition behavior:
|
|
114
|
+
`test/RulesetTransitions.t.sol`
|
|
115
|
+
|
|
116
|
+
## Source Map
|
|
117
|
+
|
|
118
|
+
- `src/JBController.sol`
|
|
119
|
+
- `src/JBMultiTerminal.sol`
|
|
120
|
+
- `src/JBTerminalStore.sol`
|
|
121
|
+
- `src/JBDirectory.sol`
|
|
122
|
+
- `src/JBRulesets.sol`
|
|
123
|
+
- `src/JBPermissions.sol`
|
|
124
|
+
- `test/TestFeeFreeCashOutBypass.sol`
|
|
125
|
+
- `test/TestTerminalMigration.sol`
|
|
126
|
+
- `test/RulesetTransitions.t.sol`
|
package/AUDIT_INSTRUCTIONS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This is the core Juicebox V6 protocol. Most ecosystem invariants reduce to this repo eventually.
|
|
4
4
|
|
|
5
|
-
## Objective
|
|
5
|
+
## Audit Objective
|
|
6
6
|
|
|
7
7
|
Find issues that:
|
|
8
8
|
- break terminal solvency or internal accounting
|
|
@@ -45,7 +45,7 @@ That order mirrors how most high-severity issues emerge:
|
|
|
45
45
|
- tokens are minted or burned
|
|
46
46
|
- permissions and price context decide whether the move was legitimate
|
|
47
47
|
|
|
48
|
-
##
|
|
48
|
+
## Security Model
|
|
49
49
|
|
|
50
50
|
Core roles:
|
|
51
51
|
- `JBMultiTerminal`: holds funds and executes pay, payout, cash-out, allowance, and fee-processing flows
|
|
@@ -67,6 +67,23 @@ Core ordering to keep in mind:
|
|
|
67
67
|
- controller mint and burn operations happen around terminal flows, not as a separate settlement layer
|
|
68
68
|
- hooks can turn what looks like a simple pay or cash-out into a multi-contract composition
|
|
69
69
|
|
|
70
|
+
## Roles And Privileges
|
|
71
|
+
|
|
72
|
+
| Role | Powers | How constrained |
|
|
73
|
+
|------|--------|-----------------|
|
|
74
|
+
| Project owner and operators | Configure rulesets, limits, routing, and permissions | Must stay inside the explicit permission model |
|
|
75
|
+
| Terminal | Hold funds and execute settlement | Must remain solvent relative to internal accounting |
|
|
76
|
+
| Controller | Mint, burn, and manage project lifecycle | Must not bypass project-scoped authorization |
|
|
77
|
+
| Hooks and splits | Extend pay and cash-out behavior | Must not make previews and accounting irreconcilable |
|
|
78
|
+
|
|
79
|
+
## Integration Assumptions
|
|
80
|
+
|
|
81
|
+
| Dependency | Assumption | What breaks if wrong |
|
|
82
|
+
|------------|------------|----------------------|
|
|
83
|
+
| Price feeds | Currency conversions are fresh and coherent | Cross-currency flows misprice |
|
|
84
|
+
| Hook ecosystem | External hooks obey documented interfaces | Settlement becomes unsafe after control transfer |
|
|
85
|
+
| Directory and migration surfaces | Canonical routing changes are authentic | Funds or permissions shift to the wrong place |
|
|
86
|
+
|
|
70
87
|
## Critical Invariants
|
|
71
88
|
|
|
72
89
|
1. Terminal solvency
|
|
@@ -93,22 +110,7 @@ When fee payment is deferred, later replenishment or migration behavior must not
|
|
|
93
110
|
8. Preview coherence
|
|
94
111
|
`previewPayFor` and `previewCashOutFrom` should not become meaningfully inconsistent with execution in ways downstream repos can exploit.
|
|
95
112
|
|
|
96
|
-
##
|
|
97
|
-
|
|
98
|
-
Prioritize:
|
|
99
|
-
- hook-driven reentrancy or state-ordering issues
|
|
100
|
-
- price-feed failure and cross-currency conversions
|
|
101
|
-
- fee-processing failure paths
|
|
102
|
-
- migration and feeless-address edge cases
|
|
103
|
-
- ruleset-boundary timing attacks
|
|
104
|
-
- wildcard or root permission escalation
|
|
105
|
-
|
|
106
|
-
The highest-yield attacker mindsets here are:
|
|
107
|
-
- a malicious hook that receives control after balances move but before the full user flow is conceptually finished
|
|
108
|
-
- a project owner exploiting migration, limits, or feeless settings rather than breaking access control directly
|
|
109
|
-
- a cross-currency user extracting value from rounding or stale price conversions
|
|
110
|
-
|
|
111
|
-
## Hotspots
|
|
113
|
+
## Attack Surfaces
|
|
112
114
|
|
|
113
115
|
- `pay`, `cashOutTokensOf`, `sendPayoutsOf`, and `useAllowanceOf`
|
|
114
116
|
- `preview*` paths when downstream repos treat them as execution truth
|
|
@@ -117,34 +119,19 @@ The highest-yield attacker mindsets here are:
|
|
|
117
119
|
- controller migration and terminal migration
|
|
118
120
|
- `setPermissionsFor` and any wildcard semantics
|
|
119
121
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
5. permission grants involving operators, wildcard project IDs, or later controller changes.
|
|
122
|
+
Replay these sequences:
|
|
123
|
+
1. `pay` with a data hook that alters weight or hook specs and then reenters through a pay hook
|
|
124
|
+
2. `cashOutTokensOf` when cross-terminal surplus and `useTotalSurplusForCashOuts` matter
|
|
125
|
+
3. `sendPayoutsOf` into splits that route to another project, hook, or failing beneficiary
|
|
126
|
+
4. held-fee accumulation followed by migration or balance depletion
|
|
127
|
+
5. permission grants involving operators, wildcard project IDs, or later controller changes
|
|
127
128
|
|
|
128
|
-
##
|
|
129
|
+
## Accepted Risks Or Behaviors
|
|
129
130
|
|
|
130
|
-
|
|
131
|
-
- the store records more value than the terminal can safely honor
|
|
132
|
-
- a limit is consumed too late, after externally controlled code can already profit
|
|
133
|
-
- a migration or held-fee edge path changes who ultimately bears an obligation
|
|
134
|
-
- permissions that look project-scoped become ecosystem-relevant through wildcard or routing semantics
|
|
131
|
+
- Hooks are intentionally powerful extension points; safety depends on clear sequencing and bounded trust, not on avoiding composition.
|
|
135
132
|
|
|
136
|
-
##
|
|
133
|
+
## Verification
|
|
137
134
|
|
|
138
|
-
Standard workflow:
|
|
139
135
|
- `npm install`
|
|
140
136
|
- `forge build`
|
|
141
137
|
- `forge test`
|
|
142
|
-
|
|
143
|
-
The current test suite already targets:
|
|
144
|
-
- flash-loan and economic exploits
|
|
145
|
-
- permissions invariants
|
|
146
|
-
- ruleset transitions
|
|
147
|
-
- fee and migration edge cases
|
|
148
|
-
- multi-token and cross-currency surplus behavior
|
|
149
|
-
|
|
150
|
-
The highest-value findings in this repo are the ones that make downstream hooks or deployers unsafe even when those repos are otherwise correct.
|
package/README.md
CHANGED
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
`@bananapus/core-v6` is the core protocol package for Juicebox on EVM chains. It defines projects, rulesets, terminals, permissions, token issuance, cash outs, splits, price feeds, and the accounting surfaces that the rest of the V6 ecosystem builds on.
|
|
4
4
|
|
|
5
5
|
Docs: <https://docs.juicebox.money>
|
|
6
|
-
Architecture: [ARCHITECTURE.md](./ARCHITECTURE.md)
|
|
6
|
+
Architecture: [ARCHITECTURE.md](./ARCHITECTURE.md)
|
|
7
|
+
User journeys: [USER_JOURNEYS.md](./USER_JOURNEYS.md)
|
|
8
|
+
Skills: [SKILLS.md](./SKILLS.md)
|
|
9
|
+
Risks: [RISKS.md](./RISKS.md)
|
|
10
|
+
Administration: [ADMINISTRATION.md](./ADMINISTRATION.md)
|
|
11
|
+
Audit instructions: [AUDIT_INSTRUCTIONS.md](./AUDIT_INSTRUCTIONS.md)
|
|
7
12
|
|
|
8
13
|
## Overview
|
|
9
14
|
|
|
@@ -18,7 +23,7 @@ The core package provides:
|
|
|
18
23
|
- operator permissions through `JBPermissions`
|
|
19
24
|
- on-chain price-feed routing through `JBPrices`
|
|
20
25
|
|
|
21
|
-
Use this repo when you need the canonical protocol
|
|
26
|
+
Use this repo when you need the canonical protocol accounting and execution surfaces. Do not duplicate its logic in downstream packages unless the repo is explicitly intended to wrap or extend the core surface.
|
|
22
27
|
|
|
23
28
|
If you only read one repo before auditing the rest of the ecosystem, read this one.
|
|
24
29
|
|
|
@@ -31,7 +36,7 @@ The core protocol is easiest to reason about in four layers:
|
|
|
31
36
|
3. accounting: `JBTerminalStore`
|
|
32
37
|
4. permissions and external context: `JBPermissions`, `JBPrices`, feeless-address and deadline helpers
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
Many integrations touch only layer 2, while many economically important bugs are easiest to understand from layer 3.
|
|
35
40
|
|
|
36
41
|
The shortest path through the repo is:
|
|
37
42
|
|
|
@@ -78,6 +83,14 @@ The shortest path through the repo is:
|
|
|
78
83
|
|
|
79
84
|
When in doubt, read the state-owning contract before the contract that merely forwards into it.
|
|
80
85
|
|
|
86
|
+
## High-Signal Tests
|
|
87
|
+
|
|
88
|
+
1. `test/TestPayBurnRedeemFlow.sol`
|
|
89
|
+
2. `test/TestTerminalPreviewParity.sol`
|
|
90
|
+
3. `test/invariants/TerminalStoreInvariant.t.sol`
|
|
91
|
+
4. `test/invariants/RulesetsInvariant.t.sol`
|
|
92
|
+
5. `test/audit/CrossTerminalSurplusSpoof.t.sol`
|
|
93
|
+
|
|
81
94
|
## Install
|
|
82
95
|
|
|
83
96
|
```bash
|
|
@@ -125,3 +138,9 @@ script/
|
|
|
125
138
|
- fee, surplus, and reclaim logic are economically sensitive and remain high-priority audit surfaces
|
|
126
139
|
|
|
127
140
|
The fastest way to misunderstand V6 is to treat the core contracts like a simple crowdfunding terminal. They are closer to a configurable accounting and settlement substrate.
|
|
141
|
+
|
|
142
|
+
## For AI Agents
|
|
143
|
+
|
|
144
|
+
- Start with `JBController`, `JBMultiTerminal`, and `JBTerminalStore`; do not summarize core behavior from helper libraries alone.
|
|
145
|
+
- Distinguish controller configuration from terminal execution and from store accounting.
|
|
146
|
+
- If a behavior involves hooks, inspect the hook repo too before treating the preview or execution path as canonical.
|
package/RISKS.md
CHANGED
|
@@ -144,6 +144,7 @@ No `ReentrancyGuard` is used. The system relies on state ordering and the `Inade
|
|
|
144
144
|
- **No state modification risk.** Preview functions cannot change balances, mint/burn tokens, or consume limits. They are safe to call from any context.
|
|
145
145
|
- **Preview-execution divergence.** Preview functions and their corresponding real operations share computation logic but execute in different contexts. `previewPayFor` calls `STORE.previewPayFrom` which invokes the data hook's `beforePayRecordedWith` via `staticcall`. The real `pay` path invokes the same hook but state changes between preview and execution (other payments, cash outs, ruleset transitions) can change the data hook's response. Callers should treat preview results as estimates, not guarantees — especially for projects with stateful data hooks.
|
|
146
146
|
- **Gas griefing via data hooks in previews.** Since `previewPayFor` and `previewCashOutFrom` invoke data hooks, a gas-expensive data hook can make preview calls prohibitively expensive. This affects frontends and indexers that rely on preview functions for quote display. Unlike the real operations (which have economic incentive to complete), preview calls have no built-in gas limit on the data hook invocation.
|
|
147
|
+
- **Not all read-only cash-out estimates are hook-aware.** `JBTerminalStore.currentReclaimableSurplusOf` and `currentTotalReclaimableSurplusOf` intentionally do not run the data hook. They use the current ruleset's plain `cashOutTaxRate` and the controller-reported total supply, so they cannot reflect hook-provided overrides such as omnichain or custom `effectiveTotalSupply` logic. Integrators should use `previewCashOutFrom` or simulate `recordCashOutFor` when they need an estimate that matches hook-adjusted execution more closely.
|
|
147
148
|
|
|
148
149
|
## 7. Integration Risks
|
|
149
150
|
|
|
@@ -174,6 +175,12 @@ No `ReentrancyGuard` is used. The system relies on state ordering and the `Inade
|
|
|
174
175
|
|
|
175
176
|
- `JBTerminalStore.recordAddedBalanceFor` has **no access control**. Any address can call it. The balance is keyed by `msg.sender` (the terminal address), so only a terminal can inflate its own recorded balance. This is safe as long as all terminals correctly track their actual holdings. A buggy or malicious terminal implementation could call `recordAddedBalanceFor` without actually receiving tokens, inflating the recorded balance above actual holdings.
|
|
176
177
|
|
|
178
|
+
### Split and Owner-Payout Failure Semantics
|
|
179
|
+
|
|
180
|
+
- **Failed split payouts still consume payout limit.** Core decrements balance and increments used payout limit before downstream split transfers are attempted. If a split payout later fails, the amount is returned to project balance, but the payout limit consumption is not rewound. This is intentional fail-open accounting: one bad split should not revert the whole payout fanout, but operators should not assume "returned to balance" also means "payout limit restored".
|
|
181
|
+
- **Failed owner transfers also consume payout limit.** The leftover owner payout path uses the same pattern as split payouts: if the owner transfer fails, funds return to project balance, but the payout limit remains consumed for that cycle.
|
|
182
|
+
- **Split hook reverts after token transfer strand tokens at the hook.** In reserved-token distributions, the controller transfers tokens to the split hook before calling `processSplitWith`. If that hook call then reverts, core emits `SplitHookReverted` but does not claw the tokens back. Integrators should treat split hooks as token-custody recipients, not pure callbacks.
|
|
183
|
+
|
|
177
184
|
## 8. Accepted Behaviors
|
|
178
185
|
|
|
179
186
|
### 8.1 Cross-terminal surplus is an explicit trust boundary
|
package/SKILLS.md
CHANGED
|
@@ -3,19 +3,23 @@
|
|
|
3
3
|
## Use This File For
|
|
4
4
|
|
|
5
5
|
- Use this file when the task touches protocol core behavior: payments, cash-outs, terminals, controller actions, rulesets, splits, tokens, permissions, or price feeds.
|
|
6
|
-
- Start here if you know the issue is in core, then
|
|
6
|
+
- Start here if you know the issue is in core, then identify the single state transition being changed before reading broadly. In this repo, most bugs reduce to controller lifecycle, terminal execution, store accounting, or ruleset state.
|
|
7
7
|
|
|
8
8
|
## Read This Next
|
|
9
9
|
|
|
10
10
|
| If you need... | Open this next |
|
|
11
11
|
|---|---|
|
|
12
|
-
| Repo overview and protocol framing | [`README.md`](./README.md) |
|
|
12
|
+
| Repo overview and protocol framing | [`README.md`](./README.md), [`ARCHITECTURE.md`](./ARCHITECTURE.md) |
|
|
13
13
|
| Controller and project lifecycle behavior | [`src/JBController.sol`](./src/JBController.sol), [`src/JBProjects.sol`](./src/JBProjects.sol), [`src/JBTokens.sol`](./src/JBTokens.sol) |
|
|
14
14
|
| Payment, cash-out, surplus, and fee accounting | [`src/JBMultiTerminal.sol`](./src/JBMultiTerminal.sol), [`src/JBTerminalStore.sol`](./src/JBTerminalStore.sol), [`src/JBFundAccessLimits.sol`](./src/JBFundAccessLimits.sol) |
|
|
15
15
|
| Rulesets, permissions, directory, and prices | [`src/JBRulesets.sol`](./src/JBRulesets.sol), [`src/JBPermissions.sol`](./src/JBPermissions.sol), [`src/JBDirectory.sol`](./src/JBDirectory.sol), [`src/JBPrices.sol`](./src/JBPrices.sol) |
|
|
16
16
|
| Shared math, metadata parsing, and constants | [`src/libraries/`](./src/libraries/), [`src/structs/`](./src/structs/), [`src/enums/`](./src/enums/) |
|
|
17
17
|
| Periphery helpers and deployment | [`src/periphery/`](./src/periphery/), [`script/Deploy.s.sol`](./script/Deploy.s.sol), [`script/DeployPeriphery.s.sol`](./script/DeployPeriphery.s.sol) |
|
|
18
|
-
|
|
|
18
|
+
| Payment and cash-out entrypoint surface | [`references/entrypoints.md`](./references/entrypoints.md) |
|
|
19
|
+
| Packed metadata, gotchas, errors, and hook return shapes | [`references/types-errors-events.md`](./references/types-errors-events.md) |
|
|
20
|
+
| Cash-out, payment, and terminal accounting proofs | [`test/TestPayBurnRedeemFlow.sol`](./test/TestPayBurnRedeemFlow.sol), [`test/TestCashOut.sol`](./test/TestCashOut.sol), [`test/TestMultiTerminalSurplus.sol`](./test/TestMultiTerminalSurplus.sol), [`test/TestTerminalPreviewParity.sol`](./test/TestTerminalPreviewParity.sol) |
|
|
21
|
+
| Permissions, rulesets, and invariants | [`test/TestPermissions.sol`](./test/TestPermissions.sol), [`test/PermissionEscalation.t.sol`](./test/PermissionEscalation.t.sol), [`test/TestRulesetQueueing.sol`](./test/TestRulesetQueueing.sol), [`test/ComprehensiveInvariant.t.sol`](./test/ComprehensiveInvariant.t.sol), [`test/PermissionsInvariant.t.sol`](./test/PermissionsInvariant.t.sol) |
|
|
22
|
+
| Economic, exploit, and weird-token coverage | [`test/EconomicSimulation.t.sol`](./test/EconomicSimulation.t.sol), [`test/CoreExploitTests.t.sol`](./test/CoreExploitTests.t.sol), [`test/FlashLoanAttacks.t.sol`](./test/FlashLoanAttacks.t.sol), [`test/WeirdTokenTests.t.sol`](./test/WeirdTokenTests.t.sol), [`test/AuditFixes.t.sol`](./test/AuditFixes.t.sol) |
|
|
19
23
|
|
|
20
24
|
## Repo Map
|
|
21
25
|
|
|
@@ -40,5 +44,13 @@ The core Juicebox V6 protocol on EVM: a modular system for launching treasury-ba
|
|
|
40
44
|
## Working Rules
|
|
41
45
|
|
|
42
46
|
- Open source before relying on any summary here. This skill is a router, not the ground truth.
|
|
43
|
-
- For runtime bugs, start from the terminal/controller/store contract that owns the state transition.
|
|
47
|
+
- For runtime bugs, start from the terminal/controller/store contract that owns the state transition. Most user-facing behavior is computed there, not in helpers or interfaces.
|
|
48
|
+
- `JBMultiTerminal` and `JBTerminalStore` are a pair. If you change one without re-deriving the other’s assumptions, expect accounting drift.
|
|
49
|
+
- Payment and cash-out previews are not optional convenience APIs. `previewPayFrom` and `previewCashOutFrom` are part of the protocol surface and need to stay aligned with execution semantics.
|
|
50
|
+
- Payout limits reset by ruleset cycle number, but surplus allowances are keyed by `ruleset.id`, not cycle number. Do not assume they reset together.
|
|
51
|
+
- Fee handling is nuanced. Re-check held fees, fee-free surplus tracking, and feeless-address behavior before changing payout or cash-out logic.
|
|
52
|
+
- Fee-free surplus is a bounded anti-bypass mechanism, not a generic exemption bucket. Re-check lifecycle capping and migration/reset behavior before changing cash-out or payout flows.
|
|
44
53
|
- For config or weird value-shape issues, open `references/types-errors-events.md` before changing structs or metadata packing.
|
|
54
|
+
- Terminal previews, accounting, and fee behavior are tightly coupled. If one changes, assume at least one of the others needs verification.
|
|
55
|
+
- Long-lived rulesets have a real cache boundary. If the issue involves extreme cycle counts, inspect `JBRulesets.updateRulesetWeightCache(...)` and the surrounding tests before touching weight math.
|
|
56
|
+
- When a bug smells cross-repo, prove it is not really coming from a hook, router, or downstream deployer before patching core.
|