@bananapus/core-v6 0.0.38 → 0.0.40
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/foundry.toml +1 -1
- package/package.json +1 -1
- package/src/JBChainlinkV3PriceFeed.sol +4 -1
- package/src/JBChainlinkV3SequencerPriceFeed.sol +4 -2
- package/src/JBController.sol +67 -58
- package/src/JBDeadline.sol +4 -4
- package/src/JBDirectory.sol +38 -36
- package/src/JBERC20.sol +10 -9
- package/src/JBFeelessAddresses.sol +6 -3
- package/src/JBFundAccessLimits.sol +26 -22
- package/src/JBMultiTerminal.sol +128 -125
- package/src/JBPermissions.sol +35 -38
- package/src/JBPrices.sol +25 -20
- package/src/JBProjects.sol +6 -3
- package/src/JBRulesets.sol +45 -42
- package/src/JBSplits.sol +19 -17
- package/src/JBTerminalStore.sol +57 -50
- package/src/JBTokens.sol +42 -32
- package/src/abstract/JBControlled.sol +3 -1
- package/src/abstract/JBPermissioned.sol +3 -1
- package/src/enums/JBApprovalStatus.sol +7 -1
- package/src/interfaces/IJBCashOutTerminal.sol +5 -5
- package/src/interfaces/IJBController.sol +13 -12
- package/src/interfaces/IJBDirectory.sol +3 -1
- package/src/interfaces/IJBMigratable.sol +5 -5
- package/src/interfaces/IJBMultiTerminal.sol +3 -2
- package/src/interfaces/IJBPayoutTerminal.sol +3 -3
- package/src/interfaces/IJBPermissions.sol +6 -5
- package/src/interfaces/IJBPermitTerminal.sol +1 -1
- package/src/interfaces/IJBPrices.sol +7 -5
- package/src/interfaces/IJBRulesets.sol +2 -1
- package/src/interfaces/IJBSplits.sol +2 -1
- package/src/interfaces/IJBTerminal.sol +13 -11
- package/src/interfaces/IJBTerminalStore.sol +23 -21
- package/src/interfaces/IJBTokens.sol +8 -7
- package/src/libraries/JBCashOuts.sol +8 -3
- package/src/libraries/JBConstants.sol +12 -3
- package/src/libraries/JBCurrencyIds.sol +2 -0
- package/src/libraries/JBFees.sol +5 -1
- package/src/libraries/JBFixedPointNumber.sol +2 -0
- package/src/libraries/JBPayoutSplitGroupLib.sol +10 -7
- package/src/libraries/JBRulesetMetadataResolver.sol +4 -0
- package/src/libraries/JBSplitGroupIds.sol +2 -1
- package/src/libraries/JBSurplus.sol +4 -2
- package/src/periphery/JBMatchingPriceFeed.sol +2 -0
- package/src/structs/JBAccountingContext.sol +7 -4
- package/src/structs/JBAfterCashOutRecordedContext.sol +8 -8
- package/src/structs/JBAfterPayRecordedContext.sol +5 -5
- package/src/structs/JBBeforeCashOutRecordedContext.sol +7 -7
- package/src/structs/JBBeforePayRecordedContext.sol +5 -5
- package/src/structs/JBFundAccessLimitGroup.sol +10 -17
- package/src/structs/JBPermissionsData.sol +3 -3
- package/src/structs/JBRuleset.sol +18 -26
- package/src/structs/JBRulesetConfig.sol +13 -25
- package/src/structs/JBRulesetMetadata.sol +25 -32
- package/src/structs/JBSplitHookContext.sol +2 -2
package/foundry.toml
CHANGED
|
@@ -17,7 +17,7 @@ fail_on_revert = false
|
|
|
17
17
|
ethereum = "${RPC_ETHEREUM_MAINNET}"
|
|
18
18
|
|
|
19
19
|
[lint]
|
|
20
|
-
exclude_lints = ["
|
|
20
|
+
exclude_lints = ["mixed-case-variable", "pascal-case-struct"]
|
|
21
21
|
[fmt]
|
|
22
22
|
number_underscore = "thousands"
|
|
23
23
|
multiline_func_header = "all"
|
package/package.json
CHANGED
|
@@ -6,7 +6,9 @@ import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interf
|
|
|
6
6
|
import {IJBPriceFeed} from "./interfaces/IJBPriceFeed.sol";
|
|
7
7
|
import {JBFixedPointNumber} from "./libraries/JBFixedPointNumber.sol";
|
|
8
8
|
|
|
9
|
-
/// @notice
|
|
9
|
+
/// @notice A price feed adapter that reads from a Chainlink V3 aggregator. Reverts if the price is stale (older than
|
|
10
|
+
/// `THRESHOLD` seconds), negative, or from an incomplete round — protecting against serving outdated oracle data.
|
|
11
|
+
/// Used by `JBPrices` to convert between currencies (e.g. ETH/USD).
|
|
10
12
|
contract JBChainlinkV3PriceFeed is IJBPriceFeed {
|
|
11
13
|
// A library that provides utility for fixed point numbers.
|
|
12
14
|
using JBFixedPointNumber for uint256;
|
|
@@ -60,6 +62,7 @@ contract JBChainlinkV3PriceFeed is IJBPriceFeed {
|
|
|
60
62
|
if (answeredInRound < roundId) revert JBChainlinkV3PriceFeed_IncompleteRound();
|
|
61
63
|
|
|
62
64
|
// Make sure the price's update threshold is met.
|
|
65
|
+
// forge-lint: disable-next-line(block-timestamp)
|
|
63
66
|
if (block.timestamp > THRESHOLD + updatedAt) {
|
|
64
67
|
revert JBChainlinkV3PriceFeed_StalePrice(block.timestamp, THRESHOLD, updatedAt);
|
|
65
68
|
}
|
|
@@ -6,8 +6,9 @@ import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interf
|
|
|
6
6
|
|
|
7
7
|
import {JBChainlinkV3PriceFeed} from "./JBChainlinkV3PriceFeed.sol";
|
|
8
8
|
|
|
9
|
-
/// @notice
|
|
10
|
-
///
|
|
9
|
+
/// @notice Extends `JBChainlinkV3PriceFeed` with L2 sequencer uptime checks (for Optimism, Arbitrum, etc.). Reverts if
|
|
10
|
+
/// the sequencer is down or has not been back online for at least `GRACE_PERIOD_TIME` seconds — preventing stale
|
|
11
|
+
/// prices from to use immediately after an outage.
|
|
11
12
|
contract JBChainlinkV3SequencerPriceFeed is JBChainlinkV3PriceFeed {
|
|
12
13
|
//*********************************************************************//
|
|
13
14
|
// --------------------------- custom errors ------------------------- //
|
|
@@ -64,6 +65,7 @@ contract JBChainlinkV3SequencerPriceFeed is JBChainlinkV3PriceFeed {
|
|
|
64
65
|
if (startedAt == 0) revert JBChainlinkV3SequencerPriceFeed_InvalidRound();
|
|
65
66
|
|
|
66
67
|
// Revert if sequencer has too recently restarted or is currently down.
|
|
68
|
+
// forge-lint: disable-next-line(block-timestamp)
|
|
67
69
|
if (block.timestamp <= GRACE_PERIOD_TIME + startedAt || answer != 0) {
|
|
68
70
|
revert JBChainlinkV3SequencerPriceFeed_SequencerDownOrRestarting(
|
|
69
71
|
block.timestamp, GRACE_PERIOD_TIME, startedAt
|
package/src/JBController.sol
CHANGED
|
@@ -41,8 +41,13 @@ import {JBSplitGroup} from "./structs/JBSplitGroup.sol";
|
|
|
41
41
|
import {JBSplitHookContext} from "./structs/JBSplitHookContext.sol";
|
|
42
42
|
import {JBTerminalConfig} from "./structs/JBTerminalConfig.sol";
|
|
43
43
|
|
|
44
|
-
/// @notice
|
|
45
|
-
///
|
|
44
|
+
/// @notice The orchestrator for every Juicebox project's lifecycle. Use the controller to launch a project, queue new
|
|
45
|
+
/// rulesets (funding cycles), mint or burn tokens, deploy an ERC-20, distribute reserved tokens, and manage
|
|
46
|
+
/// permissions. The controller coordinates between the terminal (money), rulesets (rules), tokens (issuance), and
|
|
47
|
+
/// splits (distribution).
|
|
48
|
+
/// @dev Supports ERC-2771 meta-transactions. Implements `IJBMigratable` for controller-to-controller migration.
|
|
49
|
+
/// An omnichain deployer address is trusted to launch and queue rulesets on behalf of any project for cross-chain
|
|
50
|
+
/// coordination.
|
|
46
51
|
contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigratable {
|
|
47
52
|
// A library that parses packed ruleset metadata into a friendlier format.
|
|
48
53
|
using JBRulesetMetadataResolver for JBRuleset;
|
|
@@ -166,11 +171,12 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
166
171
|
// ---------------------- external transactions ---------------------- //
|
|
167
172
|
//*********************************************************************//
|
|
168
173
|
|
|
169
|
-
/// @notice
|
|
170
|
-
/// @dev Can only be called by the project's owner or an
|
|
174
|
+
/// @notice Registers a price feed so the project can use a new currency for payout limits or surplus allowances.
|
|
175
|
+
/// @dev Can only be called by the project's owner or an operator with `ADD_PRICE_FEED` permission. The current
|
|
176
|
+
/// ruleset must have `allowAddPriceFeed` enabled.
|
|
171
177
|
/// @param projectId The ID of the project to add the feed for.
|
|
172
178
|
/// @param pricingCurrency The currency the feed's output price is in terms of.
|
|
173
|
-
/// @param unitCurrency The currency
|
|
179
|
+
/// @param unitCurrency The currency the feed prices.
|
|
174
180
|
/// @param feed The address of the price feed to add.
|
|
175
181
|
function addPriceFeedFor(
|
|
176
182
|
uint256 projectId,
|
|
@@ -198,7 +204,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
198
204
|
|
|
199
205
|
/// @notice Called after this controller has been set as the project's controller in the directory.
|
|
200
206
|
/// @dev Can only be called by the directory.
|
|
201
|
-
/// @param from The controller
|
|
207
|
+
/// @param from The controller to migrate from.
|
|
202
208
|
/// @param projectId The ID of the project that migrated to this controller.
|
|
203
209
|
function afterReceiveMigrationFrom(IERC165 from, uint256 projectId) external view override {
|
|
204
210
|
from; // Suppress unused variable warning.
|
|
@@ -208,9 +214,9 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
208
214
|
if (_msgSender() != address(DIRECTORY)) revert JBController_OnlyDirectory(_msgSender(), DIRECTORY);
|
|
209
215
|
}
|
|
210
216
|
|
|
211
|
-
/// @notice Prepares this controller to receive a project
|
|
217
|
+
/// @notice Prepares this controller to receive a project to migrate from another controller.
|
|
212
218
|
/// @dev This controller should not be the project's controller yet.
|
|
213
|
-
/// @param from The controller
|
|
219
|
+
/// @param from The controller to migrate from.
|
|
214
220
|
/// @param projectId The ID of the project that will migrate to this controller.
|
|
215
221
|
function beforeReceiveMigrationFrom(IERC165 from, uint256 projectId) external override {
|
|
216
222
|
// Keep a reference to the sender.
|
|
@@ -234,11 +240,11 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
234
240
|
}
|
|
235
241
|
}
|
|
236
242
|
|
|
237
|
-
/// @notice Burns a
|
|
238
|
-
///
|
|
239
|
-
/// terminal.
|
|
240
|
-
/// @param holder The address
|
|
241
|
-
/// @param projectId The ID of the project
|
|
243
|
+
/// @notice Burns a holder's project tokens (or credits), permanently removing them from supply. Used by terminals
|
|
244
|
+
/// during cash outs, or directly by holders who want to burn voluntarily.
|
|
245
|
+
/// @dev Can only be called by the holder, an operator with `BURN_TOKENS` permission, or a project terminal.
|
|
246
|
+
/// @param holder The address to burn tokens for.
|
|
247
|
+
/// @param projectId The ID of the project to burn tokens for.
|
|
242
248
|
/// @param tokenCount The number of tokens to burn.
|
|
243
249
|
/// @param memo A memo to pass along to the emitted event.
|
|
244
250
|
function burnTokensOf(
|
|
@@ -269,10 +275,11 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
269
275
|
TOKENS.burnFrom({holder: holder, projectId: projectId, count: tokenCount});
|
|
270
276
|
}
|
|
271
277
|
|
|
272
|
-
/// @notice
|
|
273
|
-
///
|
|
278
|
+
/// @notice Converts internal credits into the project's ERC-20 token, transferring them to the beneficiary's
|
|
279
|
+
/// wallet. Credits and ERC-20 tokens are interchangeable — this just makes them transferable/tradeable.
|
|
280
|
+
/// @dev Can only be called by the credit holder or an operator with `CLAIM_TOKENS` permission.
|
|
274
281
|
/// @param holder The address to redeem credits from.
|
|
275
|
-
/// @param projectId The ID of the project
|
|
282
|
+
/// @param projectId The ID of the project to claim tokens for.
|
|
276
283
|
/// @param tokenCount The number of tokens to claim.
|
|
277
284
|
/// @param beneficiary The account the claimed tokens will go to.
|
|
278
285
|
function claimTokensFor(
|
|
@@ -290,9 +297,10 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
290
297
|
TOKENS.claimTokensFor({holder: holder, projectId: projectId, count: tokenCount, beneficiary: beneficiary});
|
|
291
298
|
}
|
|
292
299
|
|
|
293
|
-
/// @notice Deploys
|
|
294
|
-
///
|
|
295
|
-
/// @dev Can only be called by the project's owner or an
|
|
300
|
+
/// @notice Deploys a new ERC-20 token for a project. Once deployed, holders can claim their credits as this token.
|
|
301
|
+
/// Includes ERC20Votes (governance) and ERC20Permit (gasless approvals).
|
|
302
|
+
/// @dev Can only be called by the project's owner or an operator with `DEPLOY_ERC20` permission.
|
|
303
|
+
/// @dev Each project can only have one ERC-20 deployed — calling this again after deployment will revert.
|
|
296
304
|
/// @param projectId The ID of the project to deploy the ERC-20 for.
|
|
297
305
|
/// @param name The ERC-20's name.
|
|
298
306
|
/// @param symbol The ERC-20's symbol.
|
|
@@ -330,9 +338,9 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
330
338
|
/// terminal.
|
|
331
339
|
/// @dev Can only be called by this controller.
|
|
332
340
|
/// @param terminal The terminal to pay.
|
|
333
|
-
/// @param projectId The ID of the project
|
|
334
|
-
/// @param token The token
|
|
335
|
-
/// @param splitTokenCount The number of tokens
|
|
341
|
+
/// @param projectId The ID of the project to pay.
|
|
342
|
+
/// @param token The token to pay with.
|
|
343
|
+
/// @param splitTokenCount The number of tokens to pay.
|
|
336
344
|
/// @param beneficiary The payment's beneficiary.
|
|
337
345
|
/// @param metadata The pay metadata sent to the terminal.
|
|
338
346
|
function executePayReservedTokenToTerminal(
|
|
@@ -368,10 +376,11 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
368
376
|
}
|
|
369
377
|
}
|
|
370
378
|
|
|
371
|
-
/// @notice Creates a project
|
|
372
|
-
///
|
|
373
|
-
///
|
|
374
|
-
/// @dev Anyone can
|
|
379
|
+
/// @notice Creates a new Juicebox project in one transaction — mints the project NFT, queues initial rulesets,
|
|
380
|
+
/// and
|
|
381
|
+
/// configures terminals. This is the primary entry point for launching a project.
|
|
382
|
+
/// @dev Anyone can call this on behalf of any owner. Each sub-operation (mint, queue, configure) can also be done
|
|
383
|
+
/// individually if needed.
|
|
375
384
|
/// @param owner The project's owner. The project ERC-721 will be minted to this address.
|
|
376
385
|
/// @param projectUri The project's metadata URI. This is typically an IPFS hash, optionally with the `ipfs://`
|
|
377
386
|
/// prefix. This can be updated by the project's owner.
|
|
@@ -414,10 +423,10 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
414
423
|
});
|
|
415
424
|
}
|
|
416
425
|
|
|
417
|
-
/// @notice
|
|
418
|
-
///
|
|
419
|
-
/// @dev
|
|
420
|
-
/// @dev
|
|
426
|
+
/// @notice Queues the first rulesets for an existing project and configures its terminals. For projects that
|
|
427
|
+
/// already have active rulesets, use `queueRulesetsOf(...)` instead.
|
|
428
|
+
/// @dev Can only be called by the project's owner or an operator with `LAUNCH_RULESETS` permission.
|
|
429
|
+
/// @dev Each sub-operation can also be done individually if needed.
|
|
421
430
|
/// @param projectId The ID of the project to launch rulesets for.
|
|
422
431
|
/// @param projectUri The project's metadata URI. Pass an empty string to leave it unchanged.
|
|
423
432
|
/// @param rulesetConfigurations The rulesets to queue.
|
|
@@ -508,13 +517,11 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
508
517
|
if (pendingReservedTokenBalance != 0) revert JBController_PendingReservedTokens(pendingReservedTokenBalance);
|
|
509
518
|
}
|
|
510
519
|
|
|
511
|
-
/// @notice
|
|
512
|
-
///
|
|
513
|
-
/// @dev Can
|
|
514
|
-
/// the
|
|
515
|
-
/// @
|
|
516
|
-
/// project's terminals or data hook.
|
|
517
|
-
/// @param projectId The ID of the project whose tokens are being minted.
|
|
520
|
+
/// @notice Mints new project tokens to a beneficiary. Optionally reserves a portion according to the ruleset's
|
|
521
|
+
/// reserved percent (which accumulates until `sendReservedTokensToSplitsOf` is called).
|
|
522
|
+
/// @dev Can be called by the project owner, an operator with `MINT_TOKENS` permission, a project terminal, or the
|
|
523
|
+
/// data hook. If `allowOwnerMinting` is false in the current ruleset, only terminals and the data hook can mint.
|
|
524
|
+
/// @param projectId The ID of the project to mint tokens for.
|
|
518
525
|
/// @param tokenCount The number of tokens to mint, including any reserved tokens.
|
|
519
526
|
/// @param beneficiary The address which will receive the (non-reserved) tokens.
|
|
520
527
|
/// @param memo A memo to pass along to the emitted event.
|
|
@@ -594,9 +601,9 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
594
601
|
}
|
|
595
602
|
}
|
|
596
603
|
|
|
597
|
-
/// @notice
|
|
598
|
-
/// previous ruleset
|
|
599
|
-
/// @dev Can only be called by the project's owner or an
|
|
604
|
+
/// @notice Queues new rulesets to take effect after the current one ends. Each queued ruleset must be approved by
|
|
605
|
+
/// the previous ruleset's approval hook (if one is set) before it can take effect.
|
|
606
|
+
/// @dev Can only be called by the project's owner or an operator with `QUEUE_RULESETS` permission.
|
|
600
607
|
/// @param projectId The ID of the project to queue rulesets for.
|
|
601
608
|
/// @param rulesetConfigurations The rulesets to queue.
|
|
602
609
|
/// @param memo A memo to pass along to the emitted event.
|
|
@@ -628,17 +635,18 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
628
635
|
emit QueueRulesets({rulesetId: rulesetId, projectId: projectId, memo: memo, caller: _msgSender()});
|
|
629
636
|
}
|
|
630
637
|
|
|
631
|
-
/// @notice
|
|
632
|
-
///
|
|
633
|
-
/// the project
|
|
638
|
+
/// @notice Mints and distributes all pending reserved tokens to the project's reserved token split recipients.
|
|
639
|
+
/// Anyone can call this — it's permissionless.
|
|
640
|
+
/// @dev If splits don't add up to 100%, the remainder goes to the project owner.
|
|
634
641
|
/// @param projectId The ID of the project to send reserved tokens for.
|
|
635
642
|
/// @return The amount of reserved tokens minted and sent.
|
|
636
643
|
function sendReservedTokensToSplitsOf(uint256 projectId) external override returns (uint256) {
|
|
637
644
|
return _sendReservedTokensToSplitsOf(projectId);
|
|
638
645
|
}
|
|
639
646
|
|
|
640
|
-
/// @notice
|
|
641
|
-
///
|
|
647
|
+
/// @notice Configures how a project distributes payouts and reserved tokens. Locked splits from the current
|
|
648
|
+
/// configuration must be preserved in the new split groups.
|
|
649
|
+
/// @dev Can only be called by the project's owner or an operator with `SET_SPLIT_GROUPS` permission.
|
|
642
650
|
/// @param projectId The ID of the project to set the split groups of.
|
|
643
651
|
/// @param rulesetId The ID of the ruleset the split groups should be active in. Use a `rulesetId` of 0 to set the
|
|
644
652
|
/// default split groups, which are used when a ruleset has no splits set. If there are no default splits and no
|
|
@@ -686,7 +694,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
686
694
|
/// @notice Sets the name and symbol of a project's token.
|
|
687
695
|
/// @dev Can only be called by the project's owner or an address with the owner's permission to
|
|
688
696
|
/// `SET_TOKEN_METADATA`.
|
|
689
|
-
/// @param projectId The ID of the project
|
|
697
|
+
/// @param projectId The ID of the project to update the token for.
|
|
690
698
|
/// @param name The new name.
|
|
691
699
|
/// @param symbol The new symbol.
|
|
692
700
|
function setTokenMetadataOf(uint256 projectId, string calldata name, string calldata symbol) external override {
|
|
@@ -716,10 +724,12 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
716
724
|
emit SetUri({projectId: projectId, uri: uri, caller: _msgSender()});
|
|
717
725
|
}
|
|
718
726
|
|
|
719
|
-
/// @notice
|
|
720
|
-
///
|
|
727
|
+
/// @notice Transfers internal credits (unclaimed tokens) from one address to another. Credits function like tokens
|
|
728
|
+
/// but live inside the protocol rather than as an ERC-20.
|
|
729
|
+
/// @dev Can only be called by the credit holder or an operator with `TRANSFER_CREDITS` permission. The current
|
|
730
|
+
/// ruleset must not have credit transfers paused.
|
|
721
731
|
/// @param holder The address to transfer credits from.
|
|
722
|
-
/// @param projectId The ID of the project
|
|
732
|
+
/// @param projectId The ID of the project to transfer credits for.
|
|
723
733
|
/// @param recipient The address to transfer credits to.
|
|
724
734
|
/// @param creditCount The number of credits to transfer.
|
|
725
735
|
function transferCreditsFrom(
|
|
@@ -747,8 +757,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
747
757
|
// ------------------------- external views -------------------------- //
|
|
748
758
|
//*********************************************************************//
|
|
749
759
|
|
|
750
|
-
/// @notice
|
|
751
|
-
/// earliest.
|
|
760
|
+
/// @notice Returns a paginated history of a project's rulesets (with decoded metadata), sorted newest-first.
|
|
752
761
|
/// @param projectId The ID of the project to get the rulesets of.
|
|
753
762
|
/// @param startingId The ID of the ruleset to begin with. This will be the latest ruleset in the result. If the
|
|
754
763
|
/// `startingId` is 0, passed, the project's latest ruleset will be used.
|
|
@@ -786,7 +795,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
786
795
|
}
|
|
787
796
|
}
|
|
788
797
|
|
|
789
|
-
/// @notice
|
|
798
|
+
/// @notice Returns the ruleset currently governing a project, along with its decoded metadata.
|
|
790
799
|
/// @param projectId The ID of the project to get the current ruleset of.
|
|
791
800
|
/// @return ruleset The current ruleset's struct.
|
|
792
801
|
/// @return metadata The current ruleset's metadata.
|
|
@@ -835,7 +844,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
835
844
|
}
|
|
836
845
|
|
|
837
846
|
/// @notice Previews how many beneficiary and reserved tokens `mintTokensOf(...)` would produce.
|
|
838
|
-
/// @param projectId The ID of the project
|
|
847
|
+
/// @param projectId The ID of the project to mint tokens for.
|
|
839
848
|
/// @param tokenCount The number of tokens to mint, including any reserved tokens.
|
|
840
849
|
/// @param useReservedPercent Whether to apply the ruleset's reserved percent.
|
|
841
850
|
/// @return beneficiaryTokenCount The number of tokens that would be minted for the beneficiary.
|
|
@@ -862,21 +871,21 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
862
871
|
});
|
|
863
872
|
}
|
|
864
873
|
|
|
865
|
-
/// @notice
|
|
874
|
+
/// @notice Whether the project's current ruleset allows migrating to a different controller.
|
|
866
875
|
/// @param projectId The ID of the project to check.
|
|
867
876
|
/// @return A `bool` which is true if the project allows controllers to be set.
|
|
868
877
|
function setControllerAllowed(uint256 projectId) external view returns (bool) {
|
|
869
878
|
return _currentRulesetOf(projectId).expandMetadata().allowSetController;
|
|
870
879
|
}
|
|
871
880
|
|
|
872
|
-
/// @notice
|
|
881
|
+
/// @notice Whether the project's current ruleset allows changing its terminals.
|
|
873
882
|
/// @param projectId The ID of the project to check.
|
|
874
883
|
/// @return A `bool` which is true if the project allows terminals to be set.
|
|
875
884
|
function setTerminalsAllowed(uint256 projectId) external view returns (bool) {
|
|
876
885
|
return _currentRulesetOf(projectId).expandMetadata().allowSetTerminals;
|
|
877
886
|
}
|
|
878
887
|
|
|
879
|
-
/// @notice
|
|
888
|
+
/// @notice Returns the project's total token supply including tokens that have been reserved but not yet minted.
|
|
880
889
|
/// @param projectId The ID of the project to get the total token supply of.
|
|
881
890
|
/// @return The total supply of the project's token, including pending reserved tokens.
|
|
882
891
|
function totalTokenSupplyWithReservedTokensOf(uint256 projectId) external view override returns (uint256) {
|
|
@@ -884,7 +893,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
884
893
|
return TOKENS.totalSupplyOf(projectId) + pendingReservedTokenBalanceOf[projectId];
|
|
885
894
|
}
|
|
886
895
|
|
|
887
|
-
/// @notice
|
|
896
|
+
/// @notice Returns the ruleset that will take effect after the current one ends, along with its decoded metadata.
|
|
888
897
|
/// @dev If an upcoming ruleset isn't found, returns an empty ruleset with all properties set to 0.
|
|
889
898
|
/// @param projectId The ID of the project to get the next ruleset of.
|
|
890
899
|
/// @return ruleset The upcoming ruleset's struct.
|
|
@@ -951,7 +960,7 @@ contract JBController is JBPermissioned, ERC2771Context, IJBController, IJBMigra
|
|
|
951
960
|
|
|
952
961
|
/// @notice Queues one or more rulesets and stores information pertinent to the configuration.
|
|
953
962
|
/// @param projectId The ID of the project to queue rulesets for.
|
|
954
|
-
/// @param rulesetConfigurations The rulesets
|
|
963
|
+
/// @param rulesetConfigurations The rulesets to queue.
|
|
955
964
|
/// @return rulesetId The ID of the last ruleset that was successfully queued.
|
|
956
965
|
function _queueRulesets(
|
|
957
966
|
uint256 projectId,
|
package/src/JBDeadline.sol
CHANGED
|
@@ -7,10 +7,9 @@ import {JBApprovalStatus} from "./enums/JBApprovalStatus.sol";
|
|
|
7
7
|
import {IJBRulesetApprovalHook} from "./interfaces/IJBRulesetApprovalHook.sol";
|
|
8
8
|
import {JBRuleset} from "./structs/JBRuleset.sol";
|
|
9
9
|
|
|
10
|
-
/// @notice
|
|
11
|
-
/// seconds before the current ruleset ends
|
|
12
|
-
///
|
|
13
|
-
/// only if they are approved by the previous ruleset's approval hook.
|
|
10
|
+
/// @notice A ruleset approval hook that enforces a queuing deadline. If a new ruleset is not queued at least `DURATION`
|
|
11
|
+
/// seconds before the current ruleset ends, it is rejected and the existing rules continue. This gives token holders
|
|
12
|
+
/// a guaranteed notice period before any project configuration changes take effect.
|
|
14
13
|
/// @dev If `DURATION` is set longer than the ruleset's cycle duration, no queued ruleset can ever satisfy the deadline
|
|
15
14
|
/// and the current ruleset will effectively be locked in perpetuity. Choose a `DURATION` shorter than the shortest
|
|
16
15
|
/// cycle it will govern.
|
|
@@ -60,6 +59,7 @@ contract JBDeadline is IJBRulesetApprovalHook {
|
|
|
60
59
|
// If we've already passed the deadline, the ruleset is `Approved`.
|
|
61
60
|
return (ruleset.start - ruleset.id < DURATION)
|
|
62
61
|
? JBApprovalStatus.Failed
|
|
62
|
+
// forge-lint: disable-next-line(block-timestamp)
|
|
63
63
|
: (block.timestamp + DURATION < ruleset.start)
|
|
64
64
|
? JBApprovalStatus.ApprovalExpected
|
|
65
65
|
: JBApprovalStatus.Approved;
|
package/src/JBDirectory.sol
CHANGED
|
@@ -13,9 +13,11 @@ import {IJBPermissions} from "./interfaces/IJBPermissions.sol";
|
|
|
13
13
|
import {IJBProjects} from "./interfaces/IJBProjects.sol";
|
|
14
14
|
import {IJBTerminal} from "./interfaces/IJBTerminal.sol";
|
|
15
15
|
|
|
16
|
-
/// @notice
|
|
17
|
-
///
|
|
18
|
-
///
|
|
16
|
+
/// @notice The routing table for the protocol. Every project registers which terminals accept its payments and which
|
|
17
|
+
/// controller manages its rulesets and tokens. Frontends and other contracts use the directory to discover where to
|
|
18
|
+
/// send funds for a given project and token.
|
|
19
|
+
/// @dev Also manages controller migration — when a project upgrades its controller, the directory orchestrates the
|
|
20
|
+
/// handoff including `beforeReceiveMigrationFrom`, `migrate`, and `afterReceiveMigrationFrom` lifecycle hooks.
|
|
19
21
|
contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
|
|
20
22
|
//*********************************************************************//
|
|
21
23
|
// --------------------------- custom errors ------------------------- //
|
|
@@ -83,13 +85,15 @@ contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
|
|
|
83
85
|
// ---------------------- external transactions ---------------------- //
|
|
84
86
|
//*********************************************************************//
|
|
85
87
|
|
|
86
|
-
/// @notice
|
|
88
|
+
/// @notice Assign a new controller to a project. The controller dictates how the project's terminals interact with
|
|
89
|
+
/// its tokens and rulesets. If the project already has a controller, this triggers a full migration lifecycle
|
|
90
|
+
/// (`beforeReceiveMigrationFrom` → `migrate` → state update → `afterReceiveMigrationFrom`).
|
|
87
91
|
/// @dev Can only be called if:
|
|
88
|
-
/// - The ruleset's metadata has `allowSetController` enabled, and the
|
|
89
|
-
///
|
|
90
|
-
/// - OR the
|
|
91
|
-
/// - OR
|
|
92
|
-
/// @param projectId The ID of the project
|
|
92
|
+
/// - The ruleset's metadata has `allowSetController` enabled, and the caller is the project's owner or has
|
|
93
|
+
/// `SET_CONTROLLER` permission.
|
|
94
|
+
/// - OR the caller is the project's current controller.
|
|
95
|
+
/// - OR the caller `isAllowedToSetFirstController` and the project has no controller yet.
|
|
96
|
+
/// @param projectId The ID of the project to set the controller for.
|
|
93
97
|
/// @param controller The address of the controller to set.
|
|
94
98
|
function setControllerOf(uint256 projectId, IERC165 controller) external override {
|
|
95
99
|
// Keep a reference to the current controller.
|
|
@@ -149,15 +153,13 @@ contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
|
|
|
149
153
|
}
|
|
150
154
|
}
|
|
151
155
|
|
|
152
|
-
/// @notice
|
|
153
|
-
/// controller
|
|
154
|
-
/// @dev Only this contract's owner can call this function.
|
|
155
|
-
///
|
|
156
|
-
///
|
|
157
|
-
/// @
|
|
158
|
-
/// @param
|
|
159
|
-
/// @param flag Whether the address is allowed to set first controllers for projects. Use `true` to allow and
|
|
160
|
-
/// `false` to not allow.
|
|
156
|
+
/// @notice Allow or disallow an address to set the first controller for new projects. Typically used to whitelist
|
|
157
|
+
/// deployer contracts (like `JBController`) that set a controller during `launchProjectFor`.
|
|
158
|
+
/// @dev Only this contract's owner can call this function. These addresses are vetted controllers and project
|
|
159
|
+
/// launchers. A project owner can always set their own controller — this list only governs *first* controller
|
|
160
|
+
/// assignment by third parties.
|
|
161
|
+
/// @param addr The address to allow or disallow.
|
|
162
|
+
/// @param flag Whether the address is allowed to set first controllers. `true` to allow, `false` to revoke.
|
|
161
163
|
function setIsAllowedToSetFirstController(address addr, bool flag) external override onlyOwner {
|
|
162
164
|
// Set the flag in the allowlist.
|
|
163
165
|
isAllowedToSetFirstController[addr] = flag;
|
|
@@ -165,14 +167,14 @@ contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
|
|
|
165
167
|
emit SetIsAllowedToSetFirstController({addr: addr, isAllowed: flag, caller: msg.sender});
|
|
166
168
|
}
|
|
167
169
|
|
|
168
|
-
/// @notice
|
|
169
|
-
///
|
|
170
|
-
/// @dev
|
|
171
|
-
///
|
|
172
|
-
/// `
|
|
173
|
-
/// @param projectId The ID of the project
|
|
170
|
+
/// @notice Designate which terminal should receive payments by default when someone pays a project in a specific
|
|
171
|
+
/// token. Useful when a project has multiple terminals that accept the same token.
|
|
172
|
+
/// @dev Can only be called by the project's owner or an address with `SET_PRIMARY_TERMINAL` permission. The
|
|
173
|
+
/// terminal must accept the token for this project. If the terminal isn't already in the project's terminal list,
|
|
174
|
+
/// it will be added automatically (requires `ADD_TERMINALS` permission).
|
|
175
|
+
/// @param projectId The ID of the project to set the primary terminal for.
|
|
174
176
|
/// @param token The token to set the primary terminal for.
|
|
175
|
-
/// @param terminal The terminal
|
|
177
|
+
/// @param terminal The terminal to set as the primary terminal.
|
|
176
178
|
function setPrimaryTerminalOf(uint256 projectId, address token, IJBTerminal terminal) external override {
|
|
177
179
|
// Enforce permissions.
|
|
178
180
|
_requirePermissionFrom({
|
|
@@ -203,11 +205,11 @@ contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
|
|
|
203
205
|
emit SetPrimaryTerminal({projectId: projectId, token: token, terminal: terminal, caller: msg.sender});
|
|
204
206
|
}
|
|
205
207
|
|
|
206
|
-
/// @notice
|
|
207
|
-
///
|
|
208
|
-
/// the project's
|
|
209
|
-
///
|
|
210
|
-
/// @param projectId The ID of the project
|
|
208
|
+
/// @notice Replace a project's entire terminal list. Terminals are the contracts that accept payments and process
|
|
209
|
+
/// cash outs for a project. This overwrites the existing list.
|
|
210
|
+
/// @dev Can only be called by the project's owner, an address with `SET_TERMINALS` permission, or the project's
|
|
211
|
+
/// controller. Unless the caller is the controller, the ruleset must have `allowSetTerminals` enabled.
|
|
212
|
+
/// @param projectId The ID of the project to set terminals for.
|
|
211
213
|
/// @param terminals An array of terminal addresses to set for the project.
|
|
212
214
|
function setTerminalsOf(uint256 projectId, IJBTerminal[] calldata terminals) external override {
|
|
213
215
|
// Cache the controller to avoid redundant storage reads.
|
|
@@ -254,10 +256,9 @@ contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
|
|
|
254
256
|
// ------------------------- external views -------------------------- //
|
|
255
257
|
//*********************************************************************//
|
|
256
258
|
|
|
257
|
-
/// @notice
|
|
258
|
-
///
|
|
259
|
-
///
|
|
260
|
-
/// @dev Returns the zero address if no terminal accepts the token.
|
|
259
|
+
/// @notice Look up the terminal where payments in a given token should be sent for a project. Returns the
|
|
260
|
+
/// explicitly-set primary terminal, or falls back to the first terminal in the project's list that accepts the
|
|
261
|
+
/// token. Returns the zero address if no terminal accepts the token.
|
|
261
262
|
/// @param projectId The ID of the project to get the primary terminal of.
|
|
262
263
|
/// @param token The token that the terminal accepts.
|
|
263
264
|
/// @return The primary terminal's address.
|
|
@@ -298,7 +299,8 @@ contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
|
|
|
298
299
|
return IJBTerminal(address(0));
|
|
299
300
|
}
|
|
300
301
|
|
|
301
|
-
/// @notice
|
|
302
|
+
/// @notice Get all terminals registered for a project. Terminals are the contracts that hold a project's funds and
|
|
303
|
+
/// process payments and cash outs on its behalf.
|
|
302
304
|
/// @param projectId The ID of the project to get the terminals of.
|
|
303
305
|
/// @return An array of the project's terminal addresses.
|
|
304
306
|
function terminalsOf(uint256 projectId) external view override returns (IJBTerminal[] memory) {
|
|
@@ -309,7 +311,7 @@ contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
|
|
|
309
311
|
// -------------------------- public views --------------------------- //
|
|
310
312
|
//*********************************************************************//
|
|
311
313
|
|
|
312
|
-
/// @notice Check
|
|
314
|
+
/// @notice Check whether a specific terminal is in a project's registered terminal list.
|
|
313
315
|
/// @param projectId The ID of the project to check.
|
|
314
316
|
/// @param terminal The terminal to check for.
|
|
315
317
|
/// @return A flag indicating whether the project uses the terminal.
|
package/src/JBERC20.sol
CHANGED
|
@@ -15,10 +15,11 @@ import {IJBProjects} from "./interfaces/IJBProjects.sol";
|
|
|
15
15
|
import {IJBToken} from "./interfaces/IJBToken.sol";
|
|
16
16
|
import {IJBTokens} from "./interfaces/IJBTokens.sol";
|
|
17
17
|
|
|
18
|
-
/// @notice
|
|
19
|
-
///
|
|
20
|
-
///
|
|
21
|
-
/// @dev `
|
|
18
|
+
/// @notice The ERC-20 token implementation used by Juicebox projects. Includes ERC20Votes (governance delegation) and
|
|
19
|
+
/// ERC20Permit (gasless approvals). Deployed as a minimal clone via `JBController.deployERC20For` — once deployed,
|
|
20
|
+
/// holders can claim their internal credits into this transferable token.
|
|
21
|
+
/// @dev Only `JBTokens` can mint and burn. The project owner (via `SET_TOKEN_METADATA` permission) can rename the
|
|
22
|
+
/// token. Supports ERC-1271 signature validation for smart-contract wallets.
|
|
22
23
|
contract JBERC20 is ERC20Votes, ERC20Permit, JBPermissioned, IERC1271, IJBToken {
|
|
23
24
|
//*********************************************************************//
|
|
24
25
|
// --------------------------- custom errors ------------------------- //
|
|
@@ -126,7 +127,7 @@ contract JBERC20 is ERC20Votes, ERC20Permit, JBPermissioned, IERC1271, IJBToken
|
|
|
126
127
|
/// @notice Validates a signature on behalf of this token contract (ERC-1271).
|
|
127
128
|
/// @dev Allows the project owner or an operator with `SIGN_FOR_ERC20` permission to sign messages on behalf of
|
|
128
129
|
/// this token. Useful for Etherscan contract verification and other off-chain signature flows.
|
|
129
|
-
/// @param hash The hash of the data
|
|
130
|
+
/// @param hash The hash of the data to sign.
|
|
130
131
|
/// @param signature The signature to validate.
|
|
131
132
|
/// @return magicValue `0x1626ba7e` if the signature is valid, `0xffffffff` otherwise.
|
|
132
133
|
function isValidSignature(bytes32 hash, bytes memory signature) external view override returns (bytes4 magicValue) {
|
|
@@ -169,17 +170,17 @@ contract JBERC20 is ERC20Votes, ERC20Permit, JBPermissioned, IERC1271, IJBToken
|
|
|
169
170
|
return super.decimals();
|
|
170
171
|
}
|
|
171
172
|
|
|
172
|
-
/// @notice The token's name.
|
|
173
|
+
/// @notice The token's name, set during initialization.
|
|
173
174
|
function name() public view virtual override returns (string memory) {
|
|
174
175
|
return _name;
|
|
175
176
|
}
|
|
176
177
|
|
|
177
|
-
/// @notice
|
|
178
|
+
/// @notice The current nonce for a given account, used for permit signatures.
|
|
178
179
|
function nonces(address owner) public view virtual override(ERC20Permit, Nonces) returns (uint256) {
|
|
179
180
|
return super.nonces(owner);
|
|
180
181
|
}
|
|
181
182
|
|
|
182
|
-
/// @notice The token's symbol.
|
|
183
|
+
/// @notice The token's ticker symbol, set during initialization.
|
|
183
184
|
function symbol() public view virtual override returns (string memory) {
|
|
184
185
|
return _symbol;
|
|
185
186
|
}
|
|
@@ -194,7 +195,7 @@ contract JBERC20 is ERC20Votes, ERC20Permit, JBPermissioned, IERC1271, IJBToken
|
|
|
194
195
|
// ----------------------- public transactions ----------------------- //
|
|
195
196
|
//*********************************************************************//
|
|
196
197
|
|
|
197
|
-
/// @notice
|
|
198
|
+
/// @notice Initialize a new project token with the given name, symbol, and owner.
|
|
198
199
|
/// @param name_ The token's name.
|
|
199
200
|
/// @param symbol_ The token's symbol.
|
|
200
201
|
/// @param tokens The JBTokens contract that manages this token.
|
|
@@ -6,7 +6,9 @@ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
|
6
6
|
|
|
7
7
|
import {IJBFeelessAddresses} from "./interfaces/IJBFeelessAddresses.sol";
|
|
8
8
|
|
|
9
|
-
/// @notice
|
|
9
|
+
/// @notice A registry of addresses exempt from the protocol's 2.5% fee. Feeless addresses don't incur fees on
|
|
10
|
+
/// payouts they receive, surplus allowance they use, or cash outs where they are the beneficiary. Managed by the
|
|
11
|
+
/// contract owner (typically the protocol multisig).
|
|
10
12
|
contract JBFeelessAddresses is Ownable, IJBFeelessAddresses, IERC165 {
|
|
11
13
|
//*********************************************************************//
|
|
12
14
|
// --------------------- public stored properties -------------------- //
|
|
@@ -30,8 +32,9 @@ contract JBFeelessAddresses is Ownable, IJBFeelessAddresses, IERC165 {
|
|
|
30
32
|
// ---------------------- external transactions ---------------------- //
|
|
31
33
|
//*********************************************************************//
|
|
32
34
|
|
|
33
|
-
/// @notice
|
|
34
|
-
///
|
|
35
|
+
/// @notice Add or remove an address from the fee-exempt list. Feeless addresses don't pay the 2.5% protocol fee
|
|
36
|
+
/// on payouts received, surplus allowance used, or cash outs where they're the beneficiary.
|
|
37
|
+
/// @dev Can only be called by this contract's owner (typically the protocol multisig).
|
|
35
38
|
/// @param addr The address to set as feeless or not feeless.
|
|
36
39
|
/// @param flag Whether the address should be feeless (`true`) or not feeless (`false`).
|
|
37
40
|
function setFeelessAddress(address addr, bool flag) external virtual override onlyOwner {
|