@bananapus/router-terminal-v6 0.0.14 → 0.0.15
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.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"artifacts": "source ./.env && npx sphinx artifacts --org-id 'ea165b21-7cdc-4d7b-be59-ecdd4c26bee4' --project-name 'nana-router-terminal-v6'"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@bananapus/core-v6": "^0.0.
|
|
20
|
+
"@bananapus/core-v6": "^0.0.23",
|
|
21
21
|
"@bananapus/permission-ids-v6": "^0.0.10",
|
|
22
22
|
"@openzeppelin/contracts": "^5.6.1",
|
|
23
23
|
"@uniswap/permit2": "github:Uniswap/permit2",
|
package/src/JBRouterTerminal.sol
CHANGED
|
@@ -14,7 +14,6 @@ import {IJBTokens} from "@bananapus/core-v6/src/interfaces/IJBTokens.sol";
|
|
|
14
14
|
import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
15
15
|
import {JBMetadataResolver} from "@bananapus/core-v6/src/libraries/JBMetadataResolver.sol";
|
|
16
16
|
import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
|
|
17
|
-
import {JBCashOutHookSpecification} from "@bananapus/core-v6/src/structs/JBCashOutHookSpecification.sol";
|
|
18
17
|
import {JBPayHookSpecification} from "@bananapus/core-v6/src/structs/JBPayHookSpecification.sol";
|
|
19
18
|
import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
20
19
|
import {JBSingleAllowance} from "@bananapus/core-v6/src/structs/JBSingleAllowance.sol";
|
|
@@ -220,7 +219,7 @@ contract JBRouterTerminal is
|
|
|
220
219
|
/// @notice This terminal holds no surplus. Always returns 0.
|
|
221
220
|
function currentSurplusOf(
|
|
222
221
|
uint256,
|
|
223
|
-
|
|
222
|
+
address[] calldata,
|
|
224
223
|
uint256,
|
|
225
224
|
uint256
|
|
226
225
|
)
|
|
@@ -426,16 +425,12 @@ contract JBRouterTerminal is
|
|
|
426
425
|
override
|
|
427
426
|
{
|
|
428
427
|
IJBTerminal destTerminal;
|
|
429
|
-
{
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
_route({destProjectId: projectId, tokenIn: token, amount: amount, metadata: metadata});
|
|
436
|
-
token = tokenOut;
|
|
437
|
-
amount = amountOut;
|
|
438
|
-
}
|
|
428
|
+
(destTerminal, token, amount) = _route({
|
|
429
|
+
destProjectId: projectId,
|
|
430
|
+
tokenIn: token,
|
|
431
|
+
amount: _acceptFundsFor({token: token, amount: amount, metadata: metadata}),
|
|
432
|
+
metadata: metadata
|
|
433
|
+
});
|
|
439
434
|
|
|
440
435
|
uint256 payValue = _beforeTransferFor({to: address(destTerminal), token: token, amount: amount});
|
|
441
436
|
|
|
@@ -480,16 +475,12 @@ contract JBRouterTerminal is
|
|
|
480
475
|
returns (uint256 beneficiaryTokenCount)
|
|
481
476
|
{
|
|
482
477
|
IJBTerminal destTerminal;
|
|
483
|
-
{
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
_route({destProjectId: projectId, tokenIn: token, amount: amount, metadata: metadata});
|
|
490
|
-
token = tokenOut;
|
|
491
|
-
amount = amountOut;
|
|
492
|
-
}
|
|
478
|
+
(destTerminal, token, amount) = _route({
|
|
479
|
+
destProjectId: projectId,
|
|
480
|
+
tokenIn: token,
|
|
481
|
+
amount: _acceptFundsFor({token: token, amount: amount, metadata: metadata}),
|
|
482
|
+
metadata: metadata
|
|
483
|
+
});
|
|
493
484
|
|
|
494
485
|
uint256 payValue = _beforeTransferFor({to: address(destTerminal), token: token, amount: amount});
|
|
495
486
|
|
|
@@ -553,22 +544,20 @@ contract JBRouterTerminal is
|
|
|
553
544
|
});
|
|
554
545
|
|
|
555
546
|
// Determine input/output amounts from the delta.
|
|
547
|
+
int128 delta0 = delta.amount0();
|
|
548
|
+
int128 delta1 = delta.amount1();
|
|
556
549
|
uint256 amountIn;
|
|
557
550
|
uint256 amountOut;
|
|
558
|
-
{
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
amountIn = uint256(uint128(-delta1));
|
|
569
|
-
// forge-lint: disable-next-line(unsafe-typecast)
|
|
570
|
-
amountOut = uint256(uint128(delta0));
|
|
571
|
-
}
|
|
551
|
+
if (zeroForOne) {
|
|
552
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
553
|
+
amountIn = uint256(uint128(-delta0));
|
|
554
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
555
|
+
amountOut = uint256(uint128(delta1));
|
|
556
|
+
} else {
|
|
557
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
558
|
+
amountIn = uint256(uint128(-delta1));
|
|
559
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
560
|
+
amountOut = uint256(uint128(delta0));
|
|
572
561
|
}
|
|
573
562
|
|
|
574
563
|
if (amountOut < minAmountOut) revert JBRouterTerminal_SlippageExceeded(amountOut, minAmountOut);
|
|
@@ -595,23 +584,21 @@ contract JBRouterTerminal is
|
|
|
595
584
|
/// @return The amount of tokens that have been accepted.
|
|
596
585
|
function _acceptFundsFor(address token, uint256 amount, bytes calldata metadata) internal returns (uint256) {
|
|
597
586
|
// Check for credit cash-out metadata.
|
|
598
|
-
|
|
599
|
-
(
|
|
600
|
-
JBMetadataResolver.getDataFor({id: JBMetadataResolver.getId("cashOutSource"), metadata: metadata});
|
|
587
|
+
(bool creditExists, bytes memory creditData) =
|
|
588
|
+
JBMetadataResolver.getDataFor({id: JBMetadataResolver.getId("cashOutSource"), metadata: metadata});
|
|
601
589
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
590
|
+
if (creditExists) {
|
|
591
|
+
// Credit cashouts don't use msg.value — revert if ETH was sent to prevent it being trapped.
|
|
592
|
+
if (msg.value != 0) revert JBRouterTerminal_NoMsgValueAllowed(msg.value);
|
|
605
593
|
|
|
606
|
-
|
|
594
|
+
(uint256 sourceProjectId, uint256 creditAmount) = abi.decode(creditData, (uint256, uint256));
|
|
607
595
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
596
|
+
// Pull credits from the payer (requires payer to have granted TRANSFER_CREDITS to this contract).
|
|
597
|
+
TOKENS.transferCreditsFrom({
|
|
598
|
+
holder: _msgSender(), projectId: sourceProjectId, recipient: address(this), count: creditAmount
|
|
599
|
+
});
|
|
612
600
|
|
|
613
|
-
|
|
614
|
-
}
|
|
601
|
+
return creditAmount;
|
|
615
602
|
}
|
|
616
603
|
|
|
617
604
|
// If native tokens are being paid in, return the `msg.value`.
|
|
@@ -676,6 +663,15 @@ contract JBRouterTerminal is
|
|
|
676
663
|
return 0;
|
|
677
664
|
}
|
|
678
665
|
|
|
666
|
+
/// @notice Parse the optional `cashOutMinReclaimed` metadata.
|
|
667
|
+
/// @param metadata The metadata to inspect for a minimum reclaim amount.
|
|
668
|
+
/// @return minTokensReclaimed The minimum reclaim amount, or 0 if none is specified.
|
|
669
|
+
function _minReclaimedFrom(bytes calldata metadata) internal view returns (uint256 minTokensReclaimed) {
|
|
670
|
+
(bool exists, bytes memory minData) =
|
|
671
|
+
JBMetadataResolver.getDataFor({id: JBMetadataResolver.getId("cashOutMinReclaimed"), metadata: metadata});
|
|
672
|
+
if (exists) minTokensReclaimed = abi.decode(minData, (uint256));
|
|
673
|
+
}
|
|
674
|
+
|
|
679
675
|
/// @notice Parse the optional `cashOutSource` metadata.
|
|
680
676
|
/// @param metadata The metadata to inspect for a credit cashout override.
|
|
681
677
|
/// @return sourceProjectId The source project override, or 0 if none is specified.
|
|
@@ -740,12 +736,7 @@ contract JBRouterTerminal is
|
|
|
740
736
|
returns (IJBTerminal destTerminal, address finalToken, uint256 finalAmount)
|
|
741
737
|
{
|
|
742
738
|
// Check for a user-provided minimum cashout reclaim amount (slippage protection).
|
|
743
|
-
uint256 minTokensReclaimed;
|
|
744
|
-
{
|
|
745
|
-
(bool exists, bytes memory minData) =
|
|
746
|
-
JBMetadataResolver.getDataFor({id: JBMetadataResolver.getId("cashOutMinReclaimed"), metadata: metadata});
|
|
747
|
-
if (exists) minTokensReclaimed = abi.decode(minData, (uint256));
|
|
748
|
-
}
|
|
739
|
+
uint256 minTokensReclaimed = _minReclaimedFrom(metadata);
|
|
749
740
|
|
|
750
741
|
// Intermediate steps have no per-step slippage protection. The final output amount is
|
|
751
742
|
// checked against the user's minReclaimed parameter, providing end-to-end slippage protection. Per-step
|
|
@@ -817,15 +808,7 @@ contract JBRouterTerminal is
|
|
|
817
808
|
returns (IJBTerminal destTerminal, address finalToken, uint256 finalAmount)
|
|
818
809
|
{
|
|
819
810
|
// Track the one-time minimum reclaim amount that the caller may require on the first hop.
|
|
820
|
-
uint256 minTokensReclaimed;
|
|
821
|
-
{
|
|
822
|
-
// Read the optional `cashOutMinReclaimed` payload from metadata.
|
|
823
|
-
(bool exists, bytes memory minData) =
|
|
824
|
-
JBMetadataResolver.getDataFor({id: JBMetadataResolver.getId("cashOutMinReclaimed"), metadata: metadata});
|
|
825
|
-
|
|
826
|
-
// Decode the first-hop minimum reclaim amount if the payload is present.
|
|
827
|
-
if (exists) minTokensReclaimed = abi.decode(minData, (uint256));
|
|
828
|
-
}
|
|
811
|
+
uint256 minTokensReclaimed = _minReclaimedFrom(metadata);
|
|
829
812
|
|
|
830
813
|
// Walk the same cash-out path execution would take, bounded to prevent circular routes.
|
|
831
814
|
for (uint256 i; i < _MAX_CASHOUT_ITERATIONS; i++) {
|
|
@@ -1199,15 +1182,13 @@ contract JBRouterTerminal is
|
|
|
1199
1182
|
|
|
1200
1183
|
for (uint256 i; i < terminals.length; i++) {
|
|
1201
1184
|
// Check if this terminal supports the IJBCashOutTerminal interface.
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
)
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
continue;
|
|
1210
|
-
}
|
|
1185
|
+
// slither-disable-next-line calls-loop
|
|
1186
|
+
try IERC165(address(terminals[i])).supportsInterface(type(IJBCashOutTerminal).interfaceId) returns (
|
|
1187
|
+
bool supported
|
|
1188
|
+
) {
|
|
1189
|
+
if (!supported) continue;
|
|
1190
|
+
} catch {
|
|
1191
|
+
continue;
|
|
1211
1192
|
}
|
|
1212
1193
|
|
|
1213
1194
|
IJBCashOutTerminal terminal = IJBCashOutTerminal(address(terminals[i]));
|
|
@@ -1218,12 +1199,10 @@ contract JBRouterTerminal is
|
|
|
1218
1199
|
address contextToken = contexts[j].token;
|
|
1219
1200
|
|
|
1220
1201
|
// Priority 1: Does the destination project directly accept this token?
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
if (address(destTerminal) != address(0)) return (contextToken, terminal);
|
|
1226
|
-
}
|
|
1202
|
+
// slither-disable-next-line calls-loop
|
|
1203
|
+
IJBTerminal destTerminal =
|
|
1204
|
+
DIRECTORY.primaryTerminalOf({projectId: destProjectId, token: contextToken});
|
|
1205
|
+
if (address(destTerminal) != address(0)) return (contextToken, terminal);
|
|
1227
1206
|
|
|
1228
1207
|
// Priority 2: Is this a JB project token (so we can recurse)?
|
|
1229
1208
|
if (address(fallbackTerminal) == address(0) && contextToken != JBConstants.NATIVE_TOKEN) {
|
|
@@ -1493,15 +1472,13 @@ contract JBRouterTerminal is
|
|
|
1493
1472
|
returns (address tokenOut, IJBTerminal destTerminal)
|
|
1494
1473
|
{
|
|
1495
1474
|
// 1. Metadata override — payer specifies tokenOut explicitly.
|
|
1496
|
-
|
|
1497
|
-
(
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
return (tokenOut, destTerminal);
|
|
1504
|
-
}
|
|
1475
|
+
(bool exists, bytes memory routeData) =
|
|
1476
|
+
JBMetadataResolver.getDataFor({id: JBMetadataResolver.getId("routeTokenOut"), metadata: metadata});
|
|
1477
|
+
if (exists) {
|
|
1478
|
+
(tokenOut) = abi.decode(routeData, (address));
|
|
1479
|
+
destTerminal = DIRECTORY.primaryTerminalOf({projectId: projectId, token: tokenOut});
|
|
1480
|
+
if (address(destTerminal) == address(0)) revert JBRouterTerminal_NoRouteFound(projectId, tokenOut);
|
|
1481
|
+
return (tokenOut, destTerminal);
|
|
1505
1482
|
}
|
|
1506
1483
|
|
|
1507
1484
|
// 2. Direct acceptance — project accepts tokenIn as-is.
|
|
@@ -1540,14 +1517,7 @@ contract JBRouterTerminal is
|
|
|
1540
1517
|
returns (IJBTerminal destTerminal, address tokenOut, uint256 amountOut)
|
|
1541
1518
|
{
|
|
1542
1519
|
// Check for credit source override.
|
|
1543
|
-
uint256 sourceProjectIdOverride;
|
|
1544
|
-
{
|
|
1545
|
-
(bool creditExists, bytes memory creditData) =
|
|
1546
|
-
JBMetadataResolver.getDataFor({id: JBMetadataResolver.getId("cashOutSource"), metadata: metadata});
|
|
1547
|
-
if (creditExists) {
|
|
1548
|
-
(sourceProjectIdOverride,) = abi.decode(creditData, (uint256, uint256));
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1520
|
+
(uint256 sourceProjectIdOverride,) = _cashOutSourceFrom(metadata);
|
|
1551
1521
|
|
|
1552
1522
|
// Check if input is a JB project token (credit or ERC-20).
|
|
1553
1523
|
uint256 sourceProjectId = sourceProjectIdOverride;
|
|
@@ -142,13 +142,13 @@ contract JBRouterTerminalRegistry is IJBRouterTerminalRegistry, JBPermissioned,
|
|
|
142
142
|
|
|
143
143
|
/// @notice Empty implementation to satisfy the interface. This terminal has no surplus.
|
|
144
144
|
function currentSurplusOf(
|
|
145
|
-
uint256
|
|
146
|
-
|
|
147
|
-
uint256
|
|
148
|
-
uint256
|
|
145
|
+
uint256,
|
|
146
|
+
address[] calldata,
|
|
147
|
+
uint256,
|
|
148
|
+
uint256
|
|
149
149
|
)
|
|
150
150
|
external
|
|
151
|
-
|
|
151
|
+
pure
|
|
152
152
|
override
|
|
153
153
|
returns (uint256)
|
|
154
154
|
{}
|
|
@@ -419,7 +419,7 @@ contract RouterTerminalTest is Test {
|
|
|
419
419
|
}
|
|
420
420
|
|
|
421
421
|
function test_currentSurplus_zero() public view {
|
|
422
|
-
assertEq(routerTerminal.currentSurplusOf(1, new
|
|
422
|
+
assertEq(routerTerminal.currentSurplusOf(1, new address[](0), 18, 1), 0);
|
|
423
423
|
}
|
|
424
424
|
|
|
425
425
|
//*********************************************************************//
|