Skip to content

Commit e491b95

Browse files
committed
test: async filler test cov
1 parent 5d26e5d commit e491b95

File tree

1 file changed

+279
-0
lines changed

1 file changed

+279
-0
lines changed

test/AsyncFillerTest.t.sol

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.13;
3+
4+
import { SetupHook } from "./SetupHook.t.sol";
5+
import { CLVR } from "@async-swap/algorithms/clvr.sol";
6+
import { AsyncOrder } from "@async-swap/types/AsyncOrder.sol";
7+
import { Currency, CurrencyLibrary } from "v4-core/PoolManager.sol";
8+
9+
contract AsyncFillerTest is SetupHook {
10+
11+
using CurrencyLibrary for Currency;
12+
13+
address testUser = makeAddr("testUser");
14+
address testExecutor = makeAddr("testExecutor");
15+
address nonExecutor = makeAddr("nonExecutor");
16+
17+
function setUp() public override {
18+
super.setUp();
19+
topUp(testUser, 10 ether);
20+
topUp(testExecutor, 10 ether);
21+
}
22+
23+
function topUp(address _user, uint256 amount) public ownerAction {
24+
token0.transfer(_user, amount);
25+
token1.transfer(_user, amount);
26+
}
27+
28+
function testIsExecutorTrue() public {
29+
// First create an async order to establish executor relationship
30+
vm.startPrank(testUser);
31+
token0.approve(address(router), 1000);
32+
33+
AsyncOrder memory swapOrder =
34+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: 1000, sqrtPrice: 2 ** 96 });
35+
36+
router.swap(swapOrder, abi.encode(testUser, address(router)));
37+
vm.stopPrank();
38+
39+
bool result = hook.isExecutor(poolId, testUser, address(router));
40+
assertTrue(result);
41+
}
42+
43+
function testIsExecutorFalse() public view {
44+
bool result = hook.isExecutor(poolId, testUser, nonExecutor);
45+
assertFalse(result);
46+
}
47+
48+
function testExecuteOrderWithValidExecutor() public {
49+
// First create an async order by swapping
50+
uint256 swapAmount = 1000;
51+
52+
vm.startPrank(testUser);
53+
token0.approve(address(router), swapAmount);
54+
55+
AsyncOrder memory swapOrder =
56+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: swapAmount, sqrtPrice: 2 ** 96 });
57+
58+
router.swap(swapOrder, abi.encode(testUser, address(router)));
59+
vm.stopPrank();
60+
61+
// Verify executor is set and order exists
62+
assertTrue(hook.isExecutor(poolId, testUser, address(router)));
63+
assertEq(hook.asyncOrder(poolId, testUser, true), swapAmount);
64+
65+
// Now fill the order
66+
AsyncOrder memory fillOrder =
67+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: swapAmount, sqrtPrice: 2 ** 96 });
68+
69+
vm.startPrank(testExecutor);
70+
token1.approve(address(router), swapAmount);
71+
router.fillOrder(fillOrder, abi.encode(address(router)));
72+
vm.stopPrank();
73+
74+
// Verify order was filled
75+
assertEq(hook.asyncOrder(poolId, testUser, true), 0);
76+
}
77+
78+
function testExecuteOrderFailsWithInvalidExecutor() public {
79+
// First create an async order by swapping
80+
uint256 swapAmount = 1000;
81+
82+
vm.startPrank(testUser);
83+
token0.approve(address(router), swapAmount);
84+
85+
AsyncOrder memory swapOrder =
86+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: swapAmount, sqrtPrice: 2 ** 96 });
87+
88+
router.swap(swapOrder, abi.encode(testUser, address(router)));
89+
vm.stopPrank();
90+
91+
// Give nonExecutor enough tokens
92+
topUp(nonExecutor, swapAmount);
93+
94+
// Try to fill with non-executor - this should fail at executor validation
95+
AsyncOrder memory fillOrder =
96+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: swapAmount, sqrtPrice: 2 ** 96 });
97+
98+
vm.startPrank(nonExecutor);
99+
token1.approve(address(router), swapAmount);
100+
vm.expectRevert("Caller is valid not excutor");
101+
hook.executeOrder(fillOrder, "");
102+
vm.stopPrank();
103+
}
104+
105+
function testExecuteOrderPartialFill() public {
106+
uint256 swapAmount = 1000;
107+
uint256 fillAmount = 500;
108+
109+
// Create async order
110+
vm.startPrank(testUser);
111+
token0.approve(address(router), swapAmount);
112+
113+
AsyncOrder memory swapOrder =
114+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: swapAmount, sqrtPrice: 2 ** 96 });
115+
116+
router.swap(swapOrder, abi.encode(testUser, address(router)));
117+
vm.stopPrank();
118+
119+
// Partially fill the order
120+
AsyncOrder memory fillOrder =
121+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: fillAmount, sqrtPrice: 2 ** 96 });
122+
123+
vm.startPrank(testExecutor);
124+
token1.approve(address(router), fillAmount);
125+
router.fillOrder(fillOrder, abi.encode(address(router)));
126+
vm.stopPrank();
127+
128+
// Verify partial fill
129+
assertEq(hook.asyncOrder(poolId, testUser, true), swapAmount - fillAmount);
130+
}
131+
132+
function testExecuteOrderExceedsClaimableAmount() public {
133+
uint256 swapAmount = 1000;
134+
uint256 excessFillAmount = 1500;
135+
136+
// Create async order
137+
vm.startPrank(testUser);
138+
token0.approve(address(router), swapAmount);
139+
140+
AsyncOrder memory swapOrder =
141+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: swapAmount, sqrtPrice: 2 ** 96 });
142+
143+
router.swap(swapOrder, abi.encode(testUser, address(router)));
144+
vm.stopPrank();
145+
146+
// Try to fill more than available
147+
AsyncOrder memory fillOrder =
148+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: excessFillAmount, sqrtPrice: 2 ** 96 });
149+
150+
vm.startPrank(testExecutor);
151+
token1.approve(address(router), excessFillAmount);
152+
vm.expectRevert("Max fill order limit exceed");
153+
router.fillOrder(fillOrder, abi.encode(address(router)));
154+
vm.stopPrank();
155+
}
156+
157+
function testFuzzExecuteOrder(uint256 swapAmount, uint256 fillAmount) public {
158+
vm.assume(swapAmount > 0);
159+
vm.assume(swapAmount <= 1 ether);
160+
vm.assume(fillAmount > 0);
161+
vm.assume(fillAmount <= swapAmount);
162+
163+
topUp(testUser, swapAmount);
164+
topUp(testExecutor, fillAmount);
165+
166+
// Create async order
167+
vm.startPrank(testUser);
168+
token0.approve(address(router), swapAmount);
169+
170+
AsyncOrder memory swapOrder =
171+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: swapAmount, sqrtPrice: 2 ** 96 });
172+
173+
router.swap(swapOrder, abi.encode(testUser, address(router)));
174+
vm.stopPrank();
175+
176+
// Fill the order
177+
AsyncOrder memory fillOrder =
178+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: fillAmount, sqrtPrice: 2 ** 96 });
179+
180+
vm.startPrank(testExecutor);
181+
token1.approve(address(router), fillAmount);
182+
router.fillOrder(fillOrder, abi.encode(address(router)));
183+
vm.stopPrank();
184+
185+
// Verify fill
186+
assertEq(hook.asyncOrder(poolId, testUser, true), swapAmount - fillAmount);
187+
}
188+
189+
function testExecuteOrderZeroAmount() public {
190+
uint256 swapAmount = 1000;
191+
192+
// Create async order
193+
vm.startPrank(testUser);
194+
token0.approve(address(router), swapAmount);
195+
196+
AsyncOrder memory swapOrder =
197+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: swapAmount, sqrtPrice: 2 ** 96 });
198+
199+
router.swap(swapOrder, abi.encode(testUser, address(router)));
200+
vm.stopPrank();
201+
202+
// Try to fill with zero amount
203+
AsyncOrder memory fillOrder =
204+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: 0, sqrtPrice: 2 ** 96 });
205+
206+
vm.startPrank(testExecutor);
207+
vm.expectRevert("ZeroFillOrder()");
208+
hook.executeOrder(fillOrder, "");
209+
vm.stopPrank();
210+
}
211+
212+
function testExecuteOrderBatchMode() public {
213+
uint256 swapAmount1 = 1000;
214+
uint256 swapAmount2 = 800;
215+
address testUser2 = makeAddr("testUser2");
216+
217+
topUp(testUser2, swapAmount2);
218+
219+
// Create first async order and set router as executor
220+
vm.startPrank(testUser);
221+
token0.approve(address(router), swapAmount1);
222+
AsyncOrder memory swapOrder1 =
223+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: swapAmount1, sqrtPrice: 2 ** 96 });
224+
router.swap(swapOrder1, abi.encode(testUser, address(router)));
225+
vm.stopPrank();
226+
227+
// Create second async order and set router as executor
228+
vm.startPrank(testUser2);
229+
token0.approve(address(router), swapAmount2);
230+
AsyncOrder memory swapOrder2 =
231+
AsyncOrder({ key: key, owner: testUser2, zeroForOne: true, amountIn: swapAmount2, sqrtPrice: 2 ** 96 });
232+
router.swap(swapOrder2, abi.encode(testUser2, address(router)));
233+
vm.stopPrank();
234+
235+
// Execute both orders individually (since router does the execution)
236+
AsyncOrder memory fillOrder1 =
237+
AsyncOrder({ key: key, owner: testUser, zeroForOne: true, amountIn: swapAmount1, sqrtPrice: 2 ** 96 });
238+
AsyncOrder memory fillOrder2 =
239+
AsyncOrder({ key: key, owner: testUser2, zeroForOne: true, amountIn: swapAmount2, sqrtPrice: 2 ** 96 });
240+
241+
vm.startPrank(testExecutor);
242+
token1.approve(address(router), swapAmount1 + swapAmount2);
243+
244+
router.fillOrder(fillOrder1, abi.encode(address(router)));
245+
router.fillOrder(fillOrder2, abi.encode(address(router)));
246+
vm.stopPrank();
247+
248+
// Verify both orders were filled
249+
assertEq(hook.asyncOrder(poolId, testUser, true), 0);
250+
assertEq(hook.asyncOrder(poolId, testUser2, true), 0);
251+
}
252+
253+
function testExecuteOrderZeroForOneFalse() public {
254+
uint256 swapAmount = 1000;
255+
256+
// Create async order (zeroForOne = false)
257+
vm.startPrank(testUser);
258+
token1.approve(address(router), swapAmount);
259+
260+
AsyncOrder memory swapOrder =
261+
AsyncOrder({ key: key, owner: testUser, zeroForOne: false, amountIn: swapAmount, sqrtPrice: 2 ** 96 });
262+
263+
router.swap(swapOrder, abi.encode(testUser, address(router)));
264+
vm.stopPrank();
265+
266+
// Fill the order
267+
AsyncOrder memory fillOrder =
268+
AsyncOrder({ key: key, owner: testUser, zeroForOne: false, amountIn: swapAmount, sqrtPrice: 2 ** 96 });
269+
270+
vm.startPrank(testExecutor);
271+
token0.approve(address(router), swapAmount);
272+
router.fillOrder(fillOrder, abi.encode(address(router)));
273+
vm.stopPrank();
274+
275+
// Verify order was filled
276+
assertEq(hook.asyncOrder(poolId, testUser, false), 0);
277+
}
278+
279+
}

0 commit comments

Comments
 (0)