@bananapus/ownable-v6 0.0.23 → 0.0.24
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/package.json +1 -1
- package/src/JBOwnable.sol +5 -10
- package/src/JBOwnableOverrides.sol +29 -23
- package/src/interfaces/IJBOwnable.sol +7 -5
- package/src/structs/JBOwner.sol +6 -6
package/package.json
CHANGED
package/src/JBOwnable.sol
CHANGED
|
@@ -7,16 +7,11 @@ import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.s
|
|
|
7
7
|
|
|
8
8
|
import {JBOwnableOverrides} from "./JBOwnableOverrides.sol";
|
|
9
9
|
|
|
10
|
-
/// @notice
|
|
11
|
-
///
|
|
12
|
-
/// @dev
|
|
13
|
-
///
|
|
14
|
-
///
|
|
15
|
-
/// the owner.
|
|
16
|
-
/// 2. If `JBOwner.projectId` is set to `0`, the `JBOwner.owner` address is the owner.
|
|
17
|
-
/// 3. The owner can give other addresses access with `JBPermissions.setPermissionsFor(...)`, using the
|
|
18
|
-
/// `JBOwner.permissionId` permission.
|
|
19
|
-
/// @dev To use `onlyOwner`, inherit this contract and apply the modifier to a function.
|
|
10
|
+
/// @notice Juicebox-aware ownership for any contract. Inherit this and apply the `onlyOwner` modifier to restrict
|
|
11
|
+
/// functions to the project owner, a fixed address, or anyone the owner has granted permission to via `JBPermissions`.
|
|
12
|
+
/// @dev Ownership resolves dynamically: if `JBOwner.projectId` is set, the holder of that project's ERC-721 NFT is
|
|
13
|
+
/// the owner. If `projectId` is 0, the stored `JBOwner.owner` address is used instead. The owner can delegate access
|
|
14
|
+
/// to other addresses by setting a `permissionId` and granting that permission through `JBPermissions`.
|
|
20
15
|
contract JBOwnable is JBOwnableOverrides {
|
|
21
16
|
//*********************************************************************//
|
|
22
17
|
// -------------------------- constructor ---------------------------- //
|
|
@@ -10,9 +10,12 @@ import {Context} from "@openzeppelin/contracts/utils/Context.sol";
|
|
|
10
10
|
import {IJBOwnable} from "./interfaces/IJBOwnable.sol";
|
|
11
11
|
import {JBOwner} from "./structs/JBOwner.sol";
|
|
12
12
|
|
|
13
|
-
/// @notice
|
|
14
|
-
///
|
|
15
|
-
/// `JBPermissions`.
|
|
13
|
+
/// @notice Abstract base implementing Juicebox-aware ownership resolution, transfer, and permission delegation.
|
|
14
|
+
/// Ownership is either address-based (a fixed EOA/contract) or project-based (whoever holds the project's ERC-721
|
|
15
|
+
/// NFT). The owner can delegate access to other addresses by configuring a `permissionId` in `JBPermissions`.
|
|
16
|
+
/// @dev Stale permission detection: when ownership changes (e.g. project NFT transferred), the `permissionId` is
|
|
17
|
+
/// effectively ignored until the new owner explicitly re-sets it — preventing the previous owner's delegates from
|
|
18
|
+
/// retaining access.
|
|
16
19
|
abstract contract JBOwnableOverrides is Context, JBPermissioned, IJBOwnable {
|
|
17
20
|
//*********************************************************************//
|
|
18
21
|
// --------------------------- custom errors ------------------------- //
|
|
@@ -26,14 +29,14 @@ abstract contract JBOwnableOverrides is Context, JBPermissioned, IJBOwnable {
|
|
|
26
29
|
// ---------------- public immutable stored properties --------------- //
|
|
27
30
|
//*********************************************************************//
|
|
28
31
|
|
|
29
|
-
/// @notice
|
|
32
|
+
/// @notice The `JBProjects` ERC-721 contract used to resolve project-based ownership.
|
|
30
33
|
IJBProjects public immutable override PROJECTS;
|
|
31
34
|
|
|
32
35
|
//*********************************************************************//
|
|
33
36
|
// --------------------- public stored properties -------------------- //
|
|
34
37
|
//*********************************************************************//
|
|
35
38
|
|
|
36
|
-
/// @notice
|
|
39
|
+
/// @notice The current ownership state — who owns this contract and how permission delegation is configured.
|
|
37
40
|
JBOwner public override jbOwner;
|
|
38
41
|
|
|
39
42
|
//*********************************************************************//
|
|
@@ -98,12 +101,11 @@ abstract contract JBOwnableOverrides is Context, JBPermissioned, IJBOwnable {
|
|
|
98
101
|
// -------------------------- public views --------------------------- //
|
|
99
102
|
//*********************************************************************//
|
|
100
103
|
|
|
101
|
-
/// @notice Returns the owner's address based
|
|
102
|
-
///
|
|
103
|
-
///
|
|
104
|
-
///
|
|
105
|
-
///
|
|
106
|
-
/// unexpected ERC-721 behavior.
|
|
104
|
+
/// @notice Returns the current owner's address. If ownership is project-based, this dynamically resolves to
|
|
105
|
+
/// whoever holds the project's ERC-721 NFT right now.
|
|
106
|
+
/// @dev If `projectId` is non-zero, resolves via `PROJECTS.ownerOf()`. If that call reverts (e.g., burned NFT),
|
|
107
|
+
/// returns `address(0)` — effectively treating the contract as renounced. `JBProjects` V6 has no burn function,
|
|
108
|
+
/// so this is a defensive measure only.
|
|
107
109
|
function owner() public view virtual returns (address) {
|
|
108
110
|
JBOwner memory ownerInfo = jbOwner;
|
|
109
111
|
|
|
@@ -124,9 +126,11 @@ abstract contract JBOwnableOverrides is Context, JBPermissioned, IJBOwnable {
|
|
|
124
126
|
// -------------------------- internal views ------------------------- //
|
|
125
127
|
//*********************************************************************//
|
|
126
128
|
|
|
127
|
-
/// @notice Reverts if the
|
|
129
|
+
/// @notice Reverts if the caller is not the owner (or an authorized delegate when `permissionId` is set).
|
|
128
130
|
/// @dev If `projectId` is non-zero and `PROJECTS.ownerOf()` reverts (e.g., burned NFT), the resolved owner is
|
|
129
131
|
/// `address(0)`, causing all `_checkOwner` calls to revert — equivalent to a renounced contract.
|
|
132
|
+
/// @dev Stale permission detection: if the resolved owner differs from `_permissionOwner` (set when
|
|
133
|
+
/// `setPermissionId` was last called), delegation is disabled until the new owner re-configures it.
|
|
130
134
|
function _checkOwner() internal view virtual {
|
|
131
135
|
JBOwner memory ownerInfo = jbOwner;
|
|
132
136
|
|
|
@@ -169,17 +173,18 @@ abstract contract JBOwnableOverrides is Context, JBPermissioned, IJBOwnable {
|
|
|
169
173
|
// ---------------------- public transactions ------------------------ //
|
|
170
174
|
//*********************************************************************//
|
|
171
175
|
|
|
172
|
-
/// @notice
|
|
173
|
-
///
|
|
174
|
-
/// @dev This can only be called by the current owner.
|
|
176
|
+
/// @notice Permanently gives up ownership. After this, no address can call `onlyOwner` functions.
|
|
177
|
+
/// @dev Can only be called by the current owner. This is irreversible.
|
|
175
178
|
function renounceOwnership() public virtual override {
|
|
176
179
|
_checkOwner();
|
|
177
180
|
_transferOwnership({newOwner: address(0), projectId: 0});
|
|
178
181
|
}
|
|
179
182
|
|
|
180
|
-
/// @notice
|
|
181
|
-
///
|
|
182
|
-
/// @
|
|
183
|
+
/// @notice Configures which `JBPermissions` permission ID grants delegate access to `onlyOwner` functions.
|
|
184
|
+
/// Set to 0 to disable delegation entirely (only the direct owner can call).
|
|
185
|
+
/// @dev Can only be called by the current owner. Records the current owner so stale permissions are detected
|
|
186
|
+
/// if ownership later changes.
|
|
187
|
+
/// @param permissionId The permission ID to use for `onlyOwner` delegation.
|
|
183
188
|
function setPermissionId(uint8 permissionId) public virtual override {
|
|
184
189
|
_checkOwner();
|
|
185
190
|
_setPermissionId(permissionId);
|
|
@@ -199,10 +204,11 @@ abstract contract JBOwnableOverrides is Context, JBPermissioned, IJBOwnable {
|
|
|
199
204
|
_transferOwnership({newOwner: newOwner, projectId: 0});
|
|
200
205
|
}
|
|
201
206
|
|
|
202
|
-
/// @notice
|
|
203
|
-
///
|
|
204
|
-
/// The
|
|
205
|
-
///
|
|
207
|
+
/// @notice Transfers ownership to a Juicebox project — whoever holds that project's ERC-721 NFT becomes the
|
|
208
|
+
/// owner.
|
|
209
|
+
/// @dev The `permissionId` is reset to 0 on transfer to prevent the previous owner's delegates from retaining
|
|
210
|
+
/// access. The new project owner must call `setPermissionId()` to re-enable delegation.
|
|
211
|
+
/// @dev The `projectId` must fit within a `uint88` and the project must already exist.
|
|
206
212
|
/// @param projectId The ID of the project to transfer ownership to.
|
|
207
213
|
function transferOwnershipToProject(uint256 projectId) public virtual override {
|
|
208
214
|
_checkOwner();
|
|
@@ -240,7 +246,7 @@ abstract contract JBOwnableOverrides is Context, JBPermissioned, IJBOwnable {
|
|
|
240
246
|
emit PermissionIdChanged({newId: permissionId, caller: _msgSender()});
|
|
241
247
|
}
|
|
242
248
|
|
|
243
|
-
/// @notice
|
|
249
|
+
/// @notice Drop-in replacement for OpenZeppelin's `Ownable._transferOwnership(address)`.
|
|
244
250
|
/// @param newOwner The address that should receive ownership of this contract.
|
|
245
251
|
function _transferOwnership(address newOwner) internal virtual {
|
|
246
252
|
_transferOwnership({newOwner: newOwner, projectId: 0});
|
|
@@ -3,7 +3,9 @@ pragma solidity ^0.8.0;
|
|
|
3
3
|
|
|
4
4
|
import {IJBProjects} from "@bananapus/core-v6/src/interfaces/IJBProjects.sol";
|
|
5
5
|
|
|
6
|
-
/// @notice
|
|
6
|
+
/// @notice Interface for Juicebox-aware ownership. Supports two modes: address-based (a fixed EOA/contract owns the
|
|
7
|
+
/// contract) or project-based (whoever holds a specific Juicebox project's ERC-721 NFT is the owner). The owner can
|
|
8
|
+
/// delegate access to other addresses via `JBPermissions`.
|
|
7
9
|
interface IJBOwnable {
|
|
8
10
|
/// @notice Emitted when ownership is transferred to a new owner.
|
|
9
11
|
/// @param previousOwner The address of the previous owner.
|
|
@@ -16,14 +18,14 @@ interface IJBOwnable {
|
|
|
16
18
|
/// @param caller The address that changed the permission ID.
|
|
17
19
|
event PermissionIdChanged(uint8 newId, address caller);
|
|
18
20
|
|
|
19
|
-
/// @notice The contract
|
|
21
|
+
/// @notice The `JBProjects` ERC-721 contract used to resolve project-based ownership.
|
|
20
22
|
/// @return projects The `IJBProjects` contract.
|
|
21
23
|
function PROJECTS() external view returns (IJBProjects projects);
|
|
22
24
|
|
|
23
|
-
/// @notice
|
|
25
|
+
/// @notice The current ownership state — who owns this contract and how permission delegation is configured.
|
|
24
26
|
/// @return owner The owner address (used when `projectId` is 0).
|
|
25
|
-
/// @return projectId The
|
|
26
|
-
/// @return permissionId The permission ID
|
|
27
|
+
/// @return projectId The Juicebox project whose NFT holder is the owner (0 if address-based ownership).
|
|
28
|
+
/// @return permissionId The permission ID that delegates can use to act as owner via `JBPermissions`.
|
|
27
29
|
function jbOwner() external view returns (address owner, uint88 projectId, uint8 permissionId);
|
|
28
30
|
|
|
29
31
|
/// @notice Returns the current owner's address.
|
package/src/structs/JBOwner.sol
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
pragma solidity ^0.8.0;
|
|
3
3
|
|
|
4
|
-
/// @notice
|
|
5
|
-
/// @custom:member owner
|
|
6
|
-
/// @custom:member projectId
|
|
7
|
-
/// `owner`
|
|
8
|
-
/// @custom:member permissionId The permission ID
|
|
9
|
-
///
|
|
4
|
+
/// @notice Describes who owns a `JBOwnable` contract and how they can delegate access.
|
|
5
|
+
/// @custom:member owner The owner address — only used when `projectId` is 0 (address-based ownership mode).
|
|
6
|
+
/// @custom:member projectId If non-zero, the holder of this Juicebox project's ERC-721 NFT is the owner. When set,
|
|
7
|
+
/// the `owner` field is ignored and ownership resolves dynamically via `JBProjects.ownerOf(projectId)`.
|
|
8
|
+
/// @custom:member permissionId The permission ID that delegates can hold (via `JBPermissions`) to act as owner. Set
|
|
9
|
+
/// to 0 to disable delegation entirely — only the direct owner can call `onlyOwner` functions.
|
|
10
10
|
struct JBOwner {
|
|
11
11
|
address owner;
|
|
12
12
|
uint88 projectId;
|