@bananapus/core-v6 0.0.9 → 0.0.10

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.
Files changed (39) hide show
  1. package/foundry.toml +0 -1
  2. package/package.json +2 -2
  3. package/src/JBChainlinkV3PriceFeed.sol +1 -5
  4. package/src/JBChainlinkV3SequencerPriceFeed.sol +1 -1
  5. package/src/JBController.sol +277 -277
  6. package/src/JBDeadline.sol +1 -1
  7. package/src/JBDirectory.sol +93 -93
  8. package/src/JBERC20.sol +43 -39
  9. package/src/JBFeelessAddresses.sol +12 -12
  10. package/src/JBFundAccessLimits.sol +82 -82
  11. package/src/JBMultiTerminal.sol +313 -313
  12. package/src/JBPermissions.sol +104 -100
  13. package/src/JBPrices.sol +68 -68
  14. package/src/JBProjects.sol +31 -31
  15. package/src/JBRulesets.sol +422 -422
  16. package/src/JBSplits.sol +116 -116
  17. package/src/JBTerminalStore.sol +651 -651
  18. package/src/JBTokens.sol +41 -41
  19. package/src/interfaces/IJBCashOutTerminal.sol +25 -7
  20. package/src/interfaces/IJBController.sol +78 -3
  21. package/src/interfaces/IJBDirectory.sol +25 -0
  22. package/src/interfaces/IJBFeeTerminal.sol +31 -0
  23. package/src/interfaces/IJBFeelessAddresses.sol +4 -0
  24. package/src/interfaces/IJBFundAccessLimits.sol +5 -0
  25. package/src/interfaces/IJBMigratable.sol +12 -8
  26. package/src/interfaces/IJBPayoutTerminal.sol +56 -9
  27. package/src/interfaces/IJBPermissions.sol +14 -7
  28. package/src/interfaces/IJBPermitTerminal.sol +4 -0
  29. package/src/interfaces/IJBPrices.sol +6 -0
  30. package/src/interfaces/IJBProjects.sol +8 -0
  31. package/src/interfaces/IJBRulesetApprovalHook.sol +1 -1
  32. package/src/interfaces/IJBRulesetDataHook.sol +23 -23
  33. package/src/interfaces/IJBRulesets.sol +54 -33
  34. package/src/interfaces/IJBSplits.sol +6 -0
  35. package/src/interfaces/IJBTerminal.sol +36 -0
  36. package/src/interfaces/IJBTerminalStore.sol +63 -63
  37. package/src/interfaces/IJBToken.sol +5 -5
  38. package/src/interfaces/IJBTokens.sol +50 -8
  39. package/test/TestDurationUnderflow.sol +3 -2
@@ -1,8 +1,8 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
- import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
5
4
  import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
5
+ import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
6
6
 
7
7
  import {IJBPermissions} from "./interfaces/IJBPermissions.sol";
8
8
  import {JBPermissionsData} from "./structs/JBPermissionsData.sol";
@@ -52,60 +52,63 @@ contract JBPermissions is ERC2771Context, IJBPermissions {
52
52
  constructor(address trustedForwarder) ERC2771Context(trustedForwarder) {}
53
53
 
54
54
  //*********************************************************************//
55
- // -------------------------- public views --------------------------- //
55
+ // ---------------------- external transactions ---------------------- //
56
56
  //*********************************************************************//
57
57
 
58
- /// @notice Check if an operator has a specific permission for a specific address and project ID.
59
- /// @param operator The operator to check.
60
- /// @param account The account being operated on behalf of.
61
- /// @param projectId The project ID that the operator has permission to operate under. 0 represents all projects.
62
- /// @param permissionId The permission ID to check for.
63
- /// @param includeRoot A flag indicating if the return value should default to true if the operator has the ROOT
64
- /// permission.
65
- /// @param includeWildcardProjectId A flag indicating if the return value should return true if the operator has the
66
- /// specified permission on the wildcard project ID.
67
- /// @return A flag indicating whether the operator has the specified permission.
68
- function hasPermission(
69
- address operator,
70
- address account,
71
- uint256 projectId,
72
- uint256 permissionId,
73
- bool includeRoot,
74
- bool includeWildcardProjectId
75
- )
76
- public
77
- view
78
- override
79
- returns (bool)
80
- {
81
- // Indexes above 255 don't exist
82
- if (permissionId > 255) revert JBPermissions_PermissionIdOutOfBounds(permissionId);
58
+ /// @notice Sets permissions for an operator.
59
+ /// @dev Only an address can give permissions to or revoke permissions from its operators.
60
+ /// @param account The account setting its operators' permissions.
61
+ /// @param permissionsData The data which specifies the permissions the operator is being given.
62
+ function setPermissionsFor(address account, JBPermissionsData calldata permissionsData) external override {
63
+ // Pack the permission IDs into a uint256.
64
+ uint256 packed = _packedPermissions(permissionsData.permissionIds);
83
65
 
84
- // If the ROOT permission is set and should be included, return true.
66
+ // Make sure the 0 permission is not set.
67
+ if (_includesPermission({permissions: packed, permissionId: 0})) revert JBPermissions_NoZeroPermission();
68
+
69
+ // Cache the sender.
70
+ address msgSender = _msgSender();
71
+
72
+ // Enforce permissions. ROOT operators are allowed to set permissions so long as they are not setting another
73
+ // ROOT permission or setting permissions for a wildcard project ID.
85
74
  if (
86
- includeRoot
87
- && (_includesPermission({
88
- permissions: permissionsOf[operator][account][projectId], permissionId: JBPermissionIds.ROOT
89
- })
90
- || (includeWildcardProjectId
91
- && _includesPermission({
92
- permissions: permissionsOf[operator][account][WILDCARD_PROJECT_ID],
93
- permissionId: JBPermissionIds.ROOT
94
- })))
75
+ msgSender != account
76
+ && (_includesPermission({permissions: packed, permissionId: JBPermissionIds.ROOT})
77
+ || permissionsData.projectId == WILDCARD_PROJECT_ID
78
+ || !hasPermission({
79
+ operator: msgSender,
80
+ account: account,
81
+ projectId: permissionsData.projectId,
82
+ permissionId: JBPermissionIds.ROOT,
83
+ includeRoot: true,
84
+ includeWildcardProjectId: true
85
+ }))
95
86
  ) {
96
- return true;
87
+ revert JBPermissions_Unauthorized({
88
+ account: account,
89
+ operator: msgSender,
90
+ projectId: permissionsData.projectId,
91
+ permissionId: JBPermissionIds.ROOT
92
+ });
97
93
  }
98
94
 
99
- // Otherwise return the t/f flag of the specified id.
100
- return _includesPermission({
101
- permissions: permissionsOf[operator][account][projectId], permissionId: permissionId
102
- })
103
- || (includeWildcardProjectId
104
- && _includesPermission({
105
- permissions: permissionsOf[operator][account][WILDCARD_PROJECT_ID], permissionId: permissionId
106
- }));
95
+ // Store the new value.
96
+ permissionsOf[permissionsData.operator][account][permissionsData.projectId] = packed;
97
+
98
+ emit OperatorPermissionsSet({
99
+ operator: permissionsData.operator,
100
+ account: account,
101
+ projectId: permissionsData.projectId,
102
+ permissionIds: permissionsData.permissionIds,
103
+ packed: packed,
104
+ caller: msgSender
105
+ });
107
106
  }
108
107
 
108
+ //*********************************************************************//
109
+ // ------------------------- external views -------------------------- //
110
+ //*********************************************************************//
111
+
109
112
  /// @notice Check if an operator has all of the specified permissions for a specific address and project ID.
110
113
  /// @param operator The operator to check.
111
114
  /// @param account The account being operated on behalf of.
@@ -171,6 +174,61 @@ contract JBPermissions is ERC2771Context, IJBPermissions {
171
174
  return true;
172
175
  }
173
176
 
177
+ //*********************************************************************//
178
+ // -------------------------- public views --------------------------- //
179
+ //*********************************************************************//
180
+
181
+ /// @notice Check if an operator has a specific permission for a specific address and project ID.
182
+ /// @param operator The operator to check.
183
+ /// @param account The account being operated on behalf of.
184
+ /// @param projectId The project ID that the operator has permission to operate under. 0 represents all projects.
185
+ /// @param permissionId The permission ID to check for.
186
+ /// @param includeRoot A flag indicating if the return value should default to true if the operator has the ROOT
187
+ /// permission.
188
+ /// @param includeWildcardProjectId A flag indicating if the return value should return true if the operator has the
189
+ /// specified permission on the wildcard project ID.
190
+ /// @return A flag indicating whether the operator has the specified permission.
191
+ function hasPermission(
192
+ address operator,
193
+ address account,
194
+ uint256 projectId,
195
+ uint256 permissionId,
196
+ bool includeRoot,
197
+ bool includeWildcardProjectId
198
+ )
199
+ public
200
+ view
201
+ override
202
+ returns (bool)
203
+ {
204
+ // Indexes above 255 don't exist
205
+ if (permissionId > 255) revert JBPermissions_PermissionIdOutOfBounds(permissionId);
206
+
207
+ // If the ROOT permission is set and should be included, return true.
208
+ if (
209
+ includeRoot
210
+ && (_includesPermission({
211
+ permissions: permissionsOf[operator][account][projectId], permissionId: JBPermissionIds.ROOT
212
+ })
213
+ || (includeWildcardProjectId
214
+ && _includesPermission({
215
+ permissions: permissionsOf[operator][account][WILDCARD_PROJECT_ID],
216
+ permissionId: JBPermissionIds.ROOT
217
+ })))
218
+ ) {
219
+ return true;
220
+ }
221
+
222
+ // Otherwise return the t/f flag of the specified id.
223
+ return _includesPermission({
224
+ permissions: permissionsOf[operator][account][projectId], permissionId: permissionId
225
+ })
226
+ || (includeWildcardProjectId
227
+ && _includesPermission({
228
+ permissions: permissionsOf[operator][account][WILDCARD_PROJECT_ID], permissionId: permissionId
229
+ }));
230
+ }
231
+
174
232
  //*********************************************************************//
175
233
  // -------------------------- internal views ------------------------- //
176
234
  //*********************************************************************//
@@ -195,58 +253,4 @@ contract JBPermissions is ERC2771Context, IJBPermissions {
195
253
  packed |= 1 << permissionId;
196
254
  }
197
255
  }
198
-
199
- //*********************************************************************//
200
- // ---------------------- external transactions ---------------------- //
201
- //*********************************************************************//
202
-
203
- /// @notice Sets permissions for an operator.
204
- /// @dev Only an address can give permissions to or revoke permissions from its operators.
205
- /// @param account The account setting its operators' permissions.
206
- /// @param permissionsData The data which specifies the permissions the operator is being given.
207
- function setPermissionsFor(address account, JBPermissionsData calldata permissionsData) external override {
208
- // Pack the permission IDs into a uint256.
209
- uint256 packed = _packedPermissions(permissionsData.permissionIds);
210
-
211
- // Make sure the 0 permission is not set.
212
- if (_includesPermission({permissions: packed, permissionId: 0})) revert JBPermissions_NoZeroPermission();
213
-
214
- // Cache the sender.
215
- address msgSender = _msgSender();
216
-
217
- // Enforce permissions. ROOT operators are allowed to set permissions so long as they are not setting another
218
- // ROOT permission or setting permissions for a wildcard project ID.
219
- if (
220
- msgSender != account
221
- && (_includesPermission({permissions: packed, permissionId: JBPermissionIds.ROOT})
222
- || permissionsData.projectId == WILDCARD_PROJECT_ID
223
- || !hasPermission({
224
- operator: msgSender,
225
- account: account,
226
- projectId: permissionsData.projectId,
227
- permissionId: JBPermissionIds.ROOT,
228
- includeRoot: true,
229
- includeWildcardProjectId: true
230
- }))
231
- ) {
232
- revert JBPermissions_Unauthorized({
233
- account: account,
234
- operator: msgSender,
235
- projectId: permissionsData.projectId,
236
- permissionId: JBPermissionIds.ROOT
237
- });
238
- }
239
-
240
- // Store the new value.
241
- permissionsOf[permissionsData.operator][account][permissionsData.projectId] = packed;
242
-
243
- emit OperatorPermissionsSet({
244
- operator: permissionsData.operator,
245
- account: account,
246
- projectId: permissionsData.projectId,
247
- permissionIds: permissionsData.permissionIds,
248
- packed: packed,
249
- caller: msgSender
250
- });
251
- }
252
256
  }
package/src/JBPrices.sol CHANGED
@@ -1,8 +1,8 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
- import {ERC2771Context, Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
5
4
  import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
5
+ import {ERC2771Context, Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
6
6
  import {mulDiv} from "@prb/math/src/Common.sol";
7
7
 
8
8
  import {JBControlled} from "./abstract/JBControlled.sol";
@@ -79,6 +79,73 @@ contract JBPrices is JBControlled, JBPermissioned, ERC2771Context, Ownable, IJBP
79
79
  PROJECTS = projects;
80
80
  }
81
81
 
82
+ //*********************************************************************//
83
+ // ---------------------- external transactions ---------------------- //
84
+ //*********************************************************************//
85
+
86
+ /// @notice Add a price feed for the `unitCurrency`, priced in terms of the `pricingCurrency`.
87
+ /// @dev Price feeds can only be added, not modified or removed. Once a feed is set for a currency pair (in either
88
+ /// direction), it is permanent for that project ID. Recovery from a misconfigured feed requires deploying a new
89
+ /// JBPrices contract.
90
+ /// @dev This contract's owner can add protocol-wide default price feed by passing a `projectId` of 0.
91
+ /// @param projectId The ID of the project to add a feed for. If `projectId` is 0, add a protocol-wide default price
92
+ /// feed.
93
+ /// @param pricingCurrency The currency the feed's output price is in terms of.
94
+ /// @param unitCurrency The currency being priced by the feed.
95
+ /// @param feed The address of the price feed to add.
96
+ function addPriceFeedFor(
97
+ uint256 projectId,
98
+ uint256 pricingCurrency,
99
+ uint256 unitCurrency,
100
+ IJBPriceFeed feed
101
+ )
102
+ external
103
+ override
104
+ {
105
+ // Ensure default price feeds can only be set by this contract's owner, and that other `projectId`s can only be
106
+ // set by the controller
107
+ projectId == DEFAULT_PROJECT_ID ? _checkOwner() : _onlyControllerOf(projectId);
108
+
109
+ // Make sure the pricing currency isn't 0.
110
+ if (pricingCurrency == 0) revert JBPrices_ZeroPricingCurrency();
111
+
112
+ // Make sure the unit currency isn't 0.
113
+ if (unitCurrency == 0) revert JBPrices_ZeroUnitCurrency();
114
+
115
+ // Make sure there isn't already a default price feed for the pair or its inverse.
116
+ if (
117
+ priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
118
+ || priceFeedFor[DEFAULT_PROJECT_ID][unitCurrency][pricingCurrency] != IJBPriceFeed(address(0))
119
+ ) {
120
+ revert JBPrices_PriceFeedAlreadyExists(priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency]
121
+ != IJBPriceFeed(address(0))
122
+ ? priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency]
123
+ : priceFeedFor[DEFAULT_PROJECT_ID][unitCurrency][pricingCurrency]);
124
+ }
125
+
126
+ // Make sure this project doesn't already have a price feed for the pair or its inverse.
127
+ if (
128
+ priceFeedFor[projectId][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
129
+ || priceFeedFor[projectId][unitCurrency][pricingCurrency] != IJBPriceFeed(address(0))
130
+ ) {
131
+ revert JBPrices_PriceFeedAlreadyExists(priceFeedFor[projectId][pricingCurrency][unitCurrency]
132
+ != IJBPriceFeed(address(0))
133
+ ? priceFeedFor[projectId][pricingCurrency][unitCurrency]
134
+ : priceFeedFor[projectId][unitCurrency][pricingCurrency]);
135
+ }
136
+
137
+ // Store the feed.
138
+ priceFeedFor[projectId][pricingCurrency][unitCurrency] = feed;
139
+
140
+ emit AddPriceFeed({
141
+ projectId: projectId,
142
+ pricingCurrency: pricingCurrency,
143
+ unitCurrency: unitCurrency,
144
+ feed: feed,
145
+ caller: _msgSender()
146
+ });
147
+ }
148
+
82
149
  //*********************************************************************//
83
150
  // -------------------------- public views --------------------------- //
84
151
  //*********************************************************************//
@@ -157,71 +224,4 @@ contract JBPrices is JBControlled, JBPermissioned, ERC2771Context, Ownable, IJBP
157
224
  function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
158
225
  return ERC2771Context._msgSender();
159
226
  }
160
-
161
- //*********************************************************************//
162
- // ---------------------- external transactions ---------------------- //
163
- //*********************************************************************//
164
-
165
- /// @notice Add a price feed for the `unitCurrency`, priced in terms of the `pricingCurrency`.
166
- /// @dev Price feeds can only be added, not modified or removed. Once a feed is set for a currency pair (in either
167
- /// direction), it is permanent for that project ID. Recovery from a misconfigured feed requires deploying a new
168
- /// JBPrices contract.
169
- /// @dev This contract's owner can add protocol-wide default price feed by passing a `projectId` of 0.
170
- /// @param projectId The ID of the project to add a feed for. If `projectId` is 0, add a protocol-wide default price
171
- /// feed.
172
- /// @param pricingCurrency The currency the feed's output price is in terms of.
173
- /// @param unitCurrency The currency being priced by the feed.
174
- /// @param feed The address of the price feed to add.
175
- function addPriceFeedFor(
176
- uint256 projectId,
177
- uint256 pricingCurrency,
178
- uint256 unitCurrency,
179
- IJBPriceFeed feed
180
- )
181
- external
182
- override
183
- {
184
- // Ensure default price feeds can only be set by this contract's owner, and that other `projectId`s can only be
185
- // set by the controller
186
- projectId == DEFAULT_PROJECT_ID ? _checkOwner() : _onlyControllerOf(projectId);
187
-
188
- // Make sure the pricing currency isn't 0.
189
- if (pricingCurrency == 0) revert JBPrices_ZeroPricingCurrency();
190
-
191
- // Make sure the unit currency isn't 0.
192
- if (unitCurrency == 0) revert JBPrices_ZeroUnitCurrency();
193
-
194
- // Make sure there isn't already a default price feed for the pair or its inverse.
195
- if (
196
- priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
197
- || priceFeedFor[DEFAULT_PROJECT_ID][unitCurrency][pricingCurrency] != IJBPriceFeed(address(0))
198
- ) {
199
- revert JBPrices_PriceFeedAlreadyExists(priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency]
200
- != IJBPriceFeed(address(0))
201
- ? priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency]
202
- : priceFeedFor[DEFAULT_PROJECT_ID][unitCurrency][pricingCurrency]);
203
- }
204
-
205
- // Make sure this project doesn't already have a price feed for the pair or its inverse.
206
- if (
207
- priceFeedFor[projectId][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
208
- || priceFeedFor[projectId][unitCurrency][pricingCurrency] != IJBPriceFeed(address(0))
209
- ) {
210
- revert JBPrices_PriceFeedAlreadyExists(priceFeedFor[projectId][pricingCurrency][unitCurrency]
211
- != IJBPriceFeed(address(0))
212
- ? priceFeedFor[projectId][pricingCurrency][unitCurrency]
213
- : priceFeedFor[projectId][unitCurrency][pricingCurrency]);
214
- }
215
-
216
- // Store the feed.
217
- priceFeedFor[projectId][pricingCurrency][unitCurrency] = feed;
218
-
219
- emit AddPriceFeed({
220
- projectId: projectId,
221
- pricingCurrency: pricingCurrency,
222
- unitCurrency: unitCurrency,
223
- feed: feed,
224
- caller: _msgSender()
225
- });
226
- }
227
227
  }
@@ -46,6 +46,37 @@ contract JBProjects is ERC721, ERC2771Context, Ownable, IJBProjects {
46
46
  }
47
47
  }
48
48
 
49
+ //*********************************************************************//
50
+ // ---------------------- external transactions ---------------------- //
51
+ //*********************************************************************//
52
+
53
+ /// @notice Sets the address of the resolver used to retrieve the tokenURI of projects.
54
+ /// @param resolver The address of the new resolver.
55
+ function setTokenUriResolver(IJBTokenUriResolver resolver) external override onlyOwner {
56
+ // Store the new resolver.
57
+ tokenUriResolver = resolver;
58
+
59
+ emit SetTokenUriResolver({resolver: resolver, caller: _msgSender()});
60
+ }
61
+
62
+ //*********************************************************************//
63
+ // ----------------------- public transactions ----------------------- //
64
+ //*********************************************************************//
65
+
66
+ /// @notice Create a new project for the specified owner, which mints an NFT (ERC-721) into their wallet.
67
+ /// @dev Anyone can create a project on an owner's behalf.
68
+ /// @param owner The address that will be the owner of the project.
69
+ /// @return projectId The token ID of the newly created project.
70
+ function createFor(address owner) public override returns (uint256 projectId) {
71
+ // Increment the count, which will be used as the ID.
72
+ projectId = ++count;
73
+
74
+ emit Create({projectId: projectId, owner: owner, caller: _msgSender()});
75
+
76
+ // Mint the project.
77
+ _safeMint(owner, projectId);
78
+ }
79
+
49
80
  //*********************************************************************//
50
81
  // -------------------------- public views --------------------------- //
51
82
  //*********************************************************************//
@@ -92,35 +123,4 @@ contract JBProjects is ERC721, ERC2771Context, Ownable, IJBProjects {
92
123
  function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
93
124
  return ERC2771Context._msgSender();
94
125
  }
95
-
96
- //*********************************************************************//
97
- // ---------------------- external transactions ---------------------- //
98
- //*********************************************************************//
99
-
100
- /// @notice Sets the address of the resolver used to retrieve the tokenURI of projects.
101
- /// @param resolver The address of the new resolver.
102
- function setTokenUriResolver(IJBTokenUriResolver resolver) external override onlyOwner {
103
- // Store the new resolver.
104
- tokenUriResolver = resolver;
105
-
106
- emit SetTokenUriResolver({resolver: resolver, caller: _msgSender()});
107
- }
108
-
109
- //*********************************************************************//
110
- // ---------------------- public transactions ---------------------- //
111
- //*********************************************************************//
112
-
113
- /// @notice Create a new project for the specified owner, which mints an NFT (ERC-721) into their wallet.
114
- /// @dev Anyone can create a project on an owner's behalf.
115
- /// @param owner The address that will be the owner of the project.
116
- /// @return projectId The token ID of the newly created project.
117
- function createFor(address owner) public override returns (uint256 projectId) {
118
- // Increment the count, which will be used as the ID.
119
- projectId = ++count;
120
-
121
- emit Create({projectId: projectId, owner: owner, caller: _msgSender()});
122
-
123
- // Mint the project.
124
- _safeMint(owner, projectId);
125
- }
126
126
  }