Skip to content

Commit 128d1cf

Browse files
authored
Merge pull request #49 from euler-xyz/sauce/v4-exploration/tests
test setup for EulerSwapHook
2 parents e30f681 + e0bfe0e commit 128d1cf

File tree

3 files changed

+126
-3
lines changed

3 files changed

+126
-3
lines changed

src/EulerSwapHook.sol

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {EulerSwap, IEulerSwap, IEVault} from "./EulerSwap.sol";
1616
contract EulerSwapHook is EulerSwap, BaseHook {
1717
using SafeCast for uint256;
1818

19-
PoolKey poolKey;
19+
PoolKey internal _poolKey;
2020

2121
constructor(IPoolManager _manager, Params memory params, CurveParams memory curveParams)
2222
EulerSwap(params, curveParams)
@@ -28,7 +28,7 @@ contract EulerSwapHook is EulerSwap, BaseHook {
2828
// convert fee in WAD to pips. 0.003e18 / 1e12 = 3000 = 0.30%
2929
uint24 fee = uint24(params.fee / 1e12);
3030

31-
poolKey = PoolKey({
31+
_poolKey = PoolKey({
3232
currency0: Currency.wrap(asset0Addr),
3333
currency1: Currency.wrap(asset1Addr),
3434
fee: fee,
@@ -37,7 +37,12 @@ contract EulerSwapHook is EulerSwap, BaseHook {
3737
});
3838

3939
// create the pool on v4, using starting price as sqrtPrice(1/1) * Q96
40-
poolManager.initialize(poolKey, 79228162514264337593543950336);
40+
poolManager.initialize(_poolKey, 79228162514264337593543950336);
41+
}
42+
43+
/// @dev Helper function to return the poolKey as its struct type
44+
function poolKey() external view returns (PoolKey memory) {
45+
return _poolKey;
4146
}
4247

4348
function _beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata)

test/EulerSwapHook.swaps.t.sol

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
pragma solidity ^0.8.24;
3+
4+
import {EulerSwapTestBase, EulerSwap, EulerSwapPeriphery, IEulerSwap} from "./EulerSwapTestBase.t.sol";
5+
import {TestERC20} from "evk-test/unit/evault/EVaultTestBase.t.sol";
6+
import {EulerSwapHook} from "../src/EulerSwapHook.sol";
7+
8+
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
9+
import {IPoolManager, PoolManagerDeployer} from "./utils/PoolManagerDeployer.sol";
10+
import {PoolSwapTest} from "@uniswap/v4-core/src/test/PoolSwapTest.sol";
11+
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
12+
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
13+
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
14+
15+
contract EulerSwapHookTest is EulerSwapTestBase {
16+
using StateLibrary for IPoolManager;
17+
18+
EulerSwapHook public eulerSwap;
19+
20+
IPoolManager public poolManager;
21+
PoolSwapTest public swapRouter;
22+
23+
PoolSwapTest.TestSettings public settings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
24+
25+
function setUp() public virtual override {
26+
super.setUp();
27+
28+
poolManager = PoolManagerDeployer.deploy(address(this));
29+
swapRouter = new PoolSwapTest(poolManager);
30+
31+
eulerSwap = createEulerSwapHook(poolManager, 60e18, 60e18, 0, 1e18, 1e18, 0.4e18, 0.85e18);
32+
33+
// confirm pool was created
34+
assertFalse(eulerSwap.poolKey().currency1 == CurrencyLibrary.ADDRESS_ZERO);
35+
(uint160 sqrtPriceX96,,,) = poolManager.getSlot0(eulerSwap.poolKey().toId());
36+
assertNotEq(sqrtPriceX96, 0);
37+
}
38+
39+
function test_SwapExactIn() public {
40+
uint256 amountIn = 1e18;
41+
uint256 amountOut =
42+
periphery.quoteExactInput(address(eulerSwap), address(assetTST), address(assetTST2), amountIn);
43+
44+
assetTST.mint(anyone, amountIn);
45+
46+
vm.startPrank(anyone);
47+
assetTST.approve(address(swapRouter), amountIn);
48+
49+
bool zeroForOne = address(assetTST) < address(assetTST2);
50+
_swap(eulerSwap.poolKey(), zeroForOne, true, amountIn);
51+
vm.stopPrank();
52+
53+
assertEq(assetTST.balanceOf(anyone), 0);
54+
assertEq(assetTST2.balanceOf(anyone), amountOut);
55+
}
56+
57+
function test_SwapExactOut() public {
58+
uint256 amountOut = 1e18;
59+
uint256 amountIn =
60+
periphery.quoteExactOutput(address(eulerSwap), address(assetTST), address(assetTST2), amountOut);
61+
62+
assetTST.mint(anyone, amountIn);
63+
64+
vm.startPrank(anyone);
65+
assetTST.approve(address(periphery), amountIn);
66+
bool zeroForOne = address(assetTST) < address(assetTST2);
67+
_swap(eulerSwap.poolKey(), zeroForOne, false, amountOut);
68+
vm.stopPrank();
69+
70+
assertEq(assetTST.balanceOf(anyone), 0);
71+
assertEq(assetTST2.balanceOf(anyone), amountOut);
72+
}
73+
74+
function _swap(PoolKey memory key, bool zeroForOne, bool exactInput, uint256 amount) internal {
75+
IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams({
76+
zeroForOne: zeroForOne,
77+
amountSpecified: exactInput ? -int256(amount) : int256(amount),
78+
sqrtPriceLimitX96: zeroForOne ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1
79+
});
80+
swapRouter.swap(key, swapParams, settings, "");
81+
}
82+
}

test/EulerSwapTestBase.t.sol

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import {EVaultTestBase, TestERC20} from "evk-test/unit/evault/EVaultTestBase.t.s
66
import {IEVault} from "evk/EVault/IEVault.sol";
77
import {IEulerSwap, IEVC, EulerSwap} from "../src/EulerSwap.sol";
88
import {EulerSwapPeriphery} from "../src/EulerSwapPeriphery.sol";
9+
import {EulerSwapHook} from "../src/EulerSwapHook.sol";
10+
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
11+
import {HookMiner} from "v4-periphery/src/utils/HookMiner.sol";
12+
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol";
913

1014
contract EulerSwapTestBase is EVaultTestBase {
1115
address public depositor = makeAddr("depositor");
@@ -96,6 +100,38 @@ contract EulerSwapTestBase is EVaultTestBase {
96100
return eulerSwap;
97101
}
98102

103+
function createEulerSwapHook(
104+
IPoolManager _poolManager,
105+
uint112 debtLimitA,
106+
uint112 debtLimitB,
107+
uint256 fee,
108+
uint256 px,
109+
uint256 py,
110+
uint256 cx,
111+
uint256 cy
112+
) internal returns (EulerSwapHook) {
113+
IEulerSwap.Params memory poolParams = getEulerSwapParams(debtLimitA, debtLimitB, fee);
114+
IEulerSwap.CurveParams memory curveParams =
115+
IEulerSwap.CurveParams({priceX: px, priceY: py, concentrationX: cx, concentrationY: cy});
116+
117+
bytes memory constructorArgs = abi.encode(_poolManager, poolParams, curveParams);
118+
(address hookAddress, bytes32 salt) = HookMiner.find(
119+
creator,
120+
uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG),
121+
type(EulerSwapHook).creationCode,
122+
constructorArgs
123+
);
124+
125+
vm.prank(creator);
126+
EulerSwapHook eulerSwapHook = new EulerSwapHook{salt: salt}(_poolManager, poolParams, curveParams);
127+
assertEq(address(eulerSwapHook), hookAddress);
128+
129+
vm.prank(holder);
130+
evc.setAccountOperator(holder, address(eulerSwapHook), true);
131+
132+
return eulerSwapHook;
133+
}
134+
99135
function mintAndDeposit(address who, IEVault vault, uint256 amount) internal {
100136
TestERC20 tok = TestERC20(vault.asset());
101137
tok.mint(who, amount);

0 commit comments

Comments
 (0)