@bananapus/router-terminal-v6 0.0.57 → 0.0.59

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/router-terminal-v6",
3
- "version": "0.0.57",
3
+ "version": "0.0.59",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,7 +24,7 @@
24
24
  "artifacts": "source ./.env && npx sphinx artifacts --org-id 'ea165b21-7cdc-4d7b-be59-ecdd4c26bee4' --project-name 'nana-router-terminal-v6'"
25
25
  },
26
26
  "dependencies": {
27
- "@bananapus/buyback-hook-v6": "^0.0.58",
27
+ "@bananapus/buyback-hook-v6": "^0.0.64",
28
28
  "@bananapus/core-v6": "^0.0.72",
29
29
  "@bananapus/permission-ids-v6": "^0.0.27",
30
30
  "@bananapus/univ4-router-v6": "^0.0.46",
@@ -2,6 +2,7 @@
2
2
  pragma solidity 0.8.28;
3
3
 
4
4
  import {IJBCashOutTerminal} from "@bananapus/core-v6/src/interfaces/IJBCashOutTerminal.sol";
5
+ import {IJBController} from "@bananapus/core-v6/src/interfaces/IJBController.sol";
5
6
  import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
6
7
  import {IJBPermitTerminal} from "@bananapus/core-v6/src/interfaces/IJBPermitTerminal.sol";
7
8
  import {IJBTerminal} from "@bananapus/core-v6/src/interfaces/IJBTerminal.sol";
@@ -154,11 +155,11 @@ contract JBRouterTerminal is
154
155
  /// @notice Pre-computed metadata ID for "permit2".
155
156
  bytes4 internal immutable _PERMIT2_ID;
156
157
 
157
- /// @notice Pre-computed metadata ID for "cashOutMinReclaimed".
158
- bytes4 internal immutable _CASH_OUT_MIN_RECLAIMED_ID;
158
+ /// @notice Pre-computed metadata ID for "cashOut" (the cash-out reclaim floor).
159
+ bytes4 internal immutable _CASH_OUT_ID;
159
160
 
160
- /// @notice Pre-computed metadata ID for "quoteForSwap".
161
- bytes4 internal immutable _QUOTE_FOR_SWAP_ID;
161
+ /// @notice Pre-computed metadata ID for "pay" (the pay-phase swap quote).
162
+ bytes4 internal immutable _PAY_ID;
162
163
 
163
164
  //*********************************************************************//
164
165
  // --------------------- public stored properties -------------------- //
@@ -220,8 +221,8 @@ contract JBRouterTerminal is
220
221
 
221
222
  // Pre-compute metadata IDs to avoid hashing string literals on every call.
222
223
  _PERMIT2_ID = JBMetadataResolver.getId("permit2");
223
- _CASH_OUT_MIN_RECLAIMED_ID = JBMetadataResolver.getId("cashOutMinReclaimed");
224
- _QUOTE_FOR_SWAP_ID = JBMetadataResolver.getId("quoteForSwap");
224
+ _CASH_OUT_ID = JBMetadataResolver.getId("cashOut");
225
+ _PAY_ID = JBMetadataResolver.getId("pay");
225
226
  }
226
227
 
227
228
  //*********************************************************************//
@@ -1136,7 +1137,7 @@ contract JBRouterTerminal is
1136
1137
  /// @param destProjectId The ID of the destination project.
1137
1138
  /// @param token The current token to process.
1138
1139
  /// @param amount The amount of the current token.
1139
- /// @param metadata Bytes in `JBMetadataResolver`'s format (may contain cashOutMinReclaimed).
1140
+ /// @param metadata Bytes in `JBMetadataResolver`'s format (may contain a `cashOut` reclaim floor).
1140
1141
  /// @return destTerminal The terminal that accepts the final token (address(0) if no direct acceptance found).
1141
1142
  /// @return finalToken The token after all cashouts.
1142
1143
  /// @return finalAmount The amount of the final token.
@@ -1180,6 +1181,8 @@ contract JBRouterTerminal is
1180
1181
  sourceProjectId: sourceProjectId, destProjectId: destProjectId, preferredToken: preferredToken
1181
1182
  });
1182
1183
 
1184
+ _claimRouterCreditsFor({projectId: sourceProjectId});
1185
+
1183
1186
  uint256 cashOutCount = amount;
1184
1187
  uint256 balanceBefore = _balanceOf({token: tokenToReclaim, account: address(this)});
1185
1188
 
@@ -1235,12 +1238,26 @@ contract JBRouterTerminal is
1235
1238
  revert JBRouterTerminal_CashOutLoopLimit({maxIterations: _MAX_CASHOUT_ITERATIONS});
1236
1239
  }
1237
1240
 
1241
+ /// @notice Converts this router's internal project-token credits into ERC-20s before a source cash-out.
1242
+ /// @dev Core burns holder credits before ERC-20 balances. Normalizing first keeps a source cash-out scoped to
1243
+ /// transferable token balances already visible to the router.
1244
+ /// @param projectId The Juicebox project whose tokens are being cashed out.
1245
+ function _claimRouterCreditsFor(uint256 projectId) internal {
1246
+ uint256 creditCount = TOKENS.creditBalanceOf({holder: address(this), projectId: projectId});
1247
+ if (creditCount == 0) return;
1248
+
1249
+ IJBController controller = IJBController(address(DIRECTORY.controllerOf(projectId)));
1250
+ controller.claimTokensFor({
1251
+ holder: address(this), projectId: projectId, tokenCount: creditCount, beneficiary: address(this)
1252
+ });
1253
+ }
1254
+
1238
1255
  /// @notice Convert tokenIn to tokenOut. No-op if same, wrap/unwrap for native/wrapped-native, or swap via Uniswap.
1239
1256
  /// @param tokenIn The token to convert from.
1240
1257
  /// @param tokenOut The token to convert into.
1241
1258
  /// @param amount The amount to convert.
1242
1259
  /// @param projectId The project ID (passed through to swap callback data).
1243
- /// @param metadata Bytes in `JBMetadataResolver`'s format (may contain quoteForSwap).
1260
+ /// @param metadata Bytes in `JBMetadataResolver`'s format (may contain a `pay` swap quote).
1244
1261
  /// @param refundTo The address to receive leftover input tokens from partial fills.
1245
1262
  /// @return The amount of tokenOut produced.
1246
1263
  function _convert(
@@ -1422,7 +1439,7 @@ contract JBRouterTerminal is
1422
1439
  /// @param tokenIn The token to swap from.
1423
1440
  /// @param tokenOut The token to swap into.
1424
1441
  /// @param amount The amount of tokenIn to swap.
1425
- /// @param metadata Bytes in `JBMetadataResolver`'s format (may contain quoteForSwap).
1442
+ /// @param metadata Bytes in `JBMetadataResolver`'s format (may contain a `pay` swap quote).
1426
1443
  /// @param refundTo The address to receive leftover input tokens from partial fills.
1427
1444
  /// @return amountOut The amount of tokenOut received.
1428
1445
  function _handleSwap(
@@ -1587,7 +1604,7 @@ contract JBRouterTerminal is
1587
1604
  /// @param destProjectId The destination project to reach.
1588
1605
  /// @param tokenIn The current route input token.
1589
1606
  /// @param amount The current route input amount.
1590
- /// @param metadata Metadata that may include a cashOutMinReclaimed floor.
1607
+ /// @param metadata Metadata that may include a `cashOut` reclaim floor.
1591
1608
  /// @param preferredToken The preferred token to target during any cashout loop.
1592
1609
  /// @return resolvedTerminal The terminal found by the cashout loop, or address(0) if conversion should continue.
1593
1610
  /// @return routedTokenIn The token that remains to be routed after the cashout step.
@@ -2263,7 +2280,7 @@ contract JBRouterTerminal is
2263
2280
  /// 3. Thin pools, newly initialized pools, and unusually large swaps should not rely on this fallback.
2264
2281
  ///
2265
2282
  /// Mitigations in place:
2266
- /// 1. Users SHOULD provide a `quoteForSwap` value in the payment metadata (obtained from an off-chain
2283
+ /// 1. Users SHOULD provide a `pay` swap quote in the payment metadata (obtained from an off-chain
2267
2284
  /// quoter or RPC simulation). The quote must encode the output token and minimum output amount. When present,
2268
2285
  /// this function is bypassed entirely — see `_pickPoolAndQuote`.
2269
2286
  /// 2. When a hook implements `IGeomeanOracle.observe(...)`, this function uses that oracle-derived tick instead
@@ -2276,7 +2293,7 @@ contract JBRouterTerminal is
2276
2293
  /// this V4 spot-price path altogether.
2277
2294
  ///
2278
2295
  /// Despite these mitigations, the spot-based fallback does NOT provide full MEV protection. Integrators and
2279
- /// front-ends should supply `quoteForSwap` metadata for V4 swaps whenever possible so the user's slippage
2296
+ /// front-ends should supply `pay` swap-quote metadata for V4 swaps whenever possible so the user's slippage
2280
2297
  /// tolerance reflects a recent, off-chain-verified price. When no external quote can be provided, this fallback
2281
2298
  /// is still available as an accepted-risk convenience path.
2282
2299
  /// @param key The V4 pool key describing the pool to quote against.
@@ -2376,11 +2393,11 @@ contract JBRouterTerminal is
2376
2393
  }
2377
2394
  }
2378
2395
 
2379
- /// @notice Parse the optional `cashOutMinReclaimed` metadata.
2396
+ /// @notice Parse the optional `cashOut` metadata (the minimum-reclaim floor).
2380
2397
  /// @param metadata The metadata to inspect for minimum reclaim amounts.
2381
2398
  /// @return minTokensReclaimed The minimum reclaim amount, or 0 if none is specified.
2382
2399
  function _minReclaimedFrom(bytes calldata metadata) internal view returns (uint256 minTokensReclaimed) {
2383
- (bool exists, bytes memory minData) = _getDataFor({metadata: metadata, id: _CASH_OUT_MIN_RECLAIMED_ID});
2400
+ (bool exists, bytes memory minData) = _getDataFor({metadata: metadata, id: _CASH_OUT_ID});
2384
2401
  if (exists) minTokensReclaimed = abi.decode(minData, (uint256));
2385
2402
  }
2386
2403
 
@@ -2418,10 +2435,10 @@ contract JBRouterTerminal is
2418
2435
  /// @dev For V4 pools without TWAP-capable hooks, `minAmountOut` is derived from the same-block spot tick, which is
2419
2436
  /// manipulable via sandwich attacks. This is an accepted risk for integrations that cannot source external quotes,
2420
2437
  /// especially when routing through deep pools and routine swap sizes, but it should not be treated as full MEV
2421
- /// protection. Integrators should still supply `quoteForSwap` metadata whenever they can.
2438
+ /// protection. Integrators should still supply `pay` swap-quote metadata whenever they can.
2422
2439
  ///
2423
2440
  /// Priority for `minAmountOut`:
2424
- /// 1. **User-provided quote** — If `quoteForSwap` is present in `metadata`, it is used after confirming the
2441
+ /// 1. **User-provided quote** — If a `pay` swap quote is present in `metadata`, it is used after confirming the
2425
2442
  /// quote's output token matches the selected route. This is the recommended path for MEV protection,
2426
2443
  /// especially for V4 pools.
2427
2444
  /// 2. **V3 TWAP** — If the best pool is V3, uses a manipulation-resistant time-weighted average price.
@@ -2430,7 +2447,7 @@ contract JBRouterTerminal is
2430
2447
  /// same block (see `_getV4SpotQuote` security note). The sigmoid slippage formula provides a floor but not
2431
2448
  /// full MEV protection.
2432
2449
  ///
2433
- /// @param metadata Bytes in `JBMetadataResolver`'s format (may contain quoteForSwap).
2450
+ /// @param metadata Bytes in `JBMetadataResolver`'s format (may contain a `pay` swap quote).
2434
2451
  /// @param normalizedTokenIn The normalized input token address.
2435
2452
  /// @param amount The amount of tokens to swap.
2436
2453
  /// @param normalizedTokenOut The normalized output token address.
@@ -2452,9 +2469,9 @@ contract JBRouterTerminal is
2452
2469
  revert JBRouterTerminal_NoPoolFound({tokenIn: normalizedTokenIn, tokenOut: normalizedTokenOut});
2453
2470
  }
2454
2471
 
2455
- // `quoteForSwap` is encoded as `(tokenOut, minAmountOut)`. Binding the quote to its output token prevents
2472
+ // `pay` is encoded as `(tokenOut, minAmountOut)`. Binding the quote to its output token prevents
2456
2473
  // metadata quoted for one route from being replayed against another route with a weaker floor.
2457
- (bool exists, bytes memory quote) = _getDataFor({metadata: metadata, id: _QUOTE_FOR_SWAP_ID});
2474
+ (bool exists, bytes memory quote) = _getDataFor({metadata: metadata, id: _PAY_ID});
2458
2475
 
2459
2476
  if (exists) {
2460
2477
  (address quotedTokenOut, uint256 quotedMinAmountOut) = abi.decode(quote, (address, uint256));