@@ -8,9 +8,11 @@ import {EulerSwapHook} from "../src/EulerSwapHook.sol";
8
8
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol " ;
9
9
import {IPoolManager, PoolManagerDeployer} from "./utils/PoolManagerDeployer.sol " ;
10
10
import {PoolSwapTest} from "@uniswap/v4-core/src/test/PoolSwapTest.sol " ;
11
+ import {MinimalRouter} from "./utils/MinimalRouter.sol " ;
11
12
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol " ;
12
13
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol " ;
13
14
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol " ;
15
+ import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol " ;
14
16
15
17
contract EulerSwapHookTest is EulerSwapTestBase {
16
18
using StateLibrary for IPoolManager;
@@ -19,6 +21,7 @@ contract EulerSwapHookTest is EulerSwapTestBase {
19
21
20
22
IPoolManager public poolManager;
21
23
PoolSwapTest public swapRouter;
24
+ MinimalRouter public minimalRouter;
22
25
23
26
PoolSwapTest.TestSettings public settings = PoolSwapTest.TestSettings ({takeClaims: false , settleUsingBurn: false });
24
27
@@ -27,6 +30,7 @@ contract EulerSwapHookTest is EulerSwapTestBase {
27
30
28
31
poolManager = PoolManagerDeployer.deploy (address (this ));
29
32
swapRouter = new PoolSwapTest (poolManager);
33
+ minimalRouter = new MinimalRouter (poolManager);
30
34
31
35
eulerSwap = createEulerSwapHook (poolManager, 60e18 , 60e18 , 0 , 1e18 , 1e18 , 0.4e18 , 0.85e18 );
32
36
eulerSwap.activate ();
@@ -35,10 +39,6 @@ contract EulerSwapHookTest is EulerSwapTestBase {
35
39
assertFalse (eulerSwap.poolKey ().currency1 == CurrencyLibrary.ADDRESS_ZERO);
36
40
(uint160 sqrtPriceX96 ,,,) = poolManager.getSlot0 (eulerSwap.poolKey ().toId ());
37
41
assertNotEq (sqrtPriceX96, 0 );
38
-
39
- // Seed the poolManager with balance so that transient withdrawing before depositing succeeds
40
- assetTST.mint (address (poolManager), 1000e18 );
41
- assetTST2.mint (address (poolManager), 1000e18 );
42
42
}
43
43
44
44
function test_SwapExactIn () public {
@@ -49,14 +49,34 @@ contract EulerSwapHookTest is EulerSwapTestBase {
49
49
assetTST.mint (anyone, amountIn);
50
50
51
51
vm.startPrank (anyone);
52
- assetTST.approve (address (swapRouter ), amountIn);
52
+ assetTST.approve (address (minimalRouter ), amountIn);
53
53
54
54
bool zeroForOne = address (assetTST) < address (assetTST2);
55
- _swap (eulerSwap.poolKey (), zeroForOne, true , amountIn );
55
+ BalanceDelta result = minimalRouter. swap (eulerSwap.poolKey (), zeroForOne, amountIn, 0 , "" );
56
56
vm.stopPrank ();
57
57
58
58
assertEq (assetTST.balanceOf (anyone), 0 );
59
59
assertEq (assetTST2.balanceOf (anyone), amountOut);
60
+
61
+ assertEq (zeroForOne ? uint256 (- int256 (result.amount0 ())) : uint256 (- int256 (result.amount1 ())), amountIn);
62
+ assertEq (zeroForOne ? uint256 (int256 (result.amount1 ())) : uint256 (int256 (result.amount0 ())), amountOut);
63
+ }
64
+
65
+ /// @dev swapping with an amount that exceeds PoolManager's ERC20 token balance will revert
66
+ /// if the router does not pre-pay the input
67
+ function test_swapExactIn_revertWithoutTokenLiquidity () public {
68
+ uint256 amountIn = 1e18 ; // input amount exceeds PoolManager balance
69
+
70
+ assetTST.mint (anyone, amountIn);
71
+
72
+ vm.startPrank (anyone);
73
+ assetTST.approve (address (swapRouter), amountIn);
74
+
75
+ bool zeroForOne = address (assetTST) < address (assetTST2);
76
+ PoolKey memory poolKey = eulerSwap.poolKey ();
77
+ vm.expectRevert ();
78
+ _swap (poolKey, zeroForOne, true , amountIn);
79
+ vm.stopPrank ();
60
80
}
61
81
62
82
function test_SwapExactOut () public {
@@ -67,13 +87,35 @@ contract EulerSwapHookTest is EulerSwapTestBase {
67
87
assetTST.mint (anyone, amountIn);
68
88
69
89
vm.startPrank (anyone);
70
- assetTST.approve (address (swapRouter), amountIn);
90
+ assetTST.approve (address (minimalRouter), amountIn);
91
+
71
92
bool zeroForOne = address (assetTST) < address (assetTST2);
72
- _swap (eulerSwap.poolKey (), zeroForOne, false , amountOut);
93
+ BalanceDelta result = minimalRouter. swap (eulerSwap.poolKey (), zeroForOne, amountIn , amountOut, "" );
73
94
vm.stopPrank ();
74
95
75
96
assertEq (assetTST.balanceOf (anyone), 0 );
76
97
assertEq (assetTST2.balanceOf (anyone), amountOut);
98
+
99
+ assertEq (zeroForOne ? uint256 (- int256 (result.amount0 ())) : uint256 (- int256 (result.amount1 ())), amountIn);
100
+ assertEq (zeroForOne ? uint256 (int256 (result.amount1 ())) : uint256 (int256 (result.amount0 ())), amountOut);
101
+ }
102
+
103
+ /// @dev swapping with an amount that exceeds PoolManager's ERC20 token balance will revert
104
+ /// if the router does not pre-pay the input
105
+ function test_SwapExactOut_revertWithoutTokenLiquidity () public {
106
+ uint256 amountOut = 1e18 ;
107
+ uint256 amountIn =
108
+ periphery.quoteExactOutput (address (eulerSwap), address (assetTST), address (assetTST2), amountOut);
109
+
110
+ assetTST.mint (anyone, amountIn);
111
+
112
+ vm.startPrank (anyone);
113
+ assetTST.approve (address (swapRouter), amountIn);
114
+ bool zeroForOne = address (assetTST) < address (assetTST2);
115
+ PoolKey memory poolKey = eulerSwap.poolKey ();
116
+ vm.expectRevert ();
117
+ _swap (poolKey, zeroForOne, false , amountOut);
118
+ vm.stopPrank ();
77
119
}
78
120
79
121
function _swap (PoolKey memory key , bool zeroForOne , bool exactInput , uint256 amount ) internal {
0 commit comments