@bananapus/core-v6 0.0.41 → 0.0.43
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/CHANGELOG.md +1 -1
- package/README.md +3 -3
- package/package.json +1 -1
- package/references/types-errors-events.md +0 -1
- package/src/JBChainlinkV3PriceFeed.sol +14 -6
- package/src/JBChainlinkV3SequencerPriceFeed.sol +5 -6
- package/src/JBController.sol +61 -50
- package/src/JBDirectory.sol +4 -7
- package/src/JBERC20.sol +8 -7
- package/src/JBFundAccessLimits.sol +12 -4
- package/src/JBMultiTerminal.sol +18 -51
- package/src/JBPermissions.sol +6 -3
- package/src/JBPrices.sol +18 -12
- package/src/JBRulesets.sol +4 -25
- package/src/JBSplits.sol +13 -5
- package/src/JBTerminalStore.sol +36 -25
- package/src/JBTokens.sol +11 -13
- package/src/abstract/JBControlled.sol +1 -2
- package/src/interfaces/IJBController.sol +0 -6
- package/src/libraries/JBCashOuts.sol +6 -2
- package/src/libraries/JBCurrencyIds.sol +3 -0
- package/src/libraries/JBFees.sol +10 -52
- package/src/libraries/JBMetadataResolver.sol +20 -12
- package/src/libraries/JBPayoutSplitGroupLib.sol +8 -3
- package/src/libraries/JBSplitGroupIds.sol +1 -0
- package/src/periphery/JBDeadline1Day.sol +1 -0
- package/src/periphery/JBDeadline3Days.sol +1 -0
- package/src/periphery/JBDeadline3Hours.sol +1 -0
- package/src/periphery/JBDeadline7Days.sol +1 -0
package/src/JBMultiTerminal.sol
CHANGED
|
@@ -64,7 +64,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
64
64
|
//*********************************************************************//
|
|
65
65
|
|
|
66
66
|
error JBMultiTerminal_FeeTerminalNotFound(address token);
|
|
67
|
-
error JBMultiTerminal_MintNotAllowed();
|
|
67
|
+
error JBMultiTerminal_MintNotAllowed(uint256 projectId, uint256 splitProjectId, address terminal);
|
|
68
68
|
error JBMultiTerminal_NoMsgValueAllowed(uint256 value);
|
|
69
69
|
error JBMultiTerminal_OverflowAlert(uint256 value, uint256 limit);
|
|
70
70
|
error JBMultiTerminal_PermitAllowanceNotEnough(uint256 amount, uint256 allowance);
|
|
@@ -88,9 +88,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
88
88
|
// ------------------------ internal constants ----------------------- //
|
|
89
89
|
//*********************************************************************//
|
|
90
90
|
|
|
91
|
-
/// @notice Denominator for forward-calculating this terminal's fee from a pre-fee amount.
|
|
92
|
-
uint256 internal constant _FEE_AMOUNT_FROM_DENOMINATOR = JBConstants.MAX_FEE / FEE;
|
|
93
|
-
|
|
94
91
|
/// @notice Project ID #1 receives fees. It should be the first project launched during the deployment process.
|
|
95
92
|
uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;
|
|
96
93
|
|
|
@@ -216,7 +213,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
216
213
|
|
|
217
214
|
// Emit an event for each accounting context.
|
|
218
215
|
for (uint256 i; i < accountingContexts.length;) {
|
|
219
|
-
// slither-disable-next-line reentrancy-events
|
|
220
216
|
emit SetAccountingContext({projectId: projectId, context: accountingContexts[i], caller: _msgSender()});
|
|
221
217
|
unchecked {
|
|
222
218
|
++i;
|
|
@@ -251,15 +247,15 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
251
247
|
_addToBalanceOf({
|
|
252
248
|
projectId: projectId,
|
|
253
249
|
token: token,
|
|
254
|
-
amount: _acceptFundsFor(projectId, token, amount, metadata),
|
|
250
|
+
amount: _acceptFundsFor({projectId: projectId, token: token, amount: amount, metadata: metadata}),
|
|
255
251
|
shouldReturnHeldFees: shouldReturnHeldFees,
|
|
256
252
|
memo: memo,
|
|
257
253
|
metadata: metadata
|
|
258
254
|
});
|
|
259
255
|
}
|
|
260
256
|
|
|
261
|
-
/// @notice
|
|
262
|
-
///
|
|
257
|
+
/// @notice Cash out project tokens. The project's current ruleset determines the reclaimed surplus and any data
|
|
258
|
+
/// hook or cash out hook behavior.
|
|
263
259
|
/// @dev Only the token holder or an operator with `CASH_OUT_TOKENS` permission from that holder can call this.
|
|
264
260
|
/// @param holder The account cashing out tokens.
|
|
265
261
|
/// @param projectId The ID of the project the project tokens belong to.
|
|
@@ -333,7 +329,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
333
329
|
if (split.hook != IJBSplitHook(address(0))) {
|
|
334
330
|
// Make sure that the address supports the split hook interface.
|
|
335
331
|
if (!split.hook.supportsInterface(type(IJBSplitHook).interfaceId)) {
|
|
336
|
-
revert JBMultiTerminal_SplitHookInvalid(split.hook);
|
|
332
|
+
revert JBMultiTerminal_SplitHookInvalid({hook: split.hook});
|
|
337
333
|
}
|
|
338
334
|
|
|
339
335
|
// This payout is eligible for a fee since the funds are leaving this contract and the split hook isn't a
|
|
@@ -373,7 +369,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
373
369
|
|
|
374
370
|
// The project must have a terminal to send funds to.
|
|
375
371
|
if (terminal == IJBTerminal(address(0))) {
|
|
376
|
-
revert JBMultiTerminal_RecipientProjectTerminalNotFound(split.projectId, token);
|
|
372
|
+
revert JBMultiTerminal_RecipientProjectTerminalNotFound({projectId: split.projectId, token: token});
|
|
377
373
|
}
|
|
378
374
|
|
|
379
375
|
// Fees apply to fund egress, not intra-terminal accounting. When both projects share this terminal,
|
|
@@ -412,7 +408,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
412
408
|
// Cross-project pay splits on the same terminal are allowed (different project receives the funds).
|
|
413
409
|
// The try-catch in the split group lib catches this revert and restores the balance.
|
|
414
410
|
if (terminal == this && split.projectId == projectId) {
|
|
415
|
-
revert JBMultiTerminal_MintNotAllowed(
|
|
411
|
+
revert JBMultiTerminal_MintNotAllowed({
|
|
412
|
+
projectId: projectId, splitProjectId: split.projectId, terminal: address(terminal)
|
|
413
|
+
});
|
|
416
414
|
}
|
|
417
415
|
|
|
418
416
|
// Keep a reference to the beneficiary of the payment.
|
|
@@ -432,7 +430,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
432
430
|
// destination project's data hook forwarded part of the payment to pay hooks, the store
|
|
433
431
|
// only recorded a partial balance increase. Without this cap, _feeFreeSurplusOf can exceed
|
|
434
432
|
// STORE.balanceOf, causing users to be overcharged fees on zero-tax cashouts.
|
|
435
|
-
// slither-disable-next-line reentrancy-eth
|
|
436
433
|
_capFeeFreeSurplus({projectId: split.projectId, token: token});
|
|
437
434
|
}
|
|
438
435
|
} else {
|
|
@@ -476,7 +473,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
476
473
|
require(msg.sender == address(this));
|
|
477
474
|
|
|
478
475
|
if (address(feeTerminal) == address(0)) {
|
|
479
|
-
revert JBMultiTerminal_FeeTerminalNotFound(token);
|
|
476
|
+
revert JBMultiTerminal_FeeTerminalNotFound({token: token});
|
|
480
477
|
}
|
|
481
478
|
|
|
482
479
|
// Send the projectId in the metadata.
|
|
@@ -540,7 +537,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
540
537
|
// sends fees to the fee project terminal. The migrated project's balance on this terminal is zero, but held
|
|
541
538
|
// fees are backed by the terminal's own token balance (not the project's recorded balance).
|
|
542
539
|
// Record the migration in the store.
|
|
543
|
-
// slither-disable-next-line reentrancy-events
|
|
544
540
|
balance = STORE.recordTerminalMigration({projectId: projectId, token: token});
|
|
545
541
|
|
|
546
542
|
emit MigrateTerminal({projectId: projectId, token: token, to: to, amount: balance, caller: _msgSender()});
|
|
@@ -569,8 +565,8 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
569
565
|
}
|
|
570
566
|
}
|
|
571
567
|
|
|
572
|
-
/// @notice Pay a project
|
|
573
|
-
///
|
|
568
|
+
/// @notice Pay a project. The project's current ruleset determines how many project tokens the beneficiary receives
|
|
569
|
+
/// and any data hook or pay hook behavior.
|
|
574
570
|
/// @param projectId The ID of the project to pay.
|
|
575
571
|
/// @param amount The amount of tokens to send, as a fixed point number with the same number of
|
|
576
572
|
/// decimals as the token's accounting context. If this terminal's token is native, this is ignored and `msg.value`
|
|
@@ -672,7 +668,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
672
668
|
_nextHeldFeeIndexOf[projectId][token] = currentIndex + 1;
|
|
673
669
|
|
|
674
670
|
// Process the fee.
|
|
675
|
-
// slither-disable-next-line reentrancy-no-eth
|
|
676
671
|
_processFee({
|
|
677
672
|
projectId: projectId,
|
|
678
673
|
token: token,
|
|
@@ -1022,7 +1017,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1022
1017
|
|
|
1023
1018
|
// Make sure the permit allowance is enough for this payment. If not we revert early.
|
|
1024
1019
|
if (amount > allowance.amount) {
|
|
1025
|
-
revert JBMultiTerminal_PermitAllowanceNotEnough(amount, allowance.amount);
|
|
1020
|
+
revert JBMultiTerminal_PermitAllowanceNotEnough({amount: amount, allowance: allowance.amount});
|
|
1026
1021
|
}
|
|
1027
1022
|
|
|
1028
1023
|
// Keep a reference to the permit rules.
|
|
@@ -1037,8 +1032,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1037
1032
|
// Set the allowance to `spend` tokens for the user.
|
|
1038
1033
|
try PERMIT2.permit({owner: _msgSender(), permitSingle: permitSingle, signature: allowance.signature}) {}
|
|
1039
1034
|
catch (bytes memory reason) {
|
|
1040
|
-
|
|
1041
|
-
emit Permit2AllowanceFailed(token, _msgSender(), reason);
|
|
1035
|
+
emit Permit2AllowanceFailed({token: token, owner: _msgSender(), reason: reason});
|
|
1042
1036
|
}
|
|
1043
1037
|
}
|
|
1044
1038
|
|
|
@@ -1121,7 +1115,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1121
1115
|
|
|
1122
1116
|
// Cap fee-free surplus at the remaining balance.
|
|
1123
1117
|
if (feeFreeSurplus > remainingBalance) {
|
|
1124
|
-
// slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
|
|
1125
1118
|
_feeFreeSurplusOf[projectId][token] = remainingBalance;
|
|
1126
1119
|
}
|
|
1127
1120
|
}
|
|
@@ -1202,7 +1195,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1202
1195
|
uint256 feeFreeSurplus = _feeFreeSurplusOf[projectId][tokenToReclaim];
|
|
1203
1196
|
if (feeFreeSurplus != 0) {
|
|
1204
1197
|
uint256 feeableAmount = reclaimAmount < feeFreeSurplus ? reclaimAmount : feeFreeSurplus;
|
|
1205
|
-
// slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
|
|
1206
1198
|
unchecked {
|
|
1207
1199
|
_feeFreeSurplusOf[projectId][tokenToReclaim] = feeFreeSurplus - feeableAmount;
|
|
1208
1200
|
}
|
|
@@ -1245,7 +1237,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1245
1237
|
// balance during a prior inbound payout), overcharging fees on round-trip prevention.
|
|
1246
1238
|
// Placed after hook fulfillment so any further balance reductions from cashout hooks are
|
|
1247
1239
|
// also accounted for.
|
|
1248
|
-
// slither-disable-next-line reentrancy-eth
|
|
1249
1240
|
_capFeeFreeSurplus({projectId: projectId, token: tokenToReclaim});
|
|
1250
1241
|
|
|
1251
1242
|
// Take the fee from all outbound reclaimings.
|
|
@@ -1347,12 +1338,10 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1347
1338
|
} else {
|
|
1348
1339
|
// Trigger any inherited pre-transfer logic.
|
|
1349
1340
|
// Keep a reference to the amount that'll be paid as a `msg.value`.
|
|
1350
|
-
// slither-disable-next-line reentrancy-events
|
|
1351
1341
|
uint256 payValue = _beforeTransferTo({to: address(terminal), token: token, amount: amount});
|
|
1352
1342
|
|
|
1353
1343
|
// Send the fee.
|
|
1354
1344
|
// If this terminal's token is ETH, send it in msg.value.
|
|
1355
|
-
// slither-disable-next-line unused-return
|
|
1356
1345
|
terminal.pay{value: payValue}({
|
|
1357
1346
|
projectId: projectId,
|
|
1358
1347
|
token: token,
|
|
@@ -1385,7 +1374,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1385
1374
|
{
|
|
1386
1375
|
// Trigger any inherited pre-transfer logic.
|
|
1387
1376
|
// Keep a reference to the amount that'll be paid as a `msg.value`.
|
|
1388
|
-
// slither-disable-next-line reentrancy-events
|
|
1389
1377
|
uint256 payValue = _beforeTransferTo({to: address(terminal), token: token, amount: amount});
|
|
1390
1378
|
|
|
1391
1379
|
// Add to balance on the recipient terminal.
|
|
@@ -1444,7 +1432,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1444
1432
|
cashOutMetadata: metadata
|
|
1445
1433
|
});
|
|
1446
1434
|
|
|
1447
|
-
// slither-disable-next-line calls-loop
|
|
1448
1435
|
for (uint256 i; i < specifications.length;) {
|
|
1449
1436
|
// Set the specification being iterated on.
|
|
1450
1437
|
JBCashOutHookSpecification memory specification = specifications[i];
|
|
@@ -1480,13 +1467,11 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1480
1467
|
|
|
1481
1468
|
// Trigger any inherited pre-transfer logic.
|
|
1482
1469
|
// Keep a reference to the amount that'll be paid as a `msg.value`.
|
|
1483
|
-
// slither-disable-next-line reentrancy-events
|
|
1484
1470
|
uint256 payValue = _beforeTransferTo({
|
|
1485
1471
|
to: address(specification.hook), token: beneficiaryReclaimAmount.token, amount: specification.amount
|
|
1486
1472
|
});
|
|
1487
1473
|
|
|
1488
1474
|
// Fulfill the specification.
|
|
1489
|
-
// slither-disable-next-line reentrancy-events,calls-loop
|
|
1490
1475
|
specification.hook.afterCashOutRecordedWith{value: payValue}(context);
|
|
1491
1476
|
|
|
1492
1477
|
// Revoke the temporary pull allowance now that the hook call has finished.
|
|
@@ -1541,7 +1526,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1541
1526
|
});
|
|
1542
1527
|
|
|
1543
1528
|
// Fulfill each specification through their pay hooks.
|
|
1544
|
-
// slither-disable-next-line calls-loop
|
|
1545
1529
|
for (uint256 i; i < specifications.length;) {
|
|
1546
1530
|
// Set the specification being iterated on.
|
|
1547
1531
|
JBPayHookSpecification memory specification = specifications[i];
|
|
@@ -1567,13 +1551,11 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1567
1551
|
|
|
1568
1552
|
// Trigger any inherited pre-transfer logic.
|
|
1569
1553
|
// Keep a reference to the amount that'll be paid as a `msg.value`.
|
|
1570
|
-
// slither-disable-next-line reentrancy-events
|
|
1571
1554
|
uint256 payValue = _beforeTransferTo({
|
|
1572
1555
|
to: address(specification.hook), token: tokenAmount.token, amount: specification.amount
|
|
1573
1556
|
});
|
|
1574
1557
|
|
|
1575
1558
|
// Fulfill the specification.
|
|
1576
|
-
// slither-disable-next-line reentrancy-events,calls-loop
|
|
1577
1559
|
specification.hook.afterPayRecordedWith{value: payValue}(context);
|
|
1578
1560
|
|
|
1579
1561
|
// Revoke the temporary pull allowance now that the hook call has finished.
|
|
@@ -1621,7 +1603,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1621
1603
|
// Keep a reference to the ruleset the payment is being made during.
|
|
1622
1604
|
// Keep a reference to the pay hook specifications.
|
|
1623
1605
|
// Keep a reference to the token count that'll be minted as a result of the payment.
|
|
1624
|
-
// slither-disable-next-line reentrancy-events
|
|
1625
1606
|
(JBRuleset memory ruleset, uint256 tokenCount, JBPayHookSpecification[] memory hookSpecifications) = STORE.recordPaymentFrom({
|
|
1626
1607
|
payer: payer, amount: tokenAmount, projectId: projectId, beneficiary: beneficiary, metadata: metadata
|
|
1627
1608
|
});
|
|
@@ -1633,7 +1614,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1633
1614
|
if (tokenCount != 0) {
|
|
1634
1615
|
// Set the token count to be the number of tokens minted for the beneficiary instead of the total
|
|
1635
1616
|
// amount.
|
|
1636
|
-
// slither-disable-next-line reentrancy-events
|
|
1637
1617
|
newlyIssuedTokenCount = _controllerOf(projectId)
|
|
1638
1618
|
.mintTokensOf({
|
|
1639
1619
|
projectId: projectId,
|
|
@@ -1689,7 +1669,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1689
1669
|
)
|
|
1690
1670
|
internal
|
|
1691
1671
|
{
|
|
1692
|
-
// slither-disable-next-line reentrancy-events,calls-loop
|
|
1693
1672
|
try this.executeProcessFee({
|
|
1694
1673
|
projectId: projectId, token: token, amount: amount, beneficiary: beneficiary, feeTerminal: feeTerminal
|
|
1695
1674
|
}) {
|
|
@@ -1726,7 +1705,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1726
1705
|
/// this
|
|
1727
1706
|
/// terminal.
|
|
1728
1707
|
function _recordAddedBalanceFor(uint256 projectId, address token, uint256 amount) internal {
|
|
1729
|
-
// slither-disable-next-line calls-loop
|
|
1730
1708
|
STORE.recordAddedBalanceFor({projectId: projectId, token: token, amount: amount});
|
|
1731
1709
|
}
|
|
1732
1710
|
|
|
@@ -1763,7 +1741,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1763
1741
|
// Save the fee being iterated on.
|
|
1764
1742
|
JBFee memory heldFee = _heldFeesOf[projectId][token][startIndex + i];
|
|
1765
1743
|
|
|
1766
|
-
// slither-disable-next-line incorrect-equality
|
|
1767
1744
|
if (leftoverAmount == 0) {
|
|
1768
1745
|
break;
|
|
1769
1746
|
} else {
|
|
@@ -1782,9 +1759,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1782
1759
|
// Move the start index forward to the held fee after the current one.
|
|
1783
1760
|
newStartIndex = startIndex + i + 1;
|
|
1784
1761
|
} else {
|
|
1785
|
-
|
|
1786
|
-
// splitting an already-held fee entry across repayments.
|
|
1787
|
-
feeAmount = JBFees.feeAmountResultingInFloorForFee25(leftoverAmount);
|
|
1762
|
+
feeAmount = JBFees.feeAmountResultingIn({amountAfterFee: leftoverAmount, feePercent: FEE});
|
|
1788
1763
|
|
|
1789
1764
|
// Get fee from `leftoverAmount`.
|
|
1790
1765
|
unchecked {
|
|
@@ -1883,7 +1858,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1883
1858
|
leftoverPayoutAmount = netLeftoverPayoutAmount;
|
|
1884
1859
|
}
|
|
1885
1860
|
} catch (bytes memory reason) {
|
|
1886
|
-
// slither-disable-next-line reentrancy-events
|
|
1887
1861
|
emit PayoutTransferReverted({
|
|
1888
1862
|
projectId: projectId,
|
|
1889
1863
|
addr: projectOwner,
|
|
@@ -1901,7 +1875,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1901
1875
|
|
|
1902
1876
|
// Cap fee-free surplus at remaining balance. Non-fee-free funds leave first.
|
|
1903
1877
|
// Placed after all payouts settle so the cap reflects post-payout state.
|
|
1904
|
-
// slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
|
|
1905
1878
|
_capFeeFreeSurplus({projectId: projectId, token: token});
|
|
1906
1879
|
|
|
1907
1880
|
// Take the fee.
|
|
@@ -2047,12 +2020,10 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
2047
2020
|
STORE.recordUsedAllowanceOf({projectId: projectId, token: token, amount: amount, currency: currency});
|
|
2048
2021
|
|
|
2049
2022
|
// Cap fee-free surplus at remaining balance. Non-fee-free funds leave first.
|
|
2050
|
-
// slither-disable-next-line reentrancy-no-eth,reentrancy-eth,reentrancy-benign
|
|
2051
2023
|
_capFeeFreeSurplus({projectId: projectId, token: token});
|
|
2052
2024
|
|
|
2053
2025
|
// Take a fee from the `amountPaidOut`, if needed.
|
|
2054
2026
|
// The net amount is the final amount withdrawn after the fee has been taken.
|
|
2055
|
-
// slither-disable-next-line reentrancy-events
|
|
2056
2027
|
netAmountPaidOut = amountPaidOut
|
|
2057
2028
|
- (_isFeeless(owner) || _isFeeless(beneficiary)
|
|
2058
2029
|
? 0
|
|
@@ -2097,7 +2068,6 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
2097
2068
|
if (token == JBConstants.NATIVE_TOKEN) return;
|
|
2098
2069
|
|
|
2099
2070
|
// Revert if the callee returned without consuming the full forwarded ERC-20 amount.
|
|
2100
|
-
// slither-disable-next-line calls-loop
|
|
2101
2071
|
uint256 allowance = IERC20(token).allowance({owner: address(this), spender: to});
|
|
2102
2072
|
if (allowance != 0) revert JBMultiTerminal_TemporaryAllowanceNotConsumed(token, to, allowance);
|
|
2103
2073
|
}
|
|
@@ -2202,12 +2172,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
2202
2172
|
//*********************************************************************//
|
|
2203
2173
|
|
|
2204
2174
|
/// @notice The terminal fee charged from a pre-fee `amount`.
|
|
2205
|
-
/// @dev Returns at least 1 for nonzero feeable amounts so dust payouts cannot bypass protocol fees.
|
|
2206
2175
|
/// @param amount The amount before the fee is applied.
|
|
2207
|
-
/// @return
|
|
2208
|
-
function _feeAmountFrom(uint256 amount) private pure returns (uint256
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
return feeAmount == 0 && amount != 0 ? 1 : feeAmount;
|
|
2176
|
+
/// @return The fee amount.
|
|
2177
|
+
function _feeAmountFrom(uint256 amount) private pure returns (uint256) {
|
|
2178
|
+
return JBFees.feeAmountFrom({amountBeforeFee: amount, feePercent: FEE});
|
|
2212
2179
|
}
|
|
2213
2180
|
}
|
package/src/JBPermissions.sol
CHANGED
|
@@ -17,8 +17,7 @@ contract JBPermissions is ERC2771Context, IJBPermissions {
|
|
|
17
17
|
// --------------------------- custom errors ------------------------- //
|
|
18
18
|
//*********************************************************************//
|
|
19
19
|
|
|
20
|
-
error
|
|
21
|
-
error JBPermissions_NoZeroPermission();
|
|
20
|
+
error JBPermissions_NoZeroPermission(address account, address operator, uint256 projectId);
|
|
22
21
|
error JBPermissions_PermissionIdOutOfBounds(uint256 permissionId);
|
|
23
22
|
error JBPermissions_Unauthorized(address account, address operator, uint256 projectId, uint256 permissionId);
|
|
24
23
|
|
|
@@ -69,7 +68,11 @@ contract JBPermissions is ERC2771Context, IJBPermissions {
|
|
|
69
68
|
uint256 packed = _packedPermissions(permissionsData.permissionIds);
|
|
70
69
|
|
|
71
70
|
// Make sure the 0 permission is not set.
|
|
72
|
-
if (_includesPermission({permissions: packed, permissionId: 0}))
|
|
71
|
+
if (_includesPermission({permissions: packed, permissionId: 0})) {
|
|
72
|
+
revert JBPermissions_NoZeroPermission({
|
|
73
|
+
account: account, operator: permissionsData.operator, projectId: permissionsData.projectId
|
|
74
|
+
});
|
|
75
|
+
}
|
|
73
76
|
|
|
74
77
|
// Cache the sender.
|
|
75
78
|
address msgSender = _msgSender();
|
package/src/JBPrices.sol
CHANGED
|
@@ -26,9 +26,9 @@ contract JBPrices is JBControlled, JBPermissioned, ERC2771Context, Ownable, IJBP
|
|
|
26
26
|
//*********************************************************************//
|
|
27
27
|
|
|
28
28
|
error JBPrices_PriceFeedAlreadyExists(IJBPriceFeed feed);
|
|
29
|
-
error JBPrices_PriceFeedNotFound();
|
|
30
|
-
error JBPrices_ZeroPricingCurrency();
|
|
31
|
-
error JBPrices_ZeroUnitCurrency();
|
|
29
|
+
error JBPrices_PriceFeedNotFound(uint256 projectId, uint256 pricingCurrency, uint256 unitCurrency);
|
|
30
|
+
error JBPrices_ZeroPricingCurrency(uint256 projectId, uint256 pricingCurrency);
|
|
31
|
+
error JBPrices_ZeroUnitCurrency(uint256 projectId, uint256 unitCurrency);
|
|
32
32
|
|
|
33
33
|
//*********************************************************************//
|
|
34
34
|
// ------------------------- public constants ------------------------ //
|
|
@@ -111,20 +111,23 @@ contract JBPrices is JBControlled, JBPermissioned, ERC2771Context, Ownable, IJBP
|
|
|
111
111
|
projectId == DEFAULT_PROJECT_ID ? _checkOwner() : _onlyControllerOf(projectId);
|
|
112
112
|
|
|
113
113
|
// Make sure the pricing currency isn't 0.
|
|
114
|
-
if (pricingCurrency == 0)
|
|
114
|
+
if (pricingCurrency == 0) {
|
|
115
|
+
revert JBPrices_ZeroPricingCurrency({projectId: projectId, pricingCurrency: pricingCurrency});
|
|
116
|
+
}
|
|
115
117
|
|
|
116
118
|
// Make sure the unit currency isn't 0.
|
|
117
|
-
if (unitCurrency == 0) revert JBPrices_ZeroUnitCurrency();
|
|
119
|
+
if (unitCurrency == 0) revert JBPrices_ZeroUnitCurrency({projectId: projectId, unitCurrency: unitCurrency});
|
|
118
120
|
|
|
119
121
|
// Make sure there isn't already a default price feed for the pair or its inverse.
|
|
120
122
|
if (
|
|
121
123
|
priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
|
|
122
124
|
|| priceFeedFor[DEFAULT_PROJECT_ID][unitCurrency][pricingCurrency] != IJBPriceFeed(address(0))
|
|
123
125
|
) {
|
|
124
|
-
revert JBPrices_PriceFeedAlreadyExists(
|
|
125
|
-
|
|
126
|
+
revert JBPrices_PriceFeedAlreadyExists({
|
|
127
|
+
feed: priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
|
|
126
128
|
? priceFeedFor[DEFAULT_PROJECT_ID][pricingCurrency][unitCurrency]
|
|
127
|
-
: priceFeedFor[DEFAULT_PROJECT_ID][unitCurrency][pricingCurrency]
|
|
129
|
+
: priceFeedFor[DEFAULT_PROJECT_ID][unitCurrency][pricingCurrency]
|
|
130
|
+
});
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
// Make sure this project doesn't already have a price feed for the pair or its inverse.
|
|
@@ -132,10 +135,11 @@ contract JBPrices is JBControlled, JBPermissioned, ERC2771Context, Ownable, IJBP
|
|
|
132
135
|
priceFeedFor[projectId][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
|
|
133
136
|
|| priceFeedFor[projectId][unitCurrency][pricingCurrency] != IJBPriceFeed(address(0))
|
|
134
137
|
) {
|
|
135
|
-
revert JBPrices_PriceFeedAlreadyExists(
|
|
136
|
-
|
|
138
|
+
revert JBPrices_PriceFeedAlreadyExists({
|
|
139
|
+
feed: priceFeedFor[projectId][pricingCurrency][unitCurrency] != IJBPriceFeed(address(0))
|
|
137
140
|
? priceFeedFor[projectId][pricingCurrency][unitCurrency]
|
|
138
|
-
: priceFeedFor[projectId][unitCurrency][pricingCurrency]
|
|
141
|
+
: priceFeedFor[projectId][unitCurrency][pricingCurrency]
|
|
142
|
+
});
|
|
139
143
|
}
|
|
140
144
|
|
|
141
145
|
// Price feed immutability is by design to prevent admin-key attacks on price oracles.
|
|
@@ -212,7 +216,9 @@ contract JBPrices is JBControlled, JBPermissioned, ERC2771Context, Ownable, IJBP
|
|
|
212
216
|
}
|
|
213
217
|
|
|
214
218
|
// No price feed available, revert.
|
|
215
|
-
revert JBPrices_PriceFeedNotFound(
|
|
219
|
+
revert JBPrices_PriceFeedNotFound({
|
|
220
|
+
projectId: projectId, pricingCurrency: pricingCurrency, unitCurrency: unitCurrency
|
|
221
|
+
});
|
|
216
222
|
}
|
|
217
223
|
|
|
218
224
|
//*********************************************************************//
|
package/src/JBRulesets.sol
CHANGED
|
@@ -123,7 +123,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
123
123
|
|
|
124
124
|
// Weight cut percent must be less than or equal to 100%.
|
|
125
125
|
if (weightCutPercent > JBConstants.MAX_WEIGHT_CUT_PERCENT) {
|
|
126
|
-
revert JBRulesets_InvalidWeightCutPercent(weightCutPercent);
|
|
126
|
+
revert JBRulesets_InvalidWeightCutPercent({percent: weightCutPercent});
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
// Weight must fit into a uint112.
|
|
@@ -137,7 +137,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
137
137
|
// Make sure the min start date fits in a uint48, and that the start date of the following ruleset will also fit
|
|
138
138
|
// within the max.
|
|
139
139
|
if (mustStartAtOrAfter + duration > type(uint48).max) {
|
|
140
|
-
revert JBRulesets_InvalidRulesetEndTime(mustStartAtOrAfter + duration, type(uint48).max);
|
|
140
|
+
revert JBRulesets_InvalidRulesetEndTime({timestamp: mustStartAtOrAfter + duration, limit: type(uint48).max});
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
// Approval hook should be a valid contract, supporting the correct interface
|
|
@@ -152,7 +152,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
152
152
|
// with the
|
|
153
153
|
// wrong interface
|
|
154
154
|
} catch {
|
|
155
|
-
revert JBRulesets_InvalidRulesetApprovalHook(approvalHook); // No ERC165 support
|
|
155
|
+
revert JBRulesets_InvalidRulesetApprovalHook({hook: approvalHook}); // No ERC165 support
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
@@ -217,7 +217,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
217
217
|
_getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: false});
|
|
218
218
|
|
|
219
219
|
// Nothing to cache if the target ruleset doesn't have a duration or a weight cut percent.
|
|
220
|
-
// slither-disable-next-line incorrect-equality
|
|
221
220
|
if (targetRuleset.duration == 0 || targetRuleset.weightCutPercent == 0) return;
|
|
222
221
|
|
|
223
222
|
// Get a reference to the current cache.
|
|
@@ -356,7 +355,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
356
355
|
/// @return ruleset The project's current ruleset.
|
|
357
356
|
function currentOf(uint256 projectId) external view override returns (JBRuleset memory ruleset) {
|
|
358
357
|
// If the project does not have a ruleset, return an empty struct.
|
|
359
|
-
// slither-disable-next-line incorrect-equality
|
|
360
358
|
if (latestRulesetIdOf[projectId] == 0) {
|
|
361
359
|
return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
|
|
362
360
|
}
|
|
@@ -375,7 +373,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
375
373
|
|
|
376
374
|
// Check to see if this ruleset's approval hook is approved if it exists.
|
|
377
375
|
// If so, return it.
|
|
378
|
-
// slither-disable-next-line incorrect-equality
|
|
379
376
|
if (approvalStatus == JBApprovalStatus.Approved || approvalStatus == JBApprovalStatus.Empty) {
|
|
380
377
|
return ruleset;
|
|
381
378
|
}
|
|
@@ -413,7 +410,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
413
410
|
}
|
|
414
411
|
|
|
415
412
|
// If the base has no duration, it's still the current one.
|
|
416
|
-
// slither-disable-next-line incorrect-equality
|
|
417
413
|
if (ruleset.duration == 0) return ruleset;
|
|
418
414
|
|
|
419
415
|
// Return a simulation of the current ruleset.
|
|
@@ -466,7 +462,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
466
462
|
/// @return ruleset The struct for the project's upcoming ruleset.
|
|
467
463
|
function upcomingOf(uint256 projectId) external view override returns (JBRuleset memory ruleset) {
|
|
468
464
|
// If the project does not have a latest ruleset, return an empty struct.
|
|
469
|
-
// slither-disable-next-line incorrect-equality
|
|
470
465
|
if (latestRulesetIdOf[projectId] == 0) {
|
|
471
466
|
return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
|
|
472
467
|
}
|
|
@@ -487,7 +482,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
487
482
|
|
|
488
483
|
// If the approval hook is empty, expects approval, or has approved the ruleset, return it.
|
|
489
484
|
if (
|
|
490
|
-
// slither-disable-next-line incorrect-equality
|
|
491
485
|
approvalStatus == JBApprovalStatus.Approved || approvalStatus == JBApprovalStatus.ApprovalExpected
|
|
492
486
|
|| approvalStatus == JBApprovalStatus.Empty
|
|
493
487
|
) return ruleset;
|
|
@@ -510,7 +504,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
510
504
|
}
|
|
511
505
|
|
|
512
506
|
// There's no queued if the current has a duration of 0.
|
|
513
|
-
// slither-disable-next-line incorrect-equality
|
|
514
507
|
if (ruleset.duration == 0) return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
|
|
515
508
|
|
|
516
509
|
// Get a reference to the approval status.
|
|
@@ -518,7 +511,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
518
511
|
|
|
519
512
|
// Check to see if this ruleset's approval hook hasn't failed.
|
|
520
513
|
// If so, return a ruleset based on it.
|
|
521
|
-
// slither-disable-next-line incorrect-equality
|
|
522
514
|
if (approvalStatus == JBApprovalStatus.Approved || approvalStatus == JBApprovalStatus.Empty) {
|
|
523
515
|
return _simulateCycledRulesetBasedOn({projectId: projectId, baseRuleset: ruleset, allowMidRuleset: false});
|
|
524
516
|
}
|
|
@@ -528,7 +520,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
528
520
|
ruleset = _getStructFor({projectId: projectId, rulesetId: ruleset.basedOnId, withMetadata: true});
|
|
529
521
|
|
|
530
522
|
// There's no queued if the base, which must still be the current, has a duration of 0.
|
|
531
|
-
// slither-disable-next-line incorrect-equality
|
|
532
523
|
if (ruleset.duration == 0) return _getStructFor({projectId: 0, rulesetId: 0, withMetadata: false});
|
|
533
524
|
|
|
534
525
|
// Return a simulated cycled ruleset.
|
|
@@ -557,7 +548,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
557
548
|
returns (uint256)
|
|
558
549
|
{
|
|
559
550
|
// A subsequent ruleset to one with a duration of 0 should be the next number.
|
|
560
|
-
// slither-disable-next-line incorrect-equality
|
|
561
551
|
if (baseRulesetDuration == 0) {
|
|
562
552
|
return baseRulesetCycleNumber + 1;
|
|
563
553
|
}
|
|
@@ -585,7 +575,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
585
575
|
returns (uint256 start)
|
|
586
576
|
{
|
|
587
577
|
// A subsequent ruleset to one with a duration of 0 should start as soon as possible.
|
|
588
|
-
// slither-disable-next-line incorrect-equality
|
|
589
578
|
if (baseRulesetDuration == 0) return mustStartAtOrAfter;
|
|
590
579
|
|
|
591
580
|
// The time when the ruleset immediately after the specified ruleset starts.
|
|
@@ -598,7 +587,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
598
587
|
|
|
599
588
|
// The amount of seconds since the `mustStartAtOrAfter` time which results in a start time that might satisfy
|
|
600
589
|
// the specified limits.
|
|
601
|
-
// slither-disable-next-line weak-prng
|
|
602
590
|
uint256 timeFromImmediateStartMultiple = (mustStartAtOrAfter - nextImmediateStart) % baseRulesetDuration;
|
|
603
591
|
|
|
604
592
|
// A reference to the first possible start timestamp.
|
|
@@ -634,7 +622,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
634
622
|
returns (uint256 weight)
|
|
635
623
|
{
|
|
636
624
|
// A subsequent ruleset to one with a duration of 0 should have the next possible weight.
|
|
637
|
-
// slither-disable-next-line incorrect-equality
|
|
638
625
|
if (baseRulesetDuration == 0) {
|
|
639
626
|
return mulDiv(
|
|
640
627
|
baseRulesetWeight,
|
|
@@ -647,7 +634,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
647
634
|
weight = baseRulesetWeight;
|
|
648
635
|
|
|
649
636
|
// If the weight cut percent is 0, the weight doesn't change.
|
|
650
|
-
// slither-disable-next-line incorrect-equality
|
|
651
637
|
if (baseRulesetWeightCutPercent == 0) return weight;
|
|
652
638
|
|
|
653
639
|
// The difference between the start of the base ruleset and the proposed start.
|
|
@@ -678,7 +664,7 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
678
664
|
// If too many iterations remain after cache lookup, require the cache to be populated first.
|
|
679
665
|
// This prevents gas exhaustion for short-duration rulesets with large cycle counts.
|
|
680
666
|
if (weightCutMultiple > _WEIGHT_CUT_MULTIPLE_CACHE_LOOKUP_THRESHOLD) {
|
|
681
|
-
revert JBRulesets_WeightCacheRequired(projectId);
|
|
667
|
+
revert JBRulesets_WeightCacheRequired({projectId: projectId});
|
|
682
668
|
}
|
|
683
669
|
|
|
684
670
|
// Cache the cut factor and max percent to avoid recomputing each iteration.
|
|
@@ -719,7 +705,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
719
705
|
uint256 latestId = latestRulesetIdOf[projectId];
|
|
720
706
|
|
|
721
707
|
// If the project doesn't have a ruleset yet, initialize one.
|
|
722
|
-
// slither-disable-next-line incorrect-equality
|
|
723
708
|
if (latestId == 0) {
|
|
724
709
|
// Use an empty ruleset as the base.
|
|
725
710
|
return _initializeRulesetFor({
|
|
@@ -807,7 +792,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
807
792
|
internal
|
|
808
793
|
{
|
|
809
794
|
// If there is no base, initialize a first ruleset.
|
|
810
|
-
// slither-disable-next-line incorrect-equality
|
|
811
795
|
if (baseRuleset.cycleNumber == 0) {
|
|
812
796
|
// Set fresh intrinsic properties.
|
|
813
797
|
_packAndStoreIntrinsicPropertiesOf({
|
|
@@ -910,7 +894,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
910
894
|
/// @return The approval status of the project.
|
|
911
895
|
function _approvalStatusOf(uint256 projectId, JBRuleset memory ruleset) internal view returns (JBApprovalStatus) {
|
|
912
896
|
// If there is no ruleset ID to check the approval hook of, the approval hook is empty.
|
|
913
|
-
// slither-disable-next-line incorrect-equality
|
|
914
897
|
if (ruleset.basedOnId == 0) return JBApprovalStatus.Empty;
|
|
915
898
|
|
|
916
899
|
// Read only the packed user properties to extract the approval hook address,
|
|
@@ -928,7 +911,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
928
911
|
// Wrap in try/catch to prevent a reverting approval hook from permanently freezing the project.
|
|
929
912
|
// Note: A malicious hook that consumes all gas (e.g. infinite loop) could still DoS via gas exhaustion.
|
|
930
913
|
// This is accepted risk since the project owner chose their own approval hook.
|
|
931
|
-
// slither-disable-next-line calls-loop
|
|
932
914
|
try approvalHook.approvalStatusOf({projectId: projectId, ruleset: ruleset}) returns (JBApprovalStatus status) {
|
|
933
915
|
return status;
|
|
934
916
|
} catch {
|
|
@@ -988,7 +970,6 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
988
970
|
returns (JBRuleset memory ruleset)
|
|
989
971
|
{
|
|
990
972
|
// Return an empty ruleset if the specified `rulesetId` is 0.
|
|
991
|
-
// slither-disable-next-line incorrect-equality
|
|
992
973
|
if (rulesetId == 0) return ruleset;
|
|
993
974
|
|
|
994
975
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
@@ -1104,12 +1085,10 @@ contract JBRulesets is JBControlled, IJBRulesets {
|
|
|
1104
1085
|
JBRuleset memory ruleset = _getStructFor({projectId: projectId, rulesetId: rulesetId, withMetadata: false});
|
|
1105
1086
|
|
|
1106
1087
|
// There is no upcoming ruleset if the latest ruleset has already started.
|
|
1107
|
-
// slither-disable-next-line incorrect-equality
|
|
1108
1088
|
// forge-lint: disable-next-line(block-timestamp)
|
|
1109
1089
|
if (block.timestamp >= ruleset.start) return 0;
|
|
1110
1090
|
|
|
1111
1091
|
// If this is the first ruleset, it is queued.
|
|
1112
|
-
// slither-disable-next-line incorrect-equality
|
|
1113
1092
|
if (ruleset.cycleNumber == 1) return rulesetId;
|
|
1114
1093
|
|
|
1115
1094
|
// Get a reference to the ID of the ruleset the latest ruleset was based on.
|
package/src/JBSplits.sol
CHANGED
|
@@ -20,8 +20,8 @@ contract JBSplits is JBControlled, IJBSplits {
|
|
|
20
20
|
//*********************************************************************//
|
|
21
21
|
|
|
22
22
|
error JBSplits_PreviousLockedSplitsNotIncluded(uint256 projectId, uint256 rulesetId);
|
|
23
|
-
error JBSplits_TotalPercentExceeds100();
|
|
24
|
-
error JBSplits_ZeroSplitPercent();
|
|
23
|
+
error JBSplits_TotalPercentExceeds100(uint256 projectId, uint256 rulesetId, uint256 groupId, uint256 percentTotal);
|
|
24
|
+
error JBSplits_ZeroSplitPercent(uint256 projectId, uint256 rulesetId, uint256 groupId, uint256 splitIndex);
|
|
25
25
|
|
|
26
26
|
//*********************************************************************//
|
|
27
27
|
// ------------------------- public constants ------------------------ //
|
|
@@ -180,7 +180,7 @@ contract JBSplits is JBControlled, IJBSplits {
|
|
|
180
180
|
block.timestamp < currentSplits[i].lockedUntil
|
|
181
181
|
&& !_includesLockedSplits({splits: splits, lockedSplit: currentSplits[i]})
|
|
182
182
|
) {
|
|
183
|
-
revert JBSplits_PreviousLockedSplitsNotIncluded(projectId, rulesetId);
|
|
183
|
+
revert JBSplits_PreviousLockedSplitsNotIncluded({projectId: projectId, rulesetId: rulesetId});
|
|
184
184
|
}
|
|
185
185
|
unchecked {
|
|
186
186
|
++i;
|
|
@@ -198,13 +198,21 @@ contract JBSplits is JBControlled, IJBSplits {
|
|
|
198
198
|
JBSplit memory split = splits[i];
|
|
199
199
|
|
|
200
200
|
// The percent should be greater than 0.
|
|
201
|
-
if (split.percent == 0)
|
|
201
|
+
if (split.percent == 0) {
|
|
202
|
+
revert JBSplits_ZeroSplitPercent({
|
|
203
|
+
projectId: projectId, rulesetId: rulesetId, groupId: groupId, splitIndex: i
|
|
204
|
+
});
|
|
205
|
+
}
|
|
202
206
|
|
|
203
207
|
// Add to the `percent` total.
|
|
204
208
|
percentTotal += split.percent;
|
|
205
209
|
|
|
206
210
|
// Ensure the total does not exceed 100%.
|
|
207
|
-
if (percentTotal > JBConstants.SPLITS_TOTAL_PERCENT)
|
|
211
|
+
if (percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) {
|
|
212
|
+
revert JBSplits_TotalPercentExceeds100({
|
|
213
|
+
projectId: projectId, rulesetId: rulesetId, groupId: groupId, percentTotal: percentTotal
|
|
214
|
+
});
|
|
215
|
+
}
|
|
208
216
|
|
|
209
217
|
uint256 packedSplitParts1;
|
|
210
218
|
|