@bananapus/ownable-v6 0.0.1
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/LICENSE +21 -0
- package/README.md +51 -0
- package/SKILLS.md +62 -0
- package/docs/book.css +13 -0
- package/docs/book.toml +12 -0
- package/docs/solidity.min.js +74 -0
- package/docs/src/README.md +131 -0
- package/docs/src/SUMMARY.md +9 -0
- package/docs/src/src/JBOwnable.sol/contract.JBOwnable.md +71 -0
- package/docs/src/src/JBOwnableOverrides.sol/abstract.JBOwnableOverrides.md +216 -0
- package/docs/src/src/README.md +7 -0
- package/docs/src/src/interfaces/IJBOwnable.sol/interface.IJBOwnable.md +67 -0
- package/docs/src/src/interfaces/README.md +4 -0
- package/docs/src/src/structs/JBOwner.sol/struct.JBOwner.md +23 -0
- package/docs/src/src/structs/README.md +4 -0
- package/foundry.toml +12 -0
- package/package.json +17 -0
- package/slither-ci.config.json +10 -0
- package/src/JBOwnable.sol +76 -0
- package/src/JBOwnableOverrides.sol +203 -0
- package/src/interfaces/IJBOwnable.sol +38 -0
- package/src/structs/JBOwner.sol +14 -0
- package/test/Ownable.t.sol +374 -0
- package/test/OwnableAttacks.t.sol +185 -0
- package/test/OwnableInvariantTests.sol +57 -0
- package/test/handlers/OwnableHandler.sol +78 -0
- package/test/mocks/MockOwnable.sol +45 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# IJBOwnable
|
|
2
|
+
[Git Source](https://github.com/Bananapus/nana-ownable/blob/a74b3181e75adaf0ee0c93cb00bcc5709ca8f314/src/interfaces/IJBOwnable.sol)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## Functions
|
|
6
|
+
### PROJECTS
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
```solidity
|
|
10
|
+
function PROJECTS() external view returns (IJBProjects);
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### jbOwner
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
```solidity
|
|
17
|
+
function jbOwner() external view returns (address owner, uint88 projectOwner, uint8 permissionId);
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### owner
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
```solidity
|
|
24
|
+
function owner() external view returns (address);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### renounceOwnership
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
```solidity
|
|
31
|
+
function renounceOwnership() external;
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### setPermissionId
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
```solidity
|
|
38
|
+
function setPermissionId(uint8 permissionId) external;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### transferOwnership
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
```solidity
|
|
45
|
+
function transferOwnership(address newOwner) external;
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### transferOwnershipToProject
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
```solidity
|
|
52
|
+
function transferOwnershipToProject(uint256 projectId) external;
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Events
|
|
56
|
+
### PermissionIdChanged
|
|
57
|
+
|
|
58
|
+
```solidity
|
|
59
|
+
event PermissionIdChanged(uint8 newId, address caller);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### OwnershipTransferred
|
|
63
|
+
|
|
64
|
+
```solidity
|
|
65
|
+
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner, address caller);
|
|
66
|
+
```
|
|
67
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# JBOwner
|
|
2
|
+
[Git Source](https://github.com/Bananapus/nana-ownable/blob/a74b3181e75adaf0ee0c93cb00bcc5709ca8f314/src/struct/JBOwner.sol)
|
|
3
|
+
|
|
4
|
+
Owner information for a given instance of `JBOwnableOverrides`.
|
|
5
|
+
|
|
6
|
+
**Notes:**
|
|
7
|
+
- member: owner If `projectId` is 0, this address has owner access.
|
|
8
|
+
|
|
9
|
+
- member: projectId The owner of the `JBProjects` ERC-721 with this ID has owner access. If this is 0, the
|
|
10
|
+
`owner` address has owner access.
|
|
11
|
+
|
|
12
|
+
- member: permissionId The permission ID which corresponds to owner access. See `JBPermissions` in `nana-core`
|
|
13
|
+
and `nana-permission-ids`.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
```solidity
|
|
17
|
+
struct JBOwner {
|
|
18
|
+
address owner;
|
|
19
|
+
uint88 projectId;
|
|
20
|
+
uint8 permissionId;
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
package/foundry.toml
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
[profile.default]
|
|
2
|
+
solc = '0.8.23'
|
|
3
|
+
evm_version = 'paris' # Required for L2s (Optimism, Arbitrum, etc.)
|
|
4
|
+
optimizer_runs = 1000000000
|
|
5
|
+
|
|
6
|
+
[fuzz]
|
|
7
|
+
runs = 4096
|
|
8
|
+
|
|
9
|
+
[fmt]
|
|
10
|
+
number_underscore = "thousands"
|
|
11
|
+
multiline_func_header = "all"
|
|
12
|
+
wrap_comments = true
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bananapus/ownable-v6",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/Bananapus/nana-ownable-v6"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@bananapus/core-v6": "^0.0.1",
|
|
11
|
+
"@openzeppelin/contracts": "^5.0.2"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"test": "forge test",
|
|
15
|
+
"coverage:integration": "forge coverage --match-path \"./src/*.sol\" --report lcov --report summary"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
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/)",
|
|
9
|
+
"legacy_ast": false
|
|
10
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Juicebox variation on OpenZeppelin Ownable
|
|
3
|
+
pragma solidity ^0.8.23;
|
|
4
|
+
|
|
5
|
+
import {IJBProjects} from "@bananapus/core-v6/src/interfaces/IJBProjects.sol";
|
|
6
|
+
import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
|
|
7
|
+
|
|
8
|
+
import {JBOwnableOverrides} from "./JBOwnableOverrides.sol";
|
|
9
|
+
|
|
10
|
+
/// @notice A function restricted by `JBOwnable` can only be called by a Juicebox project's owner, a specified owner
|
|
11
|
+
/// address (if set), or addresses with permission from the owner.
|
|
12
|
+
/// @dev A function with the `onlyOwner` modifier from `JBOwnable` can only be called by addresses with owner access
|
|
13
|
+
/// based on a `JBOwner` struct:
|
|
14
|
+
/// 1. If `JBOwner.projectId` isn't zero, the address holding the `JBProjects` NFT with the `JBOwner.projectId` ID is
|
|
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.
|
|
20
|
+
contract JBOwnable is JBOwnableOverrides {
|
|
21
|
+
//*********************************************************************//
|
|
22
|
+
// -------------------------- constructor ---------------------------- //
|
|
23
|
+
//*********************************************************************//
|
|
24
|
+
|
|
25
|
+
/// @dev To make a Juicebox project's owner this contract's owner, pass that project's ID as the
|
|
26
|
+
/// `initialProjectIdOwner`.
|
|
27
|
+
/// @dev To make a specific address the owner, pass that address as the `initialOwner` and `0` as the
|
|
28
|
+
/// `initialProjectIdOwner`.
|
|
29
|
+
/// @dev The owner can give other addresses owner access through the `permissions` contract.
|
|
30
|
+
/// @param permissions A contract storing permissions.
|
|
31
|
+
/// @param projects Mints ERC-721s that represent project ownership and transfers.
|
|
32
|
+
/// @param initialOwner An address with owner access (until ownership is transferred).
|
|
33
|
+
/// @param initialProjectIdOwner The ID of the Juicebox project whose owner has owner access (until ownership is
|
|
34
|
+
/// transferred).
|
|
35
|
+
constructor(
|
|
36
|
+
IJBPermissions permissions,
|
|
37
|
+
IJBProjects projects,
|
|
38
|
+
address initialOwner,
|
|
39
|
+
uint88 initialProjectIdOwner
|
|
40
|
+
)
|
|
41
|
+
JBOwnableOverrides(permissions, projects, initialOwner, initialProjectIdOwner)
|
|
42
|
+
{}
|
|
43
|
+
|
|
44
|
+
//*********************************************************************//
|
|
45
|
+
// --------------------------- modifiers ----------------------------- //
|
|
46
|
+
//*********************************************************************//
|
|
47
|
+
|
|
48
|
+
/// @notice Reverts if called by an address without owner access.
|
|
49
|
+
modifier onlyOwner() virtual {
|
|
50
|
+
_checkOwner();
|
|
51
|
+
_;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//*********************************************************************//
|
|
55
|
+
// ------------------------ internal functions ----------------------- //
|
|
56
|
+
//*********************************************************************//
|
|
57
|
+
|
|
58
|
+
/// @notice Either `newOwner` or `newProjectId` is non-zero or both are zero. But they can never both be non-zero.
|
|
59
|
+
/// @dev This function exists because some contracts need to deploy contracts for a project before the project's NFT
|
|
60
|
+
/// has been minted, so the transfer event resolves the project's current owner at emission time.
|
|
61
|
+
function _emitTransferEvent(
|
|
62
|
+
address previousOwner,
|
|
63
|
+
address newOwner,
|
|
64
|
+
uint88 newProjectId
|
|
65
|
+
)
|
|
66
|
+
internal
|
|
67
|
+
virtual
|
|
68
|
+
override
|
|
69
|
+
{
|
|
70
|
+
emit OwnershipTransferred({
|
|
71
|
+
previousOwner: previousOwner,
|
|
72
|
+
newOwner: newProjectId == 0 ? newOwner : PROJECTS.ownerOf(newProjectId),
|
|
73
|
+
caller: msg.sender
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Juicebox variation on OpenZeppelin Ownable
|
|
3
|
+
pragma solidity ^0.8.23;
|
|
4
|
+
|
|
5
|
+
import {JBPermissioned} from "@bananapus/core-v6/src/abstract/JBPermissioned.sol";
|
|
6
|
+
import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
|
|
7
|
+
import {IJBProjects} from "@bananapus/core-v6/src/interfaces/IJBProjects.sol";
|
|
8
|
+
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
|
|
9
|
+
|
|
10
|
+
import {IJBOwnable} from "./interfaces/IJBOwnable.sol";
|
|
11
|
+
import {JBOwner} from "./structs/JBOwner.sol";
|
|
12
|
+
|
|
13
|
+
/// @notice An abstract base for `JBOwnable`, which restricts functions so they can only be called by a Juicebox
|
|
14
|
+
/// project's owner or a specific owner address. The owner can give access permission to other addresses with
|
|
15
|
+
/// `JBPermissions`.
|
|
16
|
+
abstract contract JBOwnableOverrides is Context, JBPermissioned, IJBOwnable {
|
|
17
|
+
//*********************************************************************//
|
|
18
|
+
// --------------------------- custom errors --------------------------//
|
|
19
|
+
//*********************************************************************//
|
|
20
|
+
|
|
21
|
+
error JBOwnableOverrides_InvalidNewOwner();
|
|
22
|
+
error JBOwnableOverrides_ProjectDoesNotExist();
|
|
23
|
+
|
|
24
|
+
//*********************************************************************//
|
|
25
|
+
// ---------------- public immutable stored properties --------------- //
|
|
26
|
+
//*********************************************************************//
|
|
27
|
+
|
|
28
|
+
/// @notice Mints ERC-721s that represent project ownership and transfers.
|
|
29
|
+
IJBProjects public immutable override PROJECTS;
|
|
30
|
+
|
|
31
|
+
//*********************************************************************//
|
|
32
|
+
// --------------------- public stored properties -------------------- //
|
|
33
|
+
//*********************************************************************//
|
|
34
|
+
|
|
35
|
+
/// @notice This contract's owner information.
|
|
36
|
+
JBOwner public override jbOwner;
|
|
37
|
+
|
|
38
|
+
//*********************************************************************//
|
|
39
|
+
// -------------------------- constructor ---------------------------- //
|
|
40
|
+
//*********************************************************************//
|
|
41
|
+
|
|
42
|
+
/// @dev To restrict access to a Juicebox project's owner, pass that project's ID as the `initialProjectIdOwner` and
|
|
43
|
+
/// the zero address as the `initialOwner`.
|
|
44
|
+
/// To restrict access to a specific address, pass that address as the `initialOwner` and `0` as the
|
|
45
|
+
/// `initialProjectIdOwner`.
|
|
46
|
+
/// @dev The owner can give owner access to other addresses through the `permissions` contract.
|
|
47
|
+
/// @param permissions A contract storing permissions.
|
|
48
|
+
/// @param projects Mints ERC-721s that represent project ownership and transfers.
|
|
49
|
+
/// @param initialOwner The owner if the `initialProjectIdOwner` is 0 (until ownership is transferred).
|
|
50
|
+
/// @param initialProjectIdOwner The ID of the Juicebox project whose owner is this contract's owner (until
|
|
51
|
+
/// ownership is transferred).
|
|
52
|
+
constructor(
|
|
53
|
+
IJBPermissions permissions,
|
|
54
|
+
IJBProjects projects,
|
|
55
|
+
address initialOwner,
|
|
56
|
+
uint88 initialProjectIdOwner
|
|
57
|
+
)
|
|
58
|
+
JBPermissioned(permissions)
|
|
59
|
+
{
|
|
60
|
+
PROJECTS = projects;
|
|
61
|
+
|
|
62
|
+
// We force the inheriting contract to set an owner, as there is a low chance someone will use `JBOwnable` to
|
|
63
|
+
// create an unowned contract.
|
|
64
|
+
// It's more likely both were accidentally set to `0`. If you really want an unowned contract, set the owner to
|
|
65
|
+
// an address and call `renounceOwnership()` in the constructor body.
|
|
66
|
+
if (initialProjectIdOwner == 0 && initialOwner == address(0)) {
|
|
67
|
+
revert JBOwnableOverrides_InvalidNewOwner();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
_transferOwnership(initialOwner, initialProjectIdOwner);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//*********************************************************************//
|
|
74
|
+
// -------------------------- public views --------------------------- //
|
|
75
|
+
//*********************************************************************//
|
|
76
|
+
|
|
77
|
+
/// @notice Returns the owner's address based on this contract's `JBOwner`.
|
|
78
|
+
function owner() public view virtual returns (address) {
|
|
79
|
+
JBOwner memory ownerInfo = jbOwner;
|
|
80
|
+
|
|
81
|
+
if (ownerInfo.projectId == 0) {
|
|
82
|
+
return ownerInfo.owner;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return PROJECTS.ownerOf(ownerInfo.projectId);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
//*********************************************************************//
|
|
89
|
+
// -------------------------- internal views ------------------------- //
|
|
90
|
+
//*********************************************************************//
|
|
91
|
+
|
|
92
|
+
/// @notice Reverts if the sender is not the owner.
|
|
93
|
+
function _checkOwner() internal view virtual {
|
|
94
|
+
JBOwner memory ownerInfo = jbOwner;
|
|
95
|
+
|
|
96
|
+
_requirePermissionFrom({
|
|
97
|
+
account: ownerInfo.projectId == 0 ? ownerInfo.owner : PROJECTS.ownerOf(ownerInfo.projectId),
|
|
98
|
+
projectId: ownerInfo.projectId,
|
|
99
|
+
permissionId: ownerInfo.permissionId
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
//*********************************************************************//
|
|
104
|
+
// ---------------------- public transactions ------------------------ //
|
|
105
|
+
//*********************************************************************//
|
|
106
|
+
|
|
107
|
+
/// @notice Gives up ownership of this contract, making it impossible to call `onlyOwner` and `_checkOwner`
|
|
108
|
+
/// functions.
|
|
109
|
+
/// @dev This can only be called by the current owner.
|
|
110
|
+
function renounceOwnership() public virtual override {
|
|
111
|
+
_checkOwner();
|
|
112
|
+
_transferOwnership(address(0), 0);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// @notice Sets the permission ID the owner can use to give other addresses owner access.
|
|
116
|
+
/// @dev This can only be called by the current owner.
|
|
117
|
+
/// @param permissionId The permission ID to use for `onlyOwner`.
|
|
118
|
+
function setPermissionId(uint8 permissionId) public virtual override {
|
|
119
|
+
_checkOwner();
|
|
120
|
+
_setPermissionId(permissionId);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/// @notice Transfers ownership of this contract to a new address (the `newOwner`). Can only be called by the
|
|
124
|
+
/// current owner.
|
|
125
|
+
/// @dev The `permissionId` is reset to 0 on transfer to prevent permission clashes for the new owner.
|
|
126
|
+
/// The new owner must explicitly call `setPermissionId()` to configure owner-level permission delegation.
|
|
127
|
+
/// @param newOwner The address to transfer ownership to.
|
|
128
|
+
function transferOwnership(address newOwner) public virtual override {
|
|
129
|
+
_checkOwner();
|
|
130
|
+
if (newOwner == address(0)) {
|
|
131
|
+
revert JBOwnableOverrides_InvalidNewOwner();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
_transferOwnership(newOwner, 0);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/// @notice Transfer ownership of this contract to a new Juicebox project.
|
|
138
|
+
/// @dev The `permissionId` is reset to 0 on transfer to prevent permission clashes for the new project owner.
|
|
139
|
+
/// The new owner must explicitly call `setPermissionId()` to configure owner-level permission delegation.
|
|
140
|
+
/// @dev The `projectId` must fit within a `uint88`.
|
|
141
|
+
/// @param projectId The ID of the project to transfer ownership to.
|
|
142
|
+
function transferOwnershipToProject(uint256 projectId) public virtual override {
|
|
143
|
+
_checkOwner();
|
|
144
|
+
if (projectId == 0 || projectId > type(uint88).max) {
|
|
145
|
+
revert JBOwnableOverrides_InvalidNewOwner();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Make sure the project exists to prevent permanent loss of contract control.
|
|
149
|
+
if (projectId > PROJECTS.count()) {
|
|
150
|
+
revert JBOwnableOverrides_ProjectDoesNotExist();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
_transferOwnership(address(0), uint88(projectId));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
//*********************************************************************//
|
|
157
|
+
// ------------------------ internal functions ----------------------- //
|
|
158
|
+
//*********************************************************************//
|
|
159
|
+
|
|
160
|
+
/// @notice Either `newOwner` or `newProjectId` is non-zero or both are zero. But they can never both be non-zero.
|
|
161
|
+
/// @dev This function exists because some contracts need to deploy contracts for a project before the project's NFT
|
|
162
|
+
/// has been minted, so the transfer event resolves the project's current owner at emission time.
|
|
163
|
+
/// @param previousOwner The address of the previous owner.
|
|
164
|
+
/// @param newOwner The address of the new owner (zero if transferring to a project).
|
|
165
|
+
/// @param newProjectId The ID of the new owning project (zero if transferring to an address).
|
|
166
|
+
function _emitTransferEvent(address previousOwner, address newOwner, uint88 newProjectId) internal virtual;
|
|
167
|
+
|
|
168
|
+
/// @notice Sets the permission ID the owner can use to give other addresses owner access.
|
|
169
|
+
/// @dev Internal function without access restriction.
|
|
170
|
+
/// @param permissionId The permission ID to use for `onlyOwner`.
|
|
171
|
+
function _setPermissionId(uint8 permissionId) internal virtual {
|
|
172
|
+
jbOwner.permissionId = permissionId;
|
|
173
|
+
emit PermissionIdChanged({newId: permissionId, caller: msg.sender});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/// @notice Helper to allow for drop-in replacement of OpenZeppelin `Ownable`.
|
|
177
|
+
/// @param newOwner The address that should receive ownership of this contract.
|
|
178
|
+
function _transferOwnership(address newOwner) internal virtual {
|
|
179
|
+
_transferOwnership(newOwner, 0);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/// @notice Transfers this contract's ownership to an address (`newOwner`) OR a Juicebox project (`projectId`).
|
|
183
|
+
/// @dev Updates this contract's `JBOwner` owner information and resets the `JBOwner.permissionId`.
|
|
184
|
+
/// @dev If both `newOwner` and `projectId` are set, this will revert.
|
|
185
|
+
/// @dev Internal function without access restriction.
|
|
186
|
+
/// @param newOwner The address that should become this contract's owner.
|
|
187
|
+
/// @param projectId The ID of the project whose owner should become this contract's owner.
|
|
188
|
+
function _transferOwnership(address newOwner, uint88 projectId) internal virtual {
|
|
189
|
+
// Can't set both a new owner and a new project ID.
|
|
190
|
+
if (projectId != 0 && newOwner != address(0)) {
|
|
191
|
+
revert JBOwnableOverrides_InvalidNewOwner();
|
|
192
|
+
}
|
|
193
|
+
// Load the owner information from storage.
|
|
194
|
+
JBOwner memory ownerInfo = jbOwner;
|
|
195
|
+
// Get the address of the old owner.
|
|
196
|
+
address oldOwner = ownerInfo.projectId == 0 ? ownerInfo.owner : PROJECTS.ownerOf(ownerInfo.projectId);
|
|
197
|
+
// Update the stored owner information to the new owner and reset the `permissionId`.
|
|
198
|
+
// This is to prevent permissions clashes for the new user/owner.
|
|
199
|
+
jbOwner = JBOwner({owner: newOwner, projectId: projectId, permissionId: 0});
|
|
200
|
+
// Emit a transfer event with the new owner's address.
|
|
201
|
+
_emitTransferEvent(oldOwner, newOwner, projectId);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {IJBProjects} from "@bananapus/core-v6/src/interfaces/IJBProjects.sol";
|
|
5
|
+
|
|
6
|
+
interface IJBOwnable {
|
|
7
|
+
event PermissionIdChanged(uint8 newId, address caller);
|
|
8
|
+
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner, address caller);
|
|
9
|
+
|
|
10
|
+
/// @notice The contract that mints ERC-721s representing project ownership.
|
|
11
|
+
/// @return projects The `IJBProjects` contract.
|
|
12
|
+
function PROJECTS() external view returns (IJBProjects projects);
|
|
13
|
+
|
|
14
|
+
/// @notice This contract's owner information.
|
|
15
|
+
/// @return owner The owner address (used when `projectId` is 0).
|
|
16
|
+
/// @return projectId The ID of the Juicebox project whose owner is this contract's owner (0 if not project-owned).
|
|
17
|
+
/// @return permissionId The permission ID the owner can use to grant other addresses owner access.
|
|
18
|
+
function jbOwner() external view returns (address owner, uint88 projectId, uint8 permissionId);
|
|
19
|
+
|
|
20
|
+
/// @notice Returns the current owner's address.
|
|
21
|
+
/// @return owner The address of the current owner.
|
|
22
|
+
function owner() external view returns (address owner);
|
|
23
|
+
|
|
24
|
+
/// @notice Gives up ownership, making it impossible to call `onlyOwner` functions.
|
|
25
|
+
function renounceOwnership() external;
|
|
26
|
+
|
|
27
|
+
/// @notice Sets the permission ID the owner can use to give other addresses owner access.
|
|
28
|
+
/// @param permissionId The permission ID to use for `onlyOwner`.
|
|
29
|
+
function setPermissionId(uint8 permissionId) external;
|
|
30
|
+
|
|
31
|
+
/// @notice Transfers ownership of this contract to a new address.
|
|
32
|
+
/// @param newOwner The address to transfer ownership to.
|
|
33
|
+
function transferOwnership(address newOwner) external;
|
|
34
|
+
|
|
35
|
+
/// @notice Transfers ownership of this contract to a Juicebox project.
|
|
36
|
+
/// @param projectId The ID of the project to transfer ownership to.
|
|
37
|
+
function transferOwnershipToProject(uint256 projectId) external;
|
|
38
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
/// @notice Owner information for a given instance of `JBOwnableOverrides`.
|
|
5
|
+
/// @custom:member owner If `projectId` is 0, this address has owner access.
|
|
6
|
+
/// @custom:member projectId The owner of the `JBProjects` ERC-721 with this ID has owner access. If this is 0, the
|
|
7
|
+
/// `owner` address has owner access.
|
|
8
|
+
/// @custom:member permissionId The permission ID which corresponds to owner access. See `JBPermissions` in `nana-core`
|
|
9
|
+
/// and `nana-permission-ids`.
|
|
10
|
+
struct JBOwner {
|
|
11
|
+
address owner;
|
|
12
|
+
uint88 projectId;
|
|
13
|
+
uint8 permissionId;
|
|
14
|
+
}
|