@bananapus/core-v6 0.0.68 → 0.0.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -89,7 +89,7 @@ Use this file when you need deeper protocol reference material after the repo-lo
|
|
|
89
89
|
- `JBERC20` is cloned via `Clones.clone()` -- its constructor sets invalid name/symbol; real values set in `initialize()`
|
|
90
90
|
- Fee is 2.5% (`FEE = 25` out of `MAX_FEE = 1000`)
|
|
91
91
|
- Project #1 is the fee beneficiary project (receives all protocol fees)
|
|
92
|
-
- **Fee-free cashout exemption is scoped to fee-free intra-terminal payout amounts.** `
|
|
92
|
+
- **Fee-free cashout exemption is scoped to fee-free intra-terminal payout amounts.** `feeFreeSurplusOf[projectId][token]` accumulates the value of fee-free payouts. After any outflow (payouts, `useAllowanceOf`, non-zero-tax or feeless cashouts), the counter is capped at the remaining balance — non-fee-free funds leave first, preserving the fee-free counter. During cashout with `cashOutTaxRate=0`, the 2.5% fee applies only up to this surplus, then depletes. Once consumed, subsequent cashouts are fee-free again. Cleared on terminal migration. This prevents a round-trip fee bypass (intra-terminal payout → zero-tax cashout) while scoping fees precisely to the fee-free inflow.
|
|
93
93
|
- `JBProjects` constructor optionally mints project #1 to `feeProjectOwner` -- if `address(0)`, no fee project is created
|
|
94
94
|
- `JBMultiTerminal` derives `DIRECTORY` from the provided `store` in its constructor -- not passed directly
|
|
95
95
|
- `JBPrices.pricePerUnitOf()` checks project direct feeds, project inverse feeds, default direct feeds, then default inverse feeds. It skips feeds that revert or return zero.
|
package/src/JBMultiTerminal.sol
CHANGED
|
@@ -111,7 +111,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
111
111
|
IJBTokens public immutable override TOKENS;
|
|
112
112
|
|
|
113
113
|
//*********************************************************************//
|
|
114
|
-
// ---------------------
|
|
114
|
+
// --------------------- public stored properties -------------------- //
|
|
115
115
|
//*********************************************************************//
|
|
116
116
|
|
|
117
117
|
/// @notice The cumulative amount of fee-free intra-terminal payouts a project has received for a given token.
|
|
@@ -126,7 +126,11 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
126
126
|
/// unconsumed balance. There is no admin function to reset it.
|
|
127
127
|
/// @custom:param projectId The ID of the project that received the payout.
|
|
128
128
|
/// @custom:param token The token that was received.
|
|
129
|
-
mapping(uint256 projectId => mapping(address token => uint256))
|
|
129
|
+
mapping(uint256 projectId => mapping(address token => uint256)) public override feeFreeSurplusOf;
|
|
130
|
+
|
|
131
|
+
//*********************************************************************//
|
|
132
|
+
// --------------------- internal stored properties ------------------ //
|
|
133
|
+
//*********************************************************************//
|
|
130
134
|
|
|
131
135
|
/// @notice Fees currently held for each project.
|
|
132
136
|
/// @dev Projects can temporarily hold fees and unlock them later by adding funds to the project's balance.
|
|
@@ -447,7 +451,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
447
451
|
|
|
448
452
|
// Same-terminal adds never invoke destination pay hooks, so the full amount remains in the
|
|
449
453
|
// destination project's balance and must be fee-liable on its later zero-tax cashout.
|
|
450
|
-
if (isThisTerminal)
|
|
454
|
+
if (isThisTerminal) feeFreeSurplusOf[split.projectId][token] += netPayoutAmount;
|
|
451
455
|
} else {
|
|
452
456
|
// Keep a reference to the beneficiary of the payment.
|
|
453
457
|
address beneficiary = split.beneficiary != address(0) ? split.beneficiary : originalMessageSender;
|
|
@@ -592,7 +596,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
592
596
|
}
|
|
593
597
|
|
|
594
598
|
// Clear fee-free surplus tracking — the fee-free liability is settled by the migration fee below.
|
|
595
|
-
delete
|
|
599
|
+
delete feeFreeSurplusOf[projectId][token];
|
|
596
600
|
|
|
597
601
|
// Terminal migration intentionally does not transfer held fees. Held fees belong to the
|
|
598
602
|
// fee beneficiary (project #1), not the migrating project. They unlock after 28 days regardless of terminal.
|
|
@@ -672,7 +676,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
672
676
|
returns (uint256 beneficiaryTokenCount)
|
|
673
677
|
{
|
|
674
678
|
// Get a reference to the beneficiary's balance before the payment.
|
|
675
|
-
uint256 beneficiaryBalanceBefore =
|
|
679
|
+
uint256 beneficiaryBalanceBefore = _totalBalanceOf({holder: beneficiary, projectId: projectId});
|
|
676
680
|
|
|
677
681
|
// Accept the funds.
|
|
678
682
|
uint256 acceptedAmount =
|
|
@@ -690,7 +694,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
690
694
|
});
|
|
691
695
|
|
|
692
696
|
// Get a reference to the beneficiary's balance after the payment.
|
|
693
|
-
uint256 beneficiaryBalanceAfter =
|
|
697
|
+
uint256 beneficiaryBalanceAfter = _totalBalanceOf({holder: beneficiary, projectId: projectId});
|
|
694
698
|
|
|
695
699
|
// Set the beneficiary token count.
|
|
696
700
|
if (beneficiaryBalanceAfter > beneficiaryBalanceBefore) {
|
|
@@ -1213,7 +1217,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1213
1217
|
/// @param token The token whose fee-free surplus to cap.
|
|
1214
1218
|
function _capFeeFreeSurplus(uint256 projectId, address token) internal {
|
|
1215
1219
|
// Get the current fee-free surplus for this project/token pair.
|
|
1216
|
-
uint256 feeFreeSurplus =
|
|
1220
|
+
uint256 feeFreeSurplus = feeFreeSurplusOf[projectId][token];
|
|
1217
1221
|
|
|
1218
1222
|
// Nothing to cap if there's no fee-free surplus tracked.
|
|
1219
1223
|
if (feeFreeSurplus == 0) return;
|
|
@@ -1223,7 +1227,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1223
1227
|
|
|
1224
1228
|
// Cap fee-free surplus at the remaining balance.
|
|
1225
1229
|
if (feeFreeSurplus > remainingBalance) {
|
|
1226
|
-
|
|
1230
|
+
feeFreeSurplusOf[projectId][token] = remainingBalance;
|
|
1227
1231
|
}
|
|
1228
1232
|
}
|
|
1229
1233
|
|
|
@@ -1300,11 +1304,11 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1300
1304
|
}
|
|
1301
1305
|
} else {
|
|
1302
1306
|
// Zero tax: fees apply only up to the fee-free surplus (round-trip prevention).
|
|
1303
|
-
uint256 feeFreeSurplus =
|
|
1307
|
+
uint256 feeFreeSurplus = feeFreeSurplusOf[projectId][tokenToReclaim];
|
|
1304
1308
|
if (feeFreeSurplus != 0) {
|
|
1305
1309
|
uint256 feeableAmount = reclaimAmount < feeFreeSurplus ? reclaimAmount : feeFreeSurplus;
|
|
1306
1310
|
unchecked {
|
|
1307
|
-
|
|
1311
|
+
feeFreeSurplusOf[projectId][tokenToReclaim] = feeFreeSurplus - feeableAmount;
|
|
1308
1312
|
}
|
|
1309
1313
|
amountEligibleForFees += feeableAmount;
|
|
1310
1314
|
unchecked {
|
|
@@ -1338,7 +1342,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1338
1342
|
});
|
|
1339
1343
|
}
|
|
1340
1344
|
|
|
1341
|
-
// Cap fee-free surplus after every cash-out path so stale `
|
|
1345
|
+
// Cap fee-free surplus after every cash-out path so stale `feeFreeSurplusOf` cannot survive after
|
|
1342
1346
|
// associated surplus leaves. Do this after hook fulfillment so hook-driven balance reductions are included.
|
|
1343
1347
|
_capFeeFreeSurplus({projectId: projectId, token: tokenToReclaim});
|
|
1344
1348
|
|
|
@@ -1788,7 +1792,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1788
1792
|
++i;
|
|
1789
1793
|
}
|
|
1790
1794
|
}
|
|
1791
|
-
|
|
1795
|
+
feeFreeSurplusOf[projectId][token] += feeFreeAmount;
|
|
1792
1796
|
}
|
|
1793
1797
|
|
|
1794
1798
|
// Keep a reference to the number of tokens issued for the beneficiary.
|
|
@@ -1885,7 +1889,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
1885
1889
|
_recordAddedBalanceFor({projectId: projectId, token: token, amount: amount});
|
|
1886
1890
|
// The store balance was credited first; this mirrors that bounded increase for fee recovery.
|
|
1887
1891
|
unchecked {
|
|
1888
|
-
|
|
1892
|
+
feeFreeSurplusOf[projectId][token] += amount;
|
|
1889
1893
|
}
|
|
1890
1894
|
}
|
|
1891
1895
|
}
|
|
@@ -2320,6 +2324,14 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
|
|
|
2320
2324
|
JBTokenAmount({token: token, decimals: context.decimals, currency: context.currency, value: value});
|
|
2321
2325
|
}
|
|
2322
2326
|
|
|
2327
|
+
/// @notice Returns a holder's total token balance for a project.
|
|
2328
|
+
/// @param holder The holder to get a balance for.
|
|
2329
|
+
/// @param projectId The ID of the project to get a balance for.
|
|
2330
|
+
/// @return balance The holder's total project token balance.
|
|
2331
|
+
function _totalBalanceOf(address holder, uint256 projectId) internal view returns (uint256 balance) {
|
|
2332
|
+
return TOKENS.totalBalanceOf({holder: holder, projectId: projectId});
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2323
2335
|
//*********************************************************************//
|
|
2324
2336
|
// -------------------------- private helpers ------------------------ //
|
|
2325
2337
|
//*********************************************************************//
|
|
@@ -43,4 +43,14 @@ interface IJBMultiTerminal is IJBTerminal, IJBFeeTerminal, IJBCashOutTerminal, I
|
|
|
43
43
|
/// @dev Per-referrer cumulative fee payment amounts credited via this terminal are stored in
|
|
44
44
|
/// `JBTerminalStore.feeVolumeByReferralOf(address terminal, uint256 referralChainId, uint256 referralProjectId)`.
|
|
45
45
|
function currentReferralProjectId() external view returns (uint256);
|
|
46
|
+
|
|
47
|
+
/// @notice The cumulative amount of fee-free intra-terminal payouts a project has received for a given token.
|
|
48
|
+
/// @dev Incremented each time a fee-free payout lands (same terminal, no fee charged) and consumed during
|
|
49
|
+
/// zero-tax cash outs to prevent a round-trip fee bypass (intra-terminal payout -> zero-tax cash out). Exposed
|
|
50
|
+
/// for off-chain indexers and integrating contracts that need to reason about a project's outstanding fee-free
|
|
51
|
+
/// exposure before performing related operations.
|
|
52
|
+
/// @param projectId The ID of the project that received the payout.
|
|
53
|
+
/// @param token The token that was received.
|
|
54
|
+
/// @return The cumulative unconsumed fee-free surplus tracked for the (project, token) pair.
|
|
55
|
+
function feeFreeSurplusOf(uint256 projectId, address token) external view returns (uint256);
|
|
46
56
|
}
|