@bananapus/ownable-v6 0.0.16 → 0.0.18

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/CHANGE_LOG.md DELETED
@@ -1,235 +0,0 @@
1
- # nana-ownable-v6 Changelog (v5 → v6)
2
-
3
- This document describes all changes between `nana-ownable` (v5) and `nana-ownable-v6` (v6).
4
-
5
- ## Summary
6
-
7
- - **Defensive `try-catch` on all `PROJECTS.ownerOf()` calls**: `owner()` now returns `address(0)` instead of reverting for burned/invalid project NFTs — changes observable behavior for callers.
8
- - **New safety validations**: `transferOwnershipToProject()` checks project existence; constructor rejects zero-address `PROJECTS` with project-based ownership.
9
- - **Solidity version pinned**: Changed from floating `^0.8.23` to exact `^0.8.26`.
10
-
11
- ---
12
-
13
- ## 1. Breaking Changes
14
-
15
- ### Solidity Version Pinned
16
-
17
- All contracts changed from `pragma solidity ^0.8.23` (floating) to `pragma solidity ^0.8.26` (pinned). This means v6 can only compile with Solidity ^0.8.26 exactly.
18
-
19
- **Affected files:** `JBOwnable.sol`, `JBOwnableOverrides.sol`
20
-
21
- ### Import Paths Updated
22
-
23
- All imports reference `@bananapus/core-v6` instead of `@bananapus/core-v5`. Any project depending on `nana-ownable` must also migrate to `nana-core-v6`.
24
-
25
- ### `owner()` Returns `address(0)` Instead of Reverting for Invalid Projects
26
-
27
- In v5, if a project NFT was burned or otherwise invalid, `owner()` would revert because `PROJECTS.ownerOf()` reverts for nonexistent tokens.
28
-
29
- In v6, `owner()` wraps the call in `try-catch` and returns `address(0)` if `ownerOf()` reverts. This changes the observable behavior: callers that previously relied on a revert to detect invalid project ownership will now receive `address(0)` instead.
30
-
31
- ### `_checkOwner()` Behavior Change for Invalid Projects
32
-
33
- In v5, `_checkOwner()` would revert with the ERC-721 "nonexistent token" error if the owning project NFT was burned.
34
-
35
- In v6, it resolves the owner to `address(0)` via `try-catch` and then passes `address(0)` to `_requirePermissionFrom`. This still causes a revert (no one can authenticate as `address(0)`), but the revert reason changes from an ERC-721 error to a permissions error.
36
-
37
- ### `transferOwnershipToProject()` Now Validates Project Existence
38
-
39
- In v6, `transferOwnershipToProject()` checks `projectId > PROJECTS.count()` and reverts with `JBOwnableOverrides_ProjectDoesNotExist()` if the project has not been created yet. In v5, no such check existed, so ownership could be transferred to a nonexistent project ID.
40
-
41
- ### Constructor Validates `PROJECTS` Address for Project-Based Ownership
42
-
43
- In v6, the constructor reverts with `JBOwnableOverrides_ZeroAddressProjectsWithProjectOwner()` if `initialProjectIdOwner != 0` and `address(projects) == address(0)`. In v5, this combination was silently accepted, which would permanently break ownership resolution since `ownerOf()` calls on `address(0)` would always revert.
44
-
45
- ### `IJBOwnable` Return Name Changes
46
-
47
- The second return value of `jbOwner()` was renamed from `projectOwner` (v5) to `projectId` (v6) in the interface. The type (`uint88`) and position are unchanged, so the ABI is identical, but code referencing the named return will need updating.
48
-
49
- Additionally, `PROJECTS()` and `owner()` gained named return values in the interface:
50
-
51
- - `PROJECTS()`: `returns (IJBProjects)` (v5) -> `returns (IJBProjects projects)` (v6)
52
- - `owner()`: `returns (address)` (v5) -> `returns (address owner)` (v6)
53
-
54
- These are ABI-compatible but change the Solidity-level interface signature.
55
-
56
- ---
57
-
58
- ## 2. New Features
59
-
60
- ### Defensive `try-catch` on All `PROJECTS.ownerOf()` Calls
61
-
62
- Every call to `PROJECTS.ownerOf()` in v6 is wrapped in a `try-catch` block. If the call reverts (e.g., burned NFT, broken ERC-721 implementation), the resolved owner falls back to `address(0)`. This applies to:
63
-
64
- - `owner()` -- returns `address(0)` instead of reverting.
65
- - `_checkOwner()` -- resolves to `address(0)`, causing a permissions revert.
66
- - `_transferOwnership(address, uint88)` -- resolves old owner to `address(0)` for the transfer event.
67
-
68
- ### Project Existence Validation on `transferOwnershipToProject()`
69
-
70
- `transferOwnershipToProject()` now calls `PROJECTS.count()` to verify the target project exists before transferring ownership, preventing accidental loss of contract control by transferring to a nonexistent project.
71
-
72
- ### Constructor Guard Against Zero-Address `PROJECTS` with Project Ownership
73
-
74
- A new constructor check prevents deploying with `projects == address(0)` when `initialProjectIdOwner != 0`, which would make ownership irrecoverable.
75
-
76
- ### Comprehensive NatSpec Documentation on `IJBOwnable`
77
-
78
- The v6 interface adds full NatSpec documentation for all events, functions, parameters, and return values. The v5 interface had no NatSpec comments at all.
79
-
80
- ---
81
-
82
- ## 3. Event Changes
83
-
84
- No event signatures changed. Both versions define the same two events with identical parameters and indexing:
85
-
86
- - `OwnershipTransferred(address indexed previousOwner, address indexed newOwner, address caller)`
87
- - `PermissionIdChanged(uint8 newId, address caller)`
88
-
89
- The only difference is the addition of NatSpec documentation on both events in v6's `IJBOwnable.sol`, and the declaration order was swapped (v5: `PermissionIdChanged` first, then `OwnershipTransferred`; v6: `OwnershipTransferred` first, then `PermissionIdChanged`).
90
-
91
- ---
92
-
93
- ## 4. Error Changes
94
-
95
- ### New Errors
96
-
97
- | Error | Contract | Description |
98
- |---|---|---|
99
- | `JBOwnableOverrides_ProjectDoesNotExist()` | `JBOwnableOverrides` | Reverts in `transferOwnershipToProject()` if `projectId > PROJECTS.count()`. |
100
- | `JBOwnableOverrides_ZeroAddressProjectsWithProjectOwner()` | `JBOwnableOverrides` | Reverts in constructor if `initialProjectIdOwner != 0` and `address(projects) == address(0)`. |
101
-
102
- ### Unchanged Errors
103
-
104
- | Error | Status |
105
- |---|---|
106
- | `JBOwnableOverrides_InvalidNewOwner()` | Unchanged -- still used for zero-address owner, zero project ID, and dual-set owner+project scenarios. |
107
-
108
- ---
109
-
110
- ## 5. Struct Changes
111
-
112
- ### `JBOwner` (unchanged)
113
-
114
- The struct itself is identical in both versions:
115
-
116
- ```solidity
117
- struct JBOwner {
118
- address owner;
119
- uint88 projectId;
120
- uint8 permissionId;
121
- }
122
- ```
123
-
124
- The only difference is the addition of a `// forge-lint: disable-next-line(pascal-case-struct)` comment in v6.
125
-
126
- ---
127
-
128
- ## 6. Implementation Changes (Non-Interface)
129
-
130
- ### `JBOwnableOverrides._checkOwner()` -- Refactored Owner Resolution
131
-
132
- **v5:**
133
- ```solidity
134
- function _checkOwner() internal view virtual {
135
- JBOwner memory ownerInfo = jbOwner;
136
- _requirePermissionFrom({
137
- account: ownerInfo.projectId == 0 ? ownerInfo.owner : PROJECTS.ownerOf(ownerInfo.projectId),
138
- projectId: ownerInfo.projectId,
139
- permissionId: ownerInfo.permissionId
140
- });
141
- }
142
- ```
143
-
144
- **v6:**
145
- ```solidity
146
- function _checkOwner() internal view virtual {
147
- JBOwner memory ownerInfo = jbOwner;
148
- address resolvedOwner;
149
- if (ownerInfo.projectId == 0) {
150
- resolvedOwner = ownerInfo.owner;
151
- } else {
152
- try PROJECTS.ownerOf(ownerInfo.projectId) returns (address projectOwner) {
153
- resolvedOwner = projectOwner;
154
- } catch {
155
- resolvedOwner = address(0);
156
- }
157
- }
158
- _requirePermissionFrom({
159
- account: resolvedOwner, projectId: ownerInfo.projectId, permissionId: ownerInfo.permissionId
160
- });
161
- }
162
- ```
163
-
164
- The ternary expression is replaced with an explicit `if/else` block and `try-catch` for defensive error handling.
165
-
166
- ### `JBOwnableOverrides.owner()` -- Try-Catch on Project Lookup
167
-
168
- **v5:**
169
- ```solidity
170
- return PROJECTS.ownerOf(ownerInfo.projectId);
171
- ```
172
-
173
- **v6:**
174
- ```solidity
175
- try PROJECTS.ownerOf(ownerInfo.projectId) returns (address projectOwner) {
176
- return projectOwner;
177
- } catch {
178
- return address(0);
179
- }
180
- ```
181
-
182
- ### `JBOwnableOverrides._transferOwnership(address, uint88)` -- Try-Catch on Old Owner Lookup
183
-
184
- **v5:**
185
- ```solidity
186
- address oldOwner = ownerInfo.projectId == 0 ? ownerInfo.owner : PROJECTS.ownerOf(ownerInfo.projectId);
187
- ```
188
-
189
- **v6:**
190
- ```solidity
191
- address oldOwner;
192
- if (ownerInfo.projectId == 0) {
193
- oldOwner = ownerInfo.owner;
194
- } else {
195
- try PROJECTS.ownerOf(ownerInfo.projectId) returns (address projectOwner) {
196
- oldOwner = projectOwner;
197
- } catch {
198
- oldOwner = address(0);
199
- }
200
- }
201
- ```
202
-
203
- ### Named Arguments Used Throughout
204
-
205
- All internal function calls in v6 use named arguments (e.g., `_transferOwnership({newOwner: initialOwner, projectId: initialProjectIdOwner})`) instead of positional arguments. This is a style-only change with no behavioral impact.
206
-
207
- ### NatSpec Improvements
208
-
209
- - `JBOwnable._emitTransferEvent()`: Incomplete comment in v5 (`"some contracts will try to deploy contracts for a project before"`) is completed in v6 (`"some contracts need to deploy contracts for a project before the project's NFT has been minted, so the transfer event resolves the project's current owner at emission time."`). A new `@dev` comment also explains why this function intentionally does NOT use try-catch (unlike `_transferOwnership`): reverting on a nonexistent new project is desirable to prevent transferring ownership to an invalid project.
210
- - `JBOwnableOverrides._emitTransferEvent()`: Added `@param` tags for `previousOwner`, `newOwner`, and `newProjectId`.
211
- - `renounceOwnership()`, `setPermissionId()`: Changed `@notice This can only be called by the current owner.` to `@dev`.
212
- - `transferOwnership()`, `transferOwnershipToProject()`: Added documentation about `permissionId` being reset to 0 on transfer.
213
- - Constructor `@param initialOwner`: Fixed typo `intialProjectIdOwner` to `initialProjectIdOwner`.
214
-
215
- ### Comment/Formatting Fixes
216
-
217
- - Fixed malformed section header comment in v5 (`custom errors --------------------------//b`) to properly formatted (`custom errors ------------------------- //`).
218
-
219
- ---
220
-
221
- ## 7. Migration Table
222
-
223
- | v5 | v6 | Change Type |
224
- |---|---|---|
225
- | `pragma solidity ^0.8.23` | `pragma solidity ^0.8.26` | Pinned compiler version |
226
- | `@bananapus/core-v5` imports | `@bananapus/core-v6` imports | Dependency upgrade |
227
- | `PROJECTS.ownerOf()` called directly | `try PROJECTS.ownerOf() catch` in `owner()`, `_checkOwner()`, `_transferOwnership()` | Defensive error handling |
228
- | `transferOwnershipToProject()` -- no existence check | Reverts with `JBOwnableOverrides_ProjectDoesNotExist()` if `projectId > PROJECTS.count()` | New validation |
229
- | Constructor allows `projects == address(0)` with `initialProjectIdOwner != 0` | Reverts with `JBOwnableOverrides_ZeroAddressProjectsWithProjectOwner()` | New validation |
230
- | `IJBOwnable.jbOwner()` returns `(address owner, uint88 projectOwner, uint8 permissionId)` | Returns `(address owner, uint88 projectId, uint8 permissionId)` | Return name change (ABI compatible) |
231
- | `IJBOwnable.PROJECTS()` returns `(IJBProjects)`, `owner()` returns `(address)` | Returns `(IJBProjects projects)`, `(address owner)` | Named return values added (ABI compatible) |
232
- | `IJBOwnable` -- no NatSpec | Full NatSpec on all events, functions, params, and returns | Documentation |
233
- | Positional arguments in internal calls | Named arguments throughout | Style only |
234
- | 1 custom error | 3 custom errors (`+ ProjectDoesNotExist`, `+ ZeroAddressProjectsWithProjectOwner`) | New errors |
235
- | `JBOwner` struct | Identical (added forge-lint comment only) | No change |