Skip to content

Commit dc3cd7c

Browse files
committed
test: integration test
1 parent e491b95 commit dc3cd7c

File tree

1 file changed

+371
-0
lines changed

1 file changed

+371
-0
lines changed

test/IntegrationTest.t.sol

Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.13;
3+
4+
import { SetupHook } from "./SetupHook.t.sol";
5+
import { AsyncOrder } from "@async-swap/types/AsyncOrder.sol";
6+
import { Currency } from "v4-core/interfaces/IPoolManager.sol";
7+
import { CurrencyLibrary } from "v4-core/types/Currency.sol";
8+
9+
contract IntegrationTest is SetupHook {
10+
11+
using CurrencyLibrary for Currency;
12+
13+
address alice = makeAddr("alice");
14+
address bob = makeAddr("bob");
15+
address charlie = makeAddr("charlie");
16+
17+
function setUp() public override {
18+
super.setUp();
19+
topUp(alice, 50 ether);
20+
topUp(bob, 50 ether);
21+
topUp(charlie, 50 ether);
22+
}
23+
24+
function topUp(address _user, uint256 amount) public ownerAction {
25+
token0.transfer(_user, amount);
26+
token1.transfer(_user, amount);
27+
}
28+
29+
function testCompleteSwapAndFillWorkflow() public {
30+
uint256 swapAmount = 2 ether;
31+
32+
// Alice creates async swap order
33+
vm.startPrank(alice);
34+
token0.approve(address(router), swapAmount);
35+
36+
AsyncOrder memory aliceOrder = AsyncOrder({
37+
key: key,
38+
owner: alice,
39+
zeroForOne: true,
40+
amountIn: swapAmount,
41+
sqrtPrice: 2 ** 96
42+
});
43+
44+
router.swap(aliceOrder, abi.encode(alice, address(router)));
45+
vm.stopPrank();
46+
47+
// Verify Alice's order
48+
assertEq(hook.asyncOrder(poolId, alice, true), swapAmount);
49+
assertTrue(hook.isExecutor(poolId, alice, address(router)));
50+
51+
// Bob fills Alice's order
52+
vm.startPrank(bob);
53+
token1.approve(address(router), swapAmount);
54+
router.fillOrder(aliceOrder, "");
55+
vm.stopPrank();
56+
57+
// Verify order completion
58+
assertEq(hook.asyncOrder(poolId, alice, true), 0);
59+
assertEq(manager.balanceOf(alice, currency0.toId()), swapAmount);
60+
}
61+
62+
function testMultipleUsersMultipleOrders() public {
63+
uint256 aliceAmount = 1 ether;
64+
uint256 bobAmount = 1.5 ether;
65+
66+
// Alice creates order (zeroForOne = true)
67+
vm.startPrank(alice);
68+
token0.approve(address(router), aliceAmount);
69+
70+
AsyncOrder memory aliceOrder = AsyncOrder({
71+
key: key,
72+
owner: alice,
73+
zeroForOne: true,
74+
amountIn: aliceAmount,
75+
sqrtPrice: 2 ** 96
76+
});
77+
78+
router.swap(aliceOrder, abi.encode(alice, address(router)));
79+
vm.stopPrank();
80+
81+
// Bob creates order (zeroForOne = false)
82+
vm.startPrank(bob);
83+
token1.approve(address(router), bobAmount);
84+
85+
AsyncOrder memory bobOrder = AsyncOrder({
86+
key: key,
87+
owner: bob,
88+
zeroForOne: false,
89+
amountIn: bobAmount,
90+
sqrtPrice: 2 ** 96
91+
});
92+
93+
router.swap(bobOrder, abi.encode(bob, address(router)));
94+
vm.stopPrank();
95+
96+
// Verify both orders exist
97+
assertEq(hook.asyncOrder(poolId, alice, true), aliceAmount);
98+
assertEq(hook.asyncOrder(poolId, bob, false), bobAmount);
99+
100+
// Charlie fills Alice's order
101+
vm.startPrank(charlie);
102+
token1.approve(address(router), aliceAmount);
103+
router.fillOrder(aliceOrder, "");
104+
vm.stopPrank();
105+
106+
// Charlie fills Bob's order
107+
vm.startPrank(charlie);
108+
token0.approve(address(router), bobAmount);
109+
110+
AsyncOrder memory bobFillOrder = AsyncOrder({
111+
key: key,
112+
owner: bob,
113+
zeroForOne: false,
114+
amountIn: bobAmount,
115+
sqrtPrice: 2 ** 96
116+
});
117+
118+
router.fillOrder(bobFillOrder, "");
119+
vm.stopPrank();
120+
121+
// Verify all orders filled
122+
assertEq(hook.asyncOrder(poolId, alice, true), 0);
123+
assertEq(hook.asyncOrder(poolId, bob, false), 0);
124+
}
125+
126+
function testPartialFillsAndAccumulation() public {
127+
uint256 totalAmount = 3 ether;
128+
uint256 firstSwap = 1 ether;
129+
uint256 secondSwap = 2 ether;
130+
uint256 firstFill = 1.5 ether;
131+
uint256 secondFill = 1.5 ether;
132+
133+
// Alice creates first order
134+
vm.startPrank(alice);
135+
token0.approve(address(router), firstSwap);
136+
137+
AsyncOrder memory aliceOrder1 = AsyncOrder({
138+
key: key,
139+
owner: alice,
140+
zeroForOne: true,
141+
amountIn: firstSwap,
142+
sqrtPrice: 2 ** 96
143+
});
144+
145+
router.swap(aliceOrder1, abi.encode(alice, address(router)));
146+
assertEq(hook.asyncOrder(poolId, alice, true), firstSwap);
147+
148+
// Alice creates second order (accumulates)
149+
token0.approve(address(router), secondSwap);
150+
151+
AsyncOrder memory aliceOrder2 = AsyncOrder({
152+
key: key,
153+
owner: alice,
154+
zeroForOne: true,
155+
amountIn: secondSwap,
156+
sqrtPrice: 2 ** 96
157+
});
158+
159+
router.swap(aliceOrder2, abi.encode(alice, address(router)));
160+
vm.stopPrank();
161+
162+
// Verify accumulated amount
163+
assertEq(hook.asyncOrder(poolId, alice, true), totalAmount);
164+
165+
// Bob partially fills
166+
vm.startPrank(bob);
167+
token1.approve(address(router), firstFill);
168+
169+
AsyncOrder memory fillOrder1 = AsyncOrder({
170+
key: key,
171+
owner: alice,
172+
zeroForOne: true,
173+
amountIn: firstFill,
174+
sqrtPrice: 2 ** 96
175+
});
176+
177+
router.fillOrder(fillOrder1, "");
178+
vm.stopPrank();
179+
180+
// Verify partial fill
181+
assertEq(hook.asyncOrder(poolId, alice, true), totalAmount - firstFill);
182+
183+
// Charlie fills remainder
184+
vm.startPrank(charlie);
185+
token1.approve(address(router), secondFill);
186+
187+
AsyncOrder memory fillOrder2 = AsyncOrder({
188+
key: key,
189+
owner: alice,
190+
zeroForOne: true,
191+
amountIn: secondFill,
192+
sqrtPrice: 2 ** 96
193+
});
194+
195+
router.fillOrder(fillOrder2, "");
196+
vm.stopPrank();
197+
198+
// Verify complete fill
199+
assertEq(hook.asyncOrder(poolId, alice, true), 0);
200+
}
201+
202+
function testBatchOrderExecution() public {
203+
uint256 orderCount = 5;
204+
uint256 amountPerOrder = 0.5 ether;
205+
206+
// Alice creates multiple orders
207+
vm.startPrank(alice);
208+
for (uint i = 0; i < orderCount; i++) {
209+
token0.approve(address(router), amountPerOrder);
210+
211+
AsyncOrder memory order = AsyncOrder({
212+
key: key,
213+
owner: alice,
214+
zeroForOne: true,
215+
amountIn: amountPerOrder,
216+
sqrtPrice: 2 ** 96
217+
});
218+
219+
router.swap(order, abi.encode(alice, address(router)));
220+
}
221+
vm.stopPrank();
222+
223+
// Verify total accumulated
224+
assertEq(hook.asyncOrder(poolId, alice, true), orderCount * amountPerOrder);
225+
226+
// Execute orders one by one using router (since alice set router as executor)
227+
for (uint i = 0; i < orderCount; i++) {
228+
AsyncOrder memory fillOrder = AsyncOrder({
229+
key: key,
230+
owner: alice,
231+
zeroForOne: true,
232+
amountIn: amountPerOrder,
233+
sqrtPrice: 2 ** 96
234+
});
235+
236+
vm.startPrank(bob);
237+
token1.approve(address(router), amountPerOrder);
238+
router.fillOrder(fillOrder, abi.encode(address(router)));
239+
vm.stopPrank();
240+
}
241+
242+
// Verify all orders executed
243+
assertEq(hook.asyncOrder(poolId, alice, true), 0);
244+
}
245+
246+
function testCrossDirectionalOrders() public {
247+
uint256 amount = 1 ether;
248+
249+
// Alice: token0 -> token1 (zeroForOne = true)
250+
vm.startPrank(alice);
251+
token0.approve(address(router), amount);
252+
253+
AsyncOrder memory aliceOrder = AsyncOrder({
254+
key: key,
255+
owner: alice,
256+
zeroForOne: true,
257+
amountIn: amount,
258+
sqrtPrice: 2 ** 96
259+
});
260+
261+
router.swap(aliceOrder, abi.encode(alice, address(router)));
262+
vm.stopPrank();
263+
264+
// Bob: token1 -> token0 (zeroForOne = false)
265+
vm.startPrank(bob);
266+
token1.approve(address(router), amount);
267+
268+
AsyncOrder memory bobOrder = AsyncOrder({
269+
key: key,
270+
owner: bob,
271+
zeroForOne: false,
272+
amountIn: amount,
273+
sqrtPrice: 2 ** 96
274+
});
275+
276+
router.swap(bobOrder, abi.encode(bob, address(router)));
277+
vm.stopPrank();
278+
279+
// Charlie can fill both orders
280+
vm.startPrank(charlie);
281+
282+
// Fill Alice's order (needs token1)
283+
token1.approve(address(router), amount);
284+
router.fillOrder(aliceOrder, "");
285+
286+
// Fill Bob's order (needs token0)
287+
token0.approve(address(router), amount);
288+
router.fillOrder(bobOrder, "");
289+
290+
vm.stopPrank();
291+
292+
// Verify both filled
293+
assertEq(hook.asyncOrder(poolId, alice, true), 0);
294+
assertEq(hook.asyncOrder(poolId, bob, false), 0);
295+
}
296+
297+
function testAlgorithmIntegration() public {
298+
uint256 amount = 1 ether;
299+
300+
// Verify algorithm is set correctly
301+
address algorithmAddress = address(hook.ALGORITHM());
302+
assertTrue(algorithmAddress != address(0));
303+
304+
// Create order to trigger algorithm
305+
vm.startPrank(alice);
306+
token0.approve(address(router), amount);
307+
308+
AsyncOrder memory order = AsyncOrder({
309+
key: key,
310+
owner: alice,
311+
zeroForOne: true,
312+
amountIn: amount,
313+
sqrtPrice: 2 ** 96
314+
});
315+
316+
router.swap(order, abi.encode(alice, address(router)));
317+
vm.stopPrank();
318+
319+
// The swap should succeed, meaning algorithm was called successfully
320+
assertEq(hook.asyncOrder(poolId, alice, true), amount);
321+
}
322+
323+
function testLargeVolumeStressTest() public {
324+
uint256 userCount = 10;
325+
uint256 amountPerUser = 0.1 ether;
326+
327+
// Multiple users create orders
328+
for (uint i = 0; i < userCount; i++) {
329+
address user = address(uint160(i + 1000)); // Generate unique addresses
330+
topUp(user, amountPerUser);
331+
332+
vm.startPrank(user);
333+
token0.approve(address(router), amountPerUser);
334+
335+
AsyncOrder memory order = AsyncOrder({
336+
key: key,
337+
owner: user,
338+
zeroForOne: true,
339+
amountIn: amountPerUser,
340+
sqrtPrice: 2 ** 96
341+
});
342+
343+
router.swap(order, abi.encode(user, address(router)));
344+
vm.stopPrank();
345+
346+
// Verify each order
347+
assertEq(hook.asyncOrder(poolId, user, true), amountPerUser);
348+
}
349+
350+
// Single filler fills all orders
351+
vm.startPrank(charlie);
352+
token1.approve(address(router), userCount * amountPerUser);
353+
354+
for (uint i = 0; i < userCount; i++) {
355+
address user = address(uint160(i + 1000));
356+
357+
AsyncOrder memory fillOrder = AsyncOrder({
358+
key: key,
359+
owner: user,
360+
zeroForOne: true,
361+
amountIn: amountPerUser,
362+
sqrtPrice: 2 ** 96
363+
});
364+
365+
router.fillOrder(fillOrder, "");
366+
assertEq(hook.asyncOrder(poolId, user, true), 0);
367+
}
368+
vm.stopPrank();
369+
}
370+
371+
}

0 commit comments

Comments
 (0)