From d1afb1b7f3c30bd530368197a76c00c5fa253029 Mon Sep 17 00:00:00 2001 From: diana Date: Thu, 5 Sep 2024 16:44:52 -0400 Subject: [PATCH] Spearbit 99 (#339) --- .forge-snapshots/V4Router_Bytecode.snap | 2 +- ...Router_ExactOut1Hop_nativeIn_sweepETH.snap | 2 +- .../V4Router_ExactOut1Hop_nativeOut.snap | 2 +- .../V4Router_ExactOut1Hop_oneForZero.snap | 2 +- .../V4Router_ExactOut1Hop_zeroForOne.snap | 2 +- .forge-snapshots/V4Router_ExactOut2Hops.snap | 2 +- .../V4Router_ExactOut2Hops_nativeIn.snap | 2 +- .forge-snapshots/V4Router_ExactOut3Hops.snap | 2 +- .../V4Router_ExactOut3Hops_nativeIn.snap | 2 +- .../V4Router_ExactOut3Hops_nativeOut.snap | 2 +- .../V4Router_ExactOutputSingle.snap | 2 +- ...r_ExactOutputSingle_nativeIn_sweepETH.snap | 2 +- .../V4Router_ExactOutputSingle_nativeOut.snap | 2 +- src/V4Router.sol | 15 +++-- test/router/V4Router.t.sol | 59 +++++++++++++++++++ 15 files changed, 82 insertions(+), 18 deletions(-) diff --git a/.forge-snapshots/V4Router_Bytecode.snap b/.forge-snapshots/V4Router_Bytecode.snap index f0ba75b3a..86d32156a 100644 --- a/.forge-snapshots/V4Router_Bytecode.snap +++ b/.forge-snapshots/V4Router_Bytecode.snap @@ -1 +1 @@ -6909 \ No newline at end of file +7107 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_nativeIn_sweepETH.snap b/.forge-snapshots/V4Router_ExactOut1Hop_nativeIn_sweepETH.snap index 2ea024a06..82844d35c 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_nativeIn_sweepETH.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_nativeIn_sweepETH.snap @@ -1 +1 @@ -121352 \ No newline at end of file +121387 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap b/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap index 542c535f8..32c9c3a37 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap @@ -1 +1 @@ -116653 \ No newline at end of file +116688 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap b/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap index 22b36be6a..040303411 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap @@ -1 +1 @@ -125468 \ No newline at end of file +125503 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap b/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap index e05e7767f..226a0ed5b 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap @@ -1 +1 @@ -129385 \ No newline at end of file +129420 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut2Hops.snap b/.forge-snapshots/V4Router_ExactOut2Hops.snap index 120aa4622..d159c6cc5 100644 --- a/.forge-snapshots/V4Router_ExactOut2Hops.snap +++ b/.forge-snapshots/V4Router_ExactOut2Hops.snap @@ -1 +1 @@ -179217 \ No newline at end of file +179252 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut2Hops_nativeIn.snap b/.forge-snapshots/V4Router_ExactOut2Hops_nativeIn.snap index 7782d07d4..3a5782e52 100644 --- a/.forge-snapshots/V4Router_ExactOut2Hops_nativeIn.snap +++ b/.forge-snapshots/V4Router_ExactOut2Hops_nativeIn.snap @@ -1 +1 @@ -175101 \ No newline at end of file +175136 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut3Hops.snap b/.forge-snapshots/V4Router_ExactOut3Hops.snap index ed98ac422..f4e089998 100644 --- a/.forge-snapshots/V4Router_ExactOut3Hops.snap +++ b/.forge-snapshots/V4Router_ExactOut3Hops.snap @@ -1 +1 @@ -229056 \ No newline at end of file +229091 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut3Hops_nativeIn.snap b/.forge-snapshots/V4Router_ExactOut3Hops_nativeIn.snap index 8554dd790..c3ec97aba 100644 --- a/.forge-snapshots/V4Router_ExactOut3Hops_nativeIn.snap +++ b/.forge-snapshots/V4Router_ExactOut3Hops_nativeIn.snap @@ -1 +1 @@ -224964 \ No newline at end of file +224999 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap b/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap index 68ef809c4..82b547c5c 100644 --- a/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap @@ -1 +1 @@ -220265 \ No newline at end of file +220300 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOutputSingle.snap b/.forge-snapshots/V4Router_ExactOutputSingle.snap index 5c6f920bf..7ff1a5b2c 100644 --- a/.forge-snapshots/V4Router_ExactOutputSingle.snap +++ b/.forge-snapshots/V4Router_ExactOutputSingle.snap @@ -1 +1 @@ -128666 \ No newline at end of file +128698 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOutputSingle_nativeIn_sweepETH.snap b/.forge-snapshots/V4Router_ExactOutputSingle_nativeIn_sweepETH.snap index c9759720a..62d248457 100644 --- a/.forge-snapshots/V4Router_ExactOutputSingle_nativeIn_sweepETH.snap +++ b/.forge-snapshots/V4Router_ExactOutputSingle_nativeIn_sweepETH.snap @@ -1 +1 @@ -120633 \ No newline at end of file +120665 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap b/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap index 923cd951a..6667f50ed 100644 --- a/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap @@ -1 +1 @@ -116009 \ No newline at end of file +116041 \ No newline at end of file diff --git a/src/V4Router.sol b/src/V4Router.sol index 54c724604..cbdf464f0 100644 --- a/src/V4Router.sol +++ b/src/V4Router.sol @@ -121,13 +121,14 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver { } function _swapExactOutputSingle(IV4Router.ExactOutputSingleParams calldata params) private { + uint128 amountOut = params.amountOut; + if (amountOut == ActionConstants.OPEN_DELTA) { + amountOut = + _getFullDebt(params.zeroForOne ? params.poolKey.currency1 : params.poolKey.currency0).toUint128(); + } uint128 amountIn = ( -_swap( - params.poolKey, - params.zeroForOne, - int256(int128(params.amountOut)), - params.sqrtPriceLimitX96, - params.hookData + params.poolKey, params.zeroForOne, int256(int128(amountOut)), params.sqrtPriceLimitX96, params.hookData ) ).toUint128(); if (amountIn > params.amountInMaximum) revert V4TooMuchRequested(params.amountInMaximum, amountIn); @@ -142,6 +143,10 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver { Currency currencyOut = params.currencyOut; PathKey calldata pathKey; + if (amountOut == ActionConstants.OPEN_DELTA) { + amountOut = _getFullDebt(currencyOut).toUint128(); + } + for (uint256 i = pathLength; i > 0; i--) { pathKey = params.path[i - 1]; (PoolKey memory poolKey, bool oneForZero) = pathKey.getPoolAndSwapDirection(currencyOut); diff --git a/test/router/V4Router.t.sol b/test/router/V4Router.t.sol index ea2696bc4..e32da0529 100644 --- a/test/router/V4Router.t.sol +++ b/test/router/V4Router.t.sol @@ -534,6 +534,35 @@ contract V4RouterTest is RoutingTestHelpers { assertEq(outputBalanceAfter - outputBalanceBefore, amountOut); } + function test_swapExactOutputSingle_swapOpenDelta() public { + uint256 expectedAmountIn = 1008049273448486163; + + IV4Router.ExactOutputSingleParams memory params = IV4Router.ExactOutputSingleParams( + key0, true, ActionConstants.OPEN_DELTA, uint128(expectedAmountIn + 1), 0, bytes("") + ); + + plan = plan.add(Actions.TAKE, abi.encode(key0.currency1, ActionConstants.ADDRESS_THIS, 1 ether)); + plan = plan.add(Actions.SWAP_EXACT_OUT_SINGLE, abi.encode(params)); + plan = plan.add(Actions.SETTLE, abi.encode(key0.currency0, ActionConstants.OPEN_DELTA, true)); + + bytes memory data = plan.encode(); + + uint256 callerInputBefore = key0.currency0.balanceOfSelf(); + uint256 routerInputBefore = key0.currency1.balanceOfSelf(); + uint256 callerOutputBefore = key0.currency1.balanceOfSelf(); + + router.executeActions(data); + + uint256 callerInputAfter = key0.currency0.balanceOfSelf(); + uint256 routerInputAfter = key0.currency1.balanceOfSelf(); + uint256 callerOutputAfter = key0.currency1.balanceOfSelf(); + + // caller paid + assertEq(callerInputBefore - expectedAmountIn, callerInputAfter); + assertEq(routerInputBefore, routerInputAfter); + assertEq(callerOutputBefore, callerOutputAfter); + } + function test_swapExactOut_revertsForAmountIn() public { uint256 amountOut = 1 ether; uint256 expectedAmountIn = 1008049273448486163; @@ -641,6 +670,36 @@ contract V4RouterTest is RoutingTestHelpers { assertEq(outputBalanceAfter - outputBalanceBefore, amountOut); } + function test_swapExactOut_swapOpenDelta() public { + uint256 expectedAmountIn = 1008049273448486163; + + tokenPath.push(currency0); + tokenPath.push(currency1); + + IV4Router.ExactOutputParams memory params = _getExactOutputParams(tokenPath, ActionConstants.OPEN_DELTA); + + plan = plan.add(Actions.TAKE, abi.encode(key0.currency1, ActionConstants.ADDRESS_THIS, 1 ether)); + plan = plan.add(Actions.SWAP_EXACT_OUT, abi.encode(params)); + plan = plan.add(Actions.SETTLE, abi.encode(key0.currency0, ActionConstants.OPEN_DELTA, true)); + + bytes memory data = plan.encode(); + + uint256 callerInputBefore = key0.currency0.balanceOfSelf(); + uint256 routerInputBefore = key0.currency1.balanceOfSelf(); + uint256 callerOutputBefore = key0.currency1.balanceOfSelf(); + + router.executeActions(data); + + uint256 callerInputAfter = key0.currency0.balanceOfSelf(); + uint256 routerInputAfter = key0.currency1.balanceOfSelf(); + uint256 callerOutputAfter = key0.currency1.balanceOfSelf(); + + // caller paid + assertEq(callerInputBefore - expectedAmountIn, callerInputAfter); + assertEq(routerInputBefore, routerInputAfter); + assertEq(callerOutputBefore, callerOutputAfter); + } + /*////////////////////////////////////////////////////////////// ETH -> ERC20 and ERC20 -> ETH EXACT OUTPUT //////////////////////////////////////////////////////////////*/