@bananapus/core-v6 0.0.81 → 0.0.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,7 +15,7 @@ In-repo docs (entry points for this repo):
15
15
  - [AUDIT_INSTRUCTIONS.md](./AUDIT_INSTRUCTIONS.md) — what to focus on for a security audit and how to start.
16
16
  - [SKILLS.md](./SKILLS.md) — implementation nuances, gotchas, and reading order for working on this codebase.
17
17
  - [STYLE_GUIDE.md](./STYLE_GUIDE.md) — Solidity conventions and repo layout used across the V6 ecosystem.
18
- - [CHANGELOG.md](./CHANGELOG.md) v5 v6 ABI and behavior deltas.
18
+ - [CHANGELOG.md](./CHANGELOG.md) - V5 to V6 ABI and behavior deltas.
19
19
  - [references/entrypoints.md](./references/entrypoints.md) — callable entrypoints by contract.
20
20
  - [references/types-errors-events.md](./references/types-errors-events.md) — packed metadata, errors, events, and hook return shapes.
21
21
 
@@ -36,7 +36,7 @@ Use this repo when you need the protocol's canonical accounting and execution lo
36
36
 
37
37
  If you only read one V6 repo before reading the rest, read this one.
38
38
 
39
- ## Mental Model
39
+ ## Mental model
40
40
 
41
41
  It helps to think about core in four layers:
42
42
 
@@ -54,7 +54,7 @@ The shortest reading path is:
54
54
  3. `JBTerminalStore` for the accounting model
55
55
  4. `JBDirectory` and `JBPermissions` for routing and authority
56
56
 
57
- ## Read These Files First
57
+ ## Read these files first
58
58
 
59
59
  1. `src/JBController.sol`
60
60
  2. `src/JBMultiTerminal.sol`
@@ -63,7 +63,7 @@ The shortest reading path is:
63
63
  5. `src/JBRulesets.sol`
64
64
  6. `src/JBPermissions.sol`
65
65
 
66
- ## Key Contracts
66
+ ## Key contracts
67
67
 
68
68
  | Contract | Role |
69
69
  | --- | --- |
@@ -75,14 +75,14 @@ The shortest reading path is:
75
75
  | `JBPermissions` | Packed operator-permission registry. |
76
76
  | `JBPrices` | Price-feed routing used by terminals and integrations. |
77
77
 
78
- ## Integration Traps
78
+ ## Integration traps
79
79
 
80
80
  - `JBMultiTerminal` is multi-token and multi-terminal. Do not assume one token or one balance.
81
81
  - Data hooks and cash-out hooks can change economics and side effects. They are part of the protocol surface.
82
82
  - Permission checks are not always against the project owner. Some flows are scoped to the token holder instead.
83
83
  - Preview and execution are intentionally close, but callers should still treat them as separate surfaces when hooks or routing can change behavior.
84
84
 
85
- ## Where State Lives
85
+ ## Where state lives
86
86
 
87
87
  - project identity and ownership: `JBProjects`
88
88
  - controller and terminal routing: `JBDirectory`
@@ -92,7 +92,7 @@ The shortest reading path is:
92
92
 
93
93
  When a flow is unclear, read the contract that owns the state before the contract that forwards into it.
94
94
 
95
- ## High-Signal Tests
95
+ ## High-signal tests
96
96
 
97
97
  1. `test/TestPayBurnRedeemFlow.sol`
98
98
  2. `test/TestTerminalPreviewParity.sol`
@@ -122,11 +122,11 @@ Useful scripts:
122
122
  - `npm run deploy:mainnets:periphery`
123
123
  - `npm run deploy:testnets:periphery`
124
124
 
125
- ## Deployment Notes
125
+ ## Deployment notes
126
126
 
127
127
  This repo contains the main core deployments and periphery deployment helpers. Most other V6 packages assume these contracts exist first and treat them as the stable base layer.
128
128
 
129
- ## Repository Layout
129
+ ## Repository layout
130
130
 
131
131
  ```text
132
132
  src/
@@ -139,7 +139,7 @@ script/
139
139
  helpers/
140
140
  ```
141
141
 
142
- ## Risks And Notes
142
+ ## Risks and notes
143
143
 
144
144
  See [RISKS.md](./RISKS.md) for the full risk register. In short:
145
145
 
@@ -150,7 +150,7 @@ See [RISKS.md](./RISKS.md) for the full risk register. In short:
150
150
 
151
151
  The easiest way to misread V6 is to treat core like a simple crowdfunding terminal. It is closer to a configurable accounting and settlement layer.
152
152
 
153
- ## For AI Agents
153
+ ## For AI agents
154
154
 
155
155
  - Start with `JBController`, `JBMultiTerminal`, and `JBTerminalStore`.
156
156
  - Keep controller configuration, terminal execution, and store accounting separate in your mental model.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/core-v6",
3
- "version": "0.0.81",
3
+ "version": "0.0.83",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,10 +35,10 @@
35
35
  "artifacts": "source ./.env && npx sphinx artifacts --org-id 'ea165b21-7cdc-4d7b-be59-ecdd4c26bee4' --project-name 'nana-core-v6'"
36
36
  },
37
37
  "dependencies": {
38
- "@bananapus/permission-ids-v6": "^0.0.28",
38
+ "@bananapus/permission-ids-v6": "^0.0.30",
39
39
  "@chainlink/contracts": "1.5.0",
40
40
  "@openzeppelin/contracts": "5.6.1",
41
- "@prb/math": "4.1.1",
41
+ "@prb/math": "4.1.2",
42
42
  "@uniswap/permit2": "github:Uniswap/permit2#cc56ad0f3439c502c246fc5cfcc3db92bb8b7219"
43
43
  },
44
44
  "devDependencies": {
@@ -28,7 +28,7 @@ The core Juicebox V6 protocol on EVM: a modular system for launching treasury-ba
28
28
  | `JBDeadline` | Approval hook: rejects rulesets queued within `DURATION` seconds of start. Ships as `JBDeadline3Hours`, `JBDeadline1Day`, `JBDeadline3Days`, `JBDeadline7Days`. |
29
29
  | `JBMatchingPriceFeed` | Always returns 1:1. For equivalent currencies (e.g. ETH/NATIVE_TOKEN). |
30
30
 
31
- ## Key Functions
31
+ ## Key functions
32
32
 
33
33
  ### JBController
34
34
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use this file when you need deeper protocol reference material after the repo-local `SKILLS.md` has already routed you to `nana-core-v6`.
4
4
 
5
- ## Key Types
5
+ ## Key types
6
6
 
7
7
  | Struct/Enum | Key Fields | Used In |
8
8
  |-------------|------------|---------|
@@ -23,7 +23,7 @@ Use this file when you need deeper protocol reference material after the repo-lo
23
23
  | `JBRulesetWeightCache` | `weight (uint112)`, `weightCutMultiple (uint168)` | Weight caching for long-running rulesets in `JBRulesets` |
24
24
  | `JBApprovalStatus` (enum) | `Empty`, `Upcoming`, `Active`, `ApprovalExpected`, `Approved`, `Failed` | Approval hook status for queued rulesets |
25
25
 
26
- ### Hook Structs
26
+ ### Hook structs
27
27
 
28
28
  | Struct | Key Fields | Used In |
29
29
  |--------|------------|---------|
@@ -53,13 +53,13 @@ Use this file when you need deeper protocol reference material after the repo-lo
53
53
  | `1` | ETH |
54
54
  | `2` | USD |
55
55
 
56
- ### Split Group IDs (`JBSplitGroupIds`)
56
+ ### Split group IDs (`JBSplitGroupIds`)
57
57
 
58
58
  | ID | Group |
59
59
  |----|-------|
60
60
  | `1` | `RESERVED_TOKENS` -- reserved token distribution |
61
61
 
62
- ### Special Values
62
+ ### Special values
63
63
 
64
64
  | Value | Context | Meaning |
65
65
  |-------|---------|---------|
@@ -143,7 +143,7 @@ Quick-reference for the most common `JBPermissionIds` values (from `@bananapus/p
143
143
 
144
144
  IDs 22-33 are used by extension contracts (721 hook, buyback hook, router terminal, suckers).
145
145
 
146
- ## Common Errors
146
+ ## Common errors
147
147
 
148
148
  Errors an agent is most likely to encounter. All are custom errors (revert with selector).
149
149
 
@@ -187,7 +187,7 @@ Errors an agent is most likely to encounter. All are custom errors (revert with
187
187
  | `JBRulesets_InvalidWeightCutPercent` | `JBRulesets` | `weightCutPercent` exceeds `MAX_WEIGHT_CUT_PERCENT`. |
188
188
  | `JBFundAccessLimits_InvalidPayoutLimitCurrencyOrdering` | `JBFundAccessLimits` | Payout limit currencies not in strictly increasing order. |
189
189
 
190
- ## Key Events
190
+ ## Key events
191
191
 
192
192
  The most important events for indexing and off-chain monitoring. Indexed params marked with `*`.
193
193
 
@@ -220,7 +220,7 @@ The most important events for indexing and off-chain monitoring. Indexed params
220
220
  | `SetSplit` | `IJBSplits` | (projectId, rulesetId, groupId, split, caller) |
221
221
  | `AddPriceFeed` | `IJBPrices` | (projectId, pricingCurrency, unitCurrency, feed, caller) |
222
222
 
223
- ## Hook Interface Return Types
223
+ ## Hook interface return types
224
224
 
225
225
  ### `IJBRulesetDataHook.beforePayRecordedWith()`
226
226
 
@@ -260,7 +260,7 @@ function hasMintPermissionFor(uint256 projectId, JBRuleset memory ruleset, addre
260
260
 
261
261
  Returns whether `addr` is allowed to mint tokens for the project. Called by `JBController.mintTokensOf` when the caller is not the owner and `allowOwnerMinting` is false -- the data hook can grant mint permission to specific addresses (e.g. suckers for omnichain bridging).
262
262
 
263
- ## Example Integration
263
+ ## Example integration
264
264
 
265
265
  ```solidity
266
266
  // SPDX-License-Identifier: MIT
@@ -17,8 +17,13 @@ contract JBChainlinkV3PriceFeed is IJBPriceFeed {
17
17
  // --------------------------- custom errors ------------------------- //
18
18
  //*********************************************************************//
19
19
 
20
+ /// @notice Thrown when the feed round is not finished or was not answered in the current round.
20
21
  error JBChainlinkV3PriceFeed_IncompleteRound(uint80 roundId, uint80 answeredInRound, uint256 updatedAt);
22
+
23
+ /// @notice Thrown when the feed reports a non-positive price.
21
24
  error JBChainlinkV3PriceFeed_NegativePrice(int256 price);
25
+
26
+ /// @notice Thrown when the feed's last update is older than the staleness threshold.
22
27
  error JBChainlinkV3PriceFeed_StalePrice(uint256 timestamp, uint256 threshold, uint256 updatedAt);
23
28
 
24
29
  //*********************************************************************//
@@ -14,7 +14,10 @@ contract JBChainlinkV3SequencerPriceFeed is JBChainlinkV3PriceFeed {
14
14
  // --------------------------- custom errors ------------------------- //
15
15
  //*********************************************************************//
16
16
 
17
+ /// @notice Thrown when the sequencer uptime round is invalid (e.g. the uptime contract is not yet initialized).
17
18
  error JBChainlinkV3SequencerPriceFeed_InvalidRound(uint256 startedAt);
19
+
20
+ /// @notice Thrown when the L2 sequencer is down or has restarted too recently for the grace period to elapse.
18
21
  error JBChainlinkV3SequencerPriceFeed_SequencerDownOrRestarting(
19
22
  uint256 timestamp, uint256 gracePeriodTime, uint256 startedAt
20
23
  );
@@ -58,21 +58,52 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
58
58
  // --------------------------- custom errors ------------------------- //
59
59
  //*********************************************************************//
60
60
 
61
+ /// @notice Thrown when the project's current ruleset does not allow adding price feeds.
61
62
  error JBController_AddingPriceFeedNotAllowed(uint256 projectId);
63
+
64
+ /// @notice Thrown when transferring credits while the current ruleset pauses credit transfers.
62
65
  error JBController_CreditTransfersPaused(uint256 projectId, uint256 rulesetId);
66
+
67
+ /// @notice Thrown when the cash out tax rate exceeds the allowed maximum.
63
68
  error JBController_InvalidCashOutTaxRate(uint256 rate, uint256 limit);
69
+
70
+ /// @notice Thrown when the native value sent does not equal the required creation fee.
64
71
  error JBController_InvalidCreationFee(uint256 value, uint256 requiredFee);
72
+
73
+ /// @notice Thrown when the reserved percent exceeds the allowed maximum.
65
74
  error JBController_InvalidReservedPercent(uint256 percent, uint256 limit);
75
+
76
+ /// @notice Thrown when the caller is not allowed to mint and is not a terminal or data hook for the project.
66
77
  error JBController_MintNotAllowedAndNotTerminalOrHook(address caller);
78
+
79
+ /// @notice Thrown when there are no reserved tokens to send to splits.
67
80
  error JBController_NoReservedTokens(uint256 projectId);
81
+
82
+ /// @notice Thrown when the caller is not the directory.
68
83
  error JBController_OnlyDirectory(address sender, IJBDirectory directory);
84
+
85
+ /// @notice Thrown when migrating a project that still has pending reserved tokens.
69
86
  error JBController_PendingReservedTokens(uint256 pendingReservedTokenBalance);
87
+
88
+ /// @notice Thrown when a reserved token split routes back into the same project via the terminal-payment path.
70
89
  error JBController_ReservedTokenSplitProjectSameAsOwner(uint256 projectId);
90
+
91
+ /// @notice Thrown when launching rulesets for a project that has already launched.
71
92
  error JBController_RulesetsAlreadyLaunched(uint256 projectId);
93
+
94
+ /// @notice Thrown when the ruleset configurations array is empty.
72
95
  error JBController_RulesetsArrayEmpty(uint256 projectId, uint256 rulesetConfigurationCount);
96
+
97
+ /// @notice Thrown when the project's current ruleset does not allow setting a custom token.
73
98
  error JBController_RulesetSetTokenNotAllowed(uint256 projectId);
99
+
100
+ /// @notice Thrown when the terminal did not pull the full token allowance during a payout.
74
101
  error JBController_TerminalTokensNotTransferred(address terminal, address token, uint256 allowance);
102
+
103
+ /// @notice Thrown when attempting to burn zero tokens.
75
104
  error JBController_ZeroTokensToBurn(uint256 projectId, address holder);
105
+
106
+ /// @notice Thrown when attempting to mint zero tokens.
76
107
  error JBController_ZeroTokensToMint(uint256 projectId, address beneficiary);
77
108
 
78
109
  //*********************************************************************//
@@ -281,8 +312,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
281
312
  }
282
313
 
283
314
  /// @notice Converts a holder's internal project token credits into the project's ERC-20 representation,
284
- /// transferring them to the beneficiary's wallet. Credits and the ERC-20 are equivalent project tokens this
285
- /// just
315
+ /// transferring them to the beneficiary's wallet. Credits and the ERC-20 are equivalent project tokens; this just
286
316
  /// makes them transferable/tradeable.
287
317
  /// @dev Can only be called by the credit holder or an operator with `CLAIM_TOKENS` permission.
288
318
  /// @param holder The address whose project token credits are being redeemed.
@@ -342,8 +372,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
342
372
  return TOKENS.deployERC20For({projectId: projectId, name: name, symbol: symbol, salt: saltHash});
343
373
  }
344
374
 
345
- /// @notice When a project receives reserved tokens, if it has a terminal for the token, this is used to pay the
346
- /// terminal.
375
+ /// @notice Pays a project's terminal with reserved tokens when the project has a terminal for that token.
347
376
  /// @dev Can only be called by this controller.
348
377
  /// @param terminal The terminal to pay.
349
378
  /// @param projectId The ID of the project to pay.
@@ -386,9 +415,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
386
415
  }
387
416
  }
388
417
 
389
- /// @notice Creates a new Juicebox project in one transaction mints the project NFT, queues initial rulesets,
390
- /// and
391
- /// configures terminals. This is the primary entry point for launching a project.
418
+ /// @notice Creates a Juicebox project in one transaction: mints the NFT, queues rulesets, and configures terminals.
392
419
  /// @dev Anyone can call this on behalf of any owner. This is a launch convenience, not owner authorization proof:
393
420
  /// frontends and operators must use the transaction sender, an explicit owner signature, or their own deployment
394
421
  /// flow to decide whether the owner intentionally launched a configuration. Each sub-operation (mint, queue,
@@ -707,15 +734,14 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
707
734
  // If there's no current ruleset, get a reference to the upcoming one.
708
735
  if (ruleset.id == 0) ruleset = _upcomingRulesetOf(projectId);
709
736
 
710
- // If owner minting is disabled for the ruleset, the owner cannot change the token.
737
+ // If the ruleset doesn't allow setting a custom token, the owner cannot change the token.
711
738
  if (!ruleset.allowSetCustomToken()) revert JBController_RulesetSetTokenNotAllowed(projectId);
712
739
 
713
740
  TOKENS.setTokenFor({projectId: projectId, token: token});
714
741
  }
715
742
 
716
743
  /// @notice Sets the name and symbol of a project's token.
717
- /// @dev Can only be called by the project's owner or an address with the owner's permission to
718
- /// `SET_TOKEN_METADATA`.
744
+ /// @dev Can only be called by the project's owner or an address with the owner's `SET_TOKEN_METADATA` permission.
719
745
  /// @param projectId The ID of the project to update the token for.
720
746
  /// @param name The new name.
721
747
  /// @param symbol The new symbol.
@@ -730,8 +756,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
730
756
 
731
757
  /// @notice Set a project's metadata URI.
732
758
  /// @dev This is typically an IPFS hash, optionally with an `ipfs://` prefix.
733
- /// @dev Can only be called by the project's owner or an address with the owner's permission to
734
- /// `SET_PROJECT_URI`.
759
+ /// @dev Can only be called by the project's owner or an address with the owner's `SET_PROJECT_URI` permission.
735
760
  /// @param projectId The ID of the project to set the metadata URI of.
736
761
  /// @param uri The metadata URI to set.
737
762
  function setUriOf(uint256 projectId, string calldata uri) external override {
@@ -783,8 +808,8 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
783
808
 
784
809
  /// @notice Returns a paginated history of a project's rulesets (with decoded metadata), sorted newest-first.
785
810
  /// @param projectId The ID of the project to get the rulesets of.
786
- /// @param startingId The ID of the ruleset to begin with. This will be the latest ruleset in the result. If the
787
- /// `startingId` is 0, passed, the project's latest ruleset will be used.
811
+ /// @param startingId The ID of the ruleset to begin with. This will be the latest ruleset in the result.
812
+ /// If 0 is passed, the project's latest ruleset will be used.
788
813
  /// @param size The maximum number of rulesets to return.
789
814
  /// @return rulesets The array of rulesets with their metadata.
790
815
  function allRulesetsOf(
@@ -1215,8 +1240,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
1215
1240
  }
1216
1241
 
1217
1242
  /// @notice Sends pending reserved tokens to the project's reserved token splits.
1218
- /// @dev If the project has no reserved token splits, or if they don't add up to 100%, leftover tokens are sent to
1219
- /// the project's owner.
1243
+ /// @dev If the project has no reserved token splits, or if they don't add up to 100%, leftovers go to the owner.
1220
1244
  /// @param projectId The ID of the project to send reserved tokens for.
1221
1245
  /// @return tokenCount The amount of reserved tokens minted and sent.
1222
1246
  function _sendReservedTokensToSplitsOf(uint256 projectId) internal returns (uint256 tokenCount) {
@@ -1320,7 +1344,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
1320
1344
  return RULESETS.currentOf(projectId);
1321
1345
  }
1322
1346
 
1323
- /// @notice Indicates whether the provided address has mint permission for the project byway of the data hook.
1347
+ /// @notice Indicates whether the provided address has mint permission for the project by way of the data hook.
1324
1348
  /// @param projectId The ID of the project to check.
1325
1349
  /// @param ruleset The ruleset to check.
1326
1350
  /// @param addr The address to check.
@@ -23,10 +23,19 @@ contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
23
23
  // --------------------------- custom errors ------------------------- //
24
24
  //*********************************************************************//
25
25
 
26
+ /// @notice Thrown when the same terminal appears more than once in the provided terminals list.
26
27
  error JBDirectory_DuplicateTerminals(IJBTerminal terminal);
28
+
29
+ /// @notice Thrown when the project ID is greater than the number of existing projects.
27
30
  error JBDirectory_InvalidProjectIdInDirectory(uint256 projectId, uint256 limit);
31
+
32
+ /// @notice Thrown when the project's current controller does not allow setting a new controller.
28
33
  error JBDirectory_SetControllerNotAllowed(uint256 projectId);
34
+
35
+ /// @notice Thrown when the project's current controller does not allow setting terminals.
29
36
  error JBDirectory_SetTerminalsNotAllowed(uint256 projectId);
37
+
38
+ /// @notice Thrown when the terminal being set as primary does not accept the given token.
30
39
  error JBDirectory_TokenNotAccepted(uint256 projectId, address token, IJBTerminal terminal);
31
40
 
32
41
  //*********************************************************************//
@@ -40,8 +49,7 @@ contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
40
49
  // --------------------- public stored properties -------------------- //
41
50
  //*********************************************************************//
42
51
 
43
- /// @notice The specified project's controller, which dictates how its terminals interact with its tokens and
44
- /// rulesets.
52
+ /// @notice The specified project's controller, which dictates how terminals interact with tokens and rulesets.
45
53
  /// @custom:param projectId The ID of the project to get the controller of.
46
54
  mapping(uint256 projectId => IERC165) public override controllerOf;
47
55
 
@@ -89,8 +97,7 @@ contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
89
97
  /// its tokens and rulesets. If the project already has a controller, this triggers a full migration lifecycle
90
98
  /// (`beforeReceiveMigrationFrom` → `migrate` → state update → `afterReceiveMigrationFrom`).
91
99
  /// @dev Can only be called if:
92
- /// - The ruleset's metadata has `allowSetController` enabled, and the caller is the project's owner or has
93
- /// `SET_CONTROLLER` permission.
100
+ /// - The ruleset metadata enables `allowSetController`, and the caller owns the project or has `SET_CONTROLLER`.
94
101
  /// - OR the caller `isAllowedToSetFirstController` and the project has no controller yet.
95
102
  /// @param projectId The ID of the project to set the controller for.
96
103
  /// @param controller The address of the controller to set.
package/src/JBERC20.sol CHANGED
@@ -25,7 +25,10 @@ contract JBERC20 is ERC20Votes, ERC20Permit, JBPermissioned, IERC1271, IJBToken
25
25
  // --------------------------- custom errors ------------------------- //
26
26
  //*********************************************************************//
27
27
 
28
+ /// @notice Thrown when initializing a token that already has a name set, or when the provided name is empty.
28
29
  error JBERC20_AlreadyInitialized(uint256 currentNameLength, uint256 newNameLength);
30
+
31
+ /// @notice Thrown when the caller is not the JBTokens contract that owns this token.
29
32
  error JBERC20_Unauthorized(address caller, address tokens);
30
33
 
31
34
  //*********************************************************************//
@@ -16,6 +16,7 @@ contract JBFeelessAddresses is Ownable, IJBFeelessAddresses, IERC165 {
16
16
  // --------------------------- custom errors ------------------------- //
17
17
  //*********************************************************************//
18
18
 
19
+ /// @notice Thrown when the provided feeless hook does not support the `IJBFeelessHook` interface.
19
20
  error JBFeelessAddresses_InvalidFeelessHook(IJBFeelessHook hook);
20
21
 
21
22
  //*********************************************************************//
@@ -33,6 +34,8 @@ contract JBFeelessAddresses is Ownable, IJBFeelessAddresses, IERC165 {
33
34
 
34
35
  /// @notice Raw feeless status per project per address.
35
36
  /// @dev `projectId = 0` stores the global (all-project) feeless status.
37
+ /// @custom:param projectId The ID of the project. A `projectId` of 0 is the global (all-project) key.
38
+ /// @custom:param addr The address whose feeless status is being stored.
36
39
  mapping(uint256 projectId => mapping(address addr => bool)) internal _isFeelessFor;
37
40
 
38
41
  //*********************************************************************//
@@ -18,12 +18,17 @@ contract JBFundAccessLimits is JBControlled, IJBFundAccessLimits {
18
18
  // --------------------------- custom errors ------------------------- //
19
19
  //*********************************************************************//
20
20
 
21
+ /// @notice Thrown when two fund access limit groups share the same terminal and token.
21
22
  error JBFundAccessLimits_DuplicateFundAccessLimitGroup(
22
23
  uint256 projectId, uint256 rulesetId, uint256 groupIndex, address terminal, address token
23
24
  );
25
+
26
+ /// @notice Thrown when payout limits within a group are not ordered by ascending currency.
24
27
  error JBFundAccessLimits_InvalidPayoutLimitCurrencyOrdering(
25
28
  uint256 projectId, uint256 rulesetId, uint256 groupIndex, uint256 limitIndex
26
29
  );
30
+
31
+ /// @notice Thrown when surplus allowances within a group are not ordered by ascending currency.
27
32
  error JBFundAccessLimits_InvalidSurplusAllowanceCurrencyOrdering(
28
33
  uint256 projectId, uint256 rulesetId, uint256 groupIndex, uint256 allowanceIndex
29
34
  );