@zoralabs/limit-orders 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.abi-stability +70 -0
- package/.turbo/turbo-build$colon$js.log +40 -40
- package/CHANGELOG.md +23 -0
- package/cache/solidity-files-cache.json +1 -1
- package/out/CoinConfigurationVersions.sol/CoinConfigurationVersions.json +1 -1
- package/out/CoinConstants.sol/CoinConstants.json +1 -1
- package/out/DopplerMath.sol/DopplerMath.json +1 -1
- package/out/ISetLimitOrderConfig.sol/ISetLimitOrderConfig.json +1 -1
- package/out/LimitOrderBitmap.sol/LimitOrderBitmap.json +1 -1
- package/out/LimitOrderCommon.sol/LimitOrderCommon.json +1 -1
- package/out/LimitOrderCreate.sol/LimitOrderCreate.json +1 -1
- package/out/LimitOrderFill.sol/LimitOrderFill.json +1 -1
- package/out/LimitOrderLiquidity.sol/LimitOrderLiquidity.json +1 -1
- package/out/LimitOrderWithdraw.sol/LimitOrderWithdraw.json +1 -1
- package/out/PermittedCallers.sol/PermittedCallers.json +1 -1
- package/out/SwapLimitOrders.sol/SwapLimitOrders.json +1 -1
- package/out/SwapWithLimitOrders.sol/SwapWithLimitOrders.json +1 -1
- package/out/UniV4SwapToCurrency.sol/UniV4SwapToCurrency.json +1 -1
- package/out/V3ToV4SwapLib.sol/V3ToV4SwapLib.json +1 -1
- package/out/ZoraLimitOrderBook.sol/ZoraLimitOrderBook.json +1 -1
- package/out/build-info/{37e0124d88d60569.json → 68b2e124c4a02a45.json} +1 -1
- package/package.json +4 -2
- package/src/access/PermittedCallers.sol +5 -1
- package/src/libs/LimitOrderBitmap.sol +0 -1
- package/src/libs/LimitOrderCommon.sol +14 -0
- package/src/libs/LimitOrderCreate.sol +6 -0
- package/src/libs/LimitOrderFill.sol +3 -20
- package/src/libs/LimitOrderLiquidity.sol +61 -38
- package/src/libs/LimitOrderWithdraw.sol +2 -6
- package/src/libs/SwapLimitOrders.sol +13 -7
- package/src/router/SwapWithLimitOrders.sol +1 -0
- package/test/LimitOrderLiquidityPayouts.t.sol +14 -14
- package/test/SwapWithLimitOrdersRouter.t.sol +4 -0
- package/test/unit/LimitOrderCreateUnit.t.sol +17 -17
- package/test/unit/SwapLimitOrdersUnit.t.sol +47 -86
- package/test/unit/SwapLimitOrdersValidation.t.sol +3 -11
- package/test/utils/BaseTest.sol +1 -1
|
@@ -135,7 +135,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/// @notice Tests validation with valid single order
|
|
138
|
-
function test_validateOrderInputs_singleOrder_success() public {
|
|
138
|
+
function test_validateOrderInputs_singleOrder_success() public view {
|
|
139
139
|
uint256[] memory sizes = new uint256[](1);
|
|
140
140
|
int24[] memory ticks = new int24[](1);
|
|
141
141
|
sizes[0] = 1000;
|
|
@@ -146,7 +146,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
/// @notice Tests validation with multiple orders (loop iterations)
|
|
149
|
-
function test_validateOrderInputs_multipleOrders_sumsTotal() public {
|
|
149
|
+
function test_validateOrderInputs_multipleOrders_sumsTotal() public view {
|
|
150
150
|
uint256[] memory sizes = new uint256[](5);
|
|
151
151
|
int24[] memory ticks = new int24[](5);
|
|
152
152
|
|
|
@@ -160,7 +160,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
/// @notice Tests validation loop with many iterations
|
|
163
|
-
function test_validateOrderInputs_manyOrders_loopIterates() public {
|
|
163
|
+
function test_validateOrderInputs_manyOrders_loopIterates() public view {
|
|
164
164
|
uint256[] memory sizes = new uint256[](10);
|
|
165
165
|
int24[] memory ticks = new int24[](10);
|
|
166
166
|
|
|
@@ -222,7 +222,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
/// @notice Tests tick calculation for currency0
|
|
225
|
-
function test_calculateTicks_currency0_setsCorrectRange() public {
|
|
225
|
+
function test_calculateTicks_currency0_setsCorrectRange() public view {
|
|
226
226
|
bool isCurrency0 = true;
|
|
227
227
|
int24 orderTick = 1000;
|
|
228
228
|
int24 spacing = 200;
|
|
@@ -234,7 +234,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
/// @notice Tests tick calculation for currency1
|
|
237
|
-
function test_calculateTicks_currency1_setsCorrectRange() public {
|
|
237
|
+
function test_calculateTicks_currency1_setsCorrectRange() public view {
|
|
238
238
|
bool isCurrency0 = false;
|
|
239
239
|
int24 orderTick = 1000;
|
|
240
240
|
int24 spacing = 200;
|
|
@@ -246,7 +246,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
/// @notice Tests tick calculation with negative ticks
|
|
249
|
-
function test_calculateTicks_negativeTicks_handlesCorrectly() public {
|
|
249
|
+
function test_calculateTicks_negativeTicks_handlesCorrectly() public view {
|
|
250
250
|
bool isCurrency0 = true;
|
|
251
251
|
int24 orderTick = -1000;
|
|
252
252
|
int24 spacing = 200;
|
|
@@ -258,7 +258,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
/// @notice Tests realized size for currency0 with negative amount0
|
|
261
|
-
function test_calculateRealizedSize_currency0_negativeAmount_returnsSize() public {
|
|
261
|
+
function test_calculateRealizedSize_currency0_negativeAmount_returnsSize() public view {
|
|
262
262
|
bool isCurrency0 = true;
|
|
263
263
|
int128 amount0 = -1000;
|
|
264
264
|
int128 amount1 = 500;
|
|
@@ -268,7 +268,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
268
268
|
}
|
|
269
269
|
|
|
270
270
|
/// @notice Tests realized size for currency0 with positive amount0
|
|
271
|
-
function test_calculateRealizedSize_currency0_positiveAmount_returnsZero() public {
|
|
271
|
+
function test_calculateRealizedSize_currency0_positiveAmount_returnsZero() public view {
|
|
272
272
|
bool isCurrency0 = true;
|
|
273
273
|
int128 amount0 = 1000; // Positive
|
|
274
274
|
int128 amount1 = -500;
|
|
@@ -278,7 +278,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
/// @notice Tests realized size for currency1 with negative amount1
|
|
281
|
-
function test_calculateRealizedSize_currency1_negativeAmount_returnsSize() public {
|
|
281
|
+
function test_calculateRealizedSize_currency1_negativeAmount_returnsSize() public view {
|
|
282
282
|
bool isCurrency0 = false;
|
|
283
283
|
int128 amount0 = 500;
|
|
284
284
|
int128 amount1 = -1000;
|
|
@@ -288,7 +288,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
/// @notice Tests realized size for currency1 with positive amount1
|
|
291
|
-
function test_calculateRealizedSize_currency1_positiveAmount_returnsZero() public {
|
|
291
|
+
function test_calculateRealizedSize_currency1_positiveAmount_returnsZero() public view {
|
|
292
292
|
bool isCurrency0 = false;
|
|
293
293
|
int128 amount0 = -500;
|
|
294
294
|
int128 amount1 = 1000; // Positive
|
|
@@ -298,7 +298,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
/// @notice Tests realized size with zero amounts
|
|
301
|
-
function test_calculateRealizedSize_zeroAmounts_returnsZero() public {
|
|
301
|
+
function test_calculateRealizedSize_zeroAmounts_returnsZero() public view {
|
|
302
302
|
bool isCurrency0 = true;
|
|
303
303
|
int128 amount0 = 0;
|
|
304
304
|
int128 amount1 = 0;
|
|
@@ -308,7 +308,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
308
308
|
}
|
|
309
309
|
|
|
310
310
|
/// @notice Tests refund when realized < requested
|
|
311
|
-
function test_calculateRefund_partialRealization_returnsRefund() public {
|
|
311
|
+
function test_calculateRefund_partialRealization_returnsRefund() public view {
|
|
312
312
|
uint128 realizedSize = 800;
|
|
313
313
|
uint128 requestedSize = 1000;
|
|
314
314
|
|
|
@@ -317,7 +317,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
/// @notice Tests refund when realized == requested (no refund)
|
|
320
|
-
function test_calculateRefund_fullRealization_noRefund() public {
|
|
320
|
+
function test_calculateRefund_fullRealization_noRefund() public view {
|
|
321
321
|
uint128 realizedSize = 1000;
|
|
322
322
|
uint128 requestedSize = 1000;
|
|
323
323
|
|
|
@@ -326,7 +326,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
326
326
|
}
|
|
327
327
|
|
|
328
328
|
/// @notice Tests refund when realized > requested (edge case)
|
|
329
|
-
function test_calculateRefund_overRealization_noRefund() public {
|
|
329
|
+
function test_calculateRefund_overRealization_noRefund() public view {
|
|
330
330
|
uint128 realizedSize = 1200;
|
|
331
331
|
uint128 requestedSize = 1000;
|
|
332
332
|
|
|
@@ -344,7 +344,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
344
344
|
}
|
|
345
345
|
|
|
346
346
|
/// @notice Tests validation with empty arrays
|
|
347
|
-
function test_validateOrderInputs_emptyArrays_success() public {
|
|
347
|
+
function test_validateOrderInputs_emptyArrays_success() public view {
|
|
348
348
|
uint256[] memory sizes = new uint256[](0);
|
|
349
349
|
int24[] memory ticks = new int24[](0);
|
|
350
350
|
|
|
@@ -353,7 +353,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
353
353
|
}
|
|
354
354
|
|
|
355
355
|
/// @notice Tests tick calculation with zero spacing (edge case)
|
|
356
|
-
function test_calculateTicks_zeroSpacing_noChange() public {
|
|
356
|
+
function test_calculateTicks_zeroSpacing_noChange() public view {
|
|
357
357
|
bool isCurrency0 = true;
|
|
358
358
|
int24 orderTick = 1000;
|
|
359
359
|
int24 spacing = 0;
|
|
@@ -365,7 +365,7 @@ contract LimitOrderCreateUnitTest is Test {
|
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
/// @notice Tests realized size calculation with large negative values
|
|
368
|
-
function test_calculateRealizedSize_largeNegativeValue_handlesCorrectly() public {
|
|
368
|
+
function test_calculateRealizedSize_largeNegativeValue_handlesCorrectly() public view {
|
|
369
369
|
bool isCurrency0 = true;
|
|
370
370
|
int128 amount0 = -1000000000; // Large negative value
|
|
371
371
|
int128 amount1 = 0;
|
|
@@ -143,7 +143,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
/// @notice Tests validate with all valid inputs (success case)
|
|
146
|
-
function test_validate_success_validParams() public {
|
|
146
|
+
function test_validate_success_validParams() public view {
|
|
147
147
|
LimitOrderConfig memory params;
|
|
148
148
|
params.multiples = new uint256[](3);
|
|
149
149
|
params.percentages = new uint256[](3);
|
|
@@ -160,7 +160,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
/// @notice Tests validate with percentages exactly at 100%
|
|
163
|
-
function test_validate_success_exactlyOneHundredPercent() public {
|
|
163
|
+
function test_validate_success_exactlyOneHundredPercent() public view {
|
|
164
164
|
LimitOrderConfig memory params;
|
|
165
165
|
params.multiples = new uint256[](2);
|
|
166
166
|
params.percentages = new uint256[](2);
|
|
@@ -175,7 +175,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
/// @notice Tests validate loop iterations (line 65 for loop with multiple iterations)
|
|
178
|
-
function test_validate_multipleIterations_checksAllElements() public {
|
|
178
|
+
function test_validate_multipleIterations_checksAllElements() public view {
|
|
179
179
|
LimitOrderConfig memory params;
|
|
180
180
|
params.multiples = new uint256[](5); // 5 elements to iterate
|
|
181
181
|
params.percentages = new uint256[](5);
|
|
@@ -190,7 +190,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
/// @notice Tests validate with single element (loop executes once)
|
|
193
|
-
function test_validate_singleElement_loopExecutesOnce() public {
|
|
193
|
+
function test_validate_singleElement_loopExecutesOnce() public view {
|
|
194
194
|
LimitOrderConfig memory params;
|
|
195
195
|
params.multiples = new uint256[](1);
|
|
196
196
|
params.percentages = new uint256[](1);
|
|
@@ -203,7 +203,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
/// @notice Tests computeOrders with totalSize of zero returns empty
|
|
206
|
-
function test_computeOrders_zeroSize_returnsEmpty() public {
|
|
206
|
+
function test_computeOrders_zeroSize_returnsEmpty() public view {
|
|
207
207
|
LimitOrderConfig memory params;
|
|
208
208
|
params.multiples = new uint256[](2);
|
|
209
209
|
params.percentages = new uint256[](2);
|
|
@@ -233,7 +233,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
/// @notice Tests computeOrders with small totalSize creates orders
|
|
236
|
-
function test_computeOrders_smallSize_createsOrders() public {
|
|
236
|
+
function test_computeOrders_smallSize_createsOrders() public view {
|
|
237
237
|
LimitOrderConfig memory params;
|
|
238
238
|
params.multiples = new uint256[](2);
|
|
239
239
|
params.percentages = new uint256[](2);
|
|
@@ -246,14 +246,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
246
246
|
int24 baseTick = 0;
|
|
247
247
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
248
248
|
|
|
249
|
-
(Orders memory orders, uint128 allocated,
|
|
250
|
-
testKey,
|
|
251
|
-
true,
|
|
252
|
-
totalSize,
|
|
253
|
-
baseTick,
|
|
254
|
-
sqrtPriceX96,
|
|
255
|
-
params
|
|
256
|
-
);
|
|
249
|
+
(Orders memory orders, uint128 allocated, ) = SwapLimitOrders.computeOrders(testKey, true, totalSize, baseTick, sqrtPriceX96, params);
|
|
257
250
|
|
|
258
251
|
// Should create orders
|
|
259
252
|
assertEq(orders.sizes.length, 2, "should create 2 orders");
|
|
@@ -264,7 +257,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
264
257
|
/// @notice Tests computeOrders with multiple orders (verifying skip logic exists even if hard to trigger)
|
|
265
258
|
/// @dev Note: Zero-rounding skip is virtually impossible with reasonable sizes and PERCENT_SCALE=10000
|
|
266
259
|
/// since even 1 basis point of 1e18 = 1e14. The skip logic exists for safety in edge cases.
|
|
267
|
-
function test_computeOrders_multipleOrders_createsAll() public {
|
|
260
|
+
function test_computeOrders_multipleOrders_createsAll() public view {
|
|
268
261
|
LimitOrderConfig memory params;
|
|
269
262
|
params.multiples = new uint256[](2);
|
|
270
263
|
params.percentages = new uint256[](2);
|
|
@@ -277,14 +270,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
277
270
|
int24 baseTick = 0;
|
|
278
271
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
279
272
|
|
|
280
|
-
(Orders memory orders,
|
|
281
|
-
testKey,
|
|
282
|
-
true,
|
|
283
|
-
totalSize,
|
|
284
|
-
baseTick,
|
|
285
|
-
sqrtPriceX96,
|
|
286
|
-
params
|
|
287
|
-
);
|
|
273
|
+
(Orders memory orders, , ) = SwapLimitOrders.computeOrders(testKey, true, totalSize, baseTick, sqrtPriceX96, params);
|
|
288
274
|
|
|
289
275
|
// Both orders should be created
|
|
290
276
|
assertEq(orders.sizes.length, 2, "should create 2 orders");
|
|
@@ -292,7 +278,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
292
278
|
}
|
|
293
279
|
|
|
294
280
|
/// @notice Tests computeOrders loop with many iterations (line 105 for loop)
|
|
295
|
-
function test_computeOrders_manyOrders_loopIteratesMultipleTimes() public {
|
|
281
|
+
function test_computeOrders_manyOrders_loopIteratesMultipleTimes() public view {
|
|
296
282
|
LimitOrderConfig memory params;
|
|
297
283
|
params.multiples = new uint256[](6); // Many orders
|
|
298
284
|
params.percentages = new uint256[](6);
|
|
@@ -306,14 +292,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
306
292
|
int24 baseTick = 0;
|
|
307
293
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
308
294
|
|
|
309
|
-
(Orders memory orders,
|
|
310
|
-
testKey,
|
|
311
|
-
true,
|
|
312
|
-
totalSize,
|
|
313
|
-
baseTick,
|
|
314
|
-
sqrtPriceX96,
|
|
315
|
-
params
|
|
316
|
-
);
|
|
295
|
+
(Orders memory orders, , ) = SwapLimitOrders.computeOrders(testKey, true, totalSize, baseTick, sqrtPriceX96, params);
|
|
317
296
|
|
|
318
297
|
// All 6 orders should be created
|
|
319
298
|
assertEq(orders.sizes.length, 6, "should create 6 orders");
|
|
@@ -321,7 +300,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
321
300
|
}
|
|
322
301
|
|
|
323
302
|
/// @notice Tests computeOrders with single order (loop executes once)
|
|
324
|
-
function test_computeOrders_singleOrder_loopExecutesOnce() public {
|
|
303
|
+
function test_computeOrders_singleOrder_loopExecutesOnce() public view {
|
|
325
304
|
LimitOrderConfig memory params;
|
|
326
305
|
params.multiples = new uint256[](1);
|
|
327
306
|
params.percentages = new uint256[](1);
|
|
@@ -332,21 +311,14 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
332
311
|
int24 baseTick = 0;
|
|
333
312
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
334
313
|
|
|
335
|
-
(Orders memory orders,
|
|
336
|
-
testKey,
|
|
337
|
-
true,
|
|
338
|
-
totalSize,
|
|
339
|
-
baseTick,
|
|
340
|
-
sqrtPriceX96,
|
|
341
|
-
params
|
|
342
|
-
);
|
|
314
|
+
(Orders memory orders, , ) = SwapLimitOrders.computeOrders(testKey, true, totalSize, baseTick, sqrtPriceX96, params);
|
|
343
315
|
|
|
344
316
|
assertEq(orders.sizes.length, 1, "should create 1 order");
|
|
345
317
|
assertEq(orders.ticks.length, 1, "should have 1 tick");
|
|
346
318
|
}
|
|
347
319
|
|
|
348
320
|
/// @notice Tests computeOrders with large totalSize and valid percentages
|
|
349
|
-
function test_computeOrders_largeSize_allocatesCorrectly() public {
|
|
321
|
+
function test_computeOrders_largeSize_allocatesCorrectly() public view {
|
|
350
322
|
LimitOrderConfig memory params;
|
|
351
323
|
params.multiples = new uint256[](2);
|
|
352
324
|
params.percentages = new uint256[](2);
|
|
@@ -423,7 +395,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
423
395
|
}
|
|
424
396
|
|
|
425
397
|
/// @notice Tests computeOrders with extreme multiples (tick clamping)
|
|
426
|
-
function test_computeOrders_extremeMultiples_clampsToMaxTick() public {
|
|
398
|
+
function test_computeOrders_extremeMultiples_clampsToMaxTick() public view {
|
|
427
399
|
LimitOrderConfig memory params;
|
|
428
400
|
params.multiples = new uint256[](1);
|
|
429
401
|
params.percentages = new uint256[](1);
|
|
@@ -444,7 +416,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
444
416
|
}
|
|
445
417
|
|
|
446
418
|
/// @notice Tests computeOrders for currency1 (isCurrency0 = false) - tests line 147 branch
|
|
447
|
-
function test_computeOrders_currency1_ticksBelowBase() public {
|
|
419
|
+
function test_computeOrders_currency1_ticksBelowBase() public view {
|
|
448
420
|
LimitOrderConfig memory params;
|
|
449
421
|
params.multiples = new uint256[](2);
|
|
450
422
|
params.percentages = new uint256[](2);
|
|
@@ -466,7 +438,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
466
438
|
}
|
|
467
439
|
|
|
468
440
|
/// @notice Tests computeOrders with sqrt price overflow (line 155 branch: scaled > type(uint160).max)
|
|
469
|
-
function test_computeOrders_sqrtPriceOverflow_clampsToMax() public {
|
|
441
|
+
function test_computeOrders_sqrtPriceOverflow_clampsToMax() public view {
|
|
470
442
|
LimitOrderConfig memory params;
|
|
471
443
|
params.multiples = new uint256[](1);
|
|
472
444
|
params.percentages = new uint256[](1);
|
|
@@ -487,7 +459,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
487
459
|
}
|
|
488
460
|
|
|
489
461
|
/// @notice Tests computeOrders near minimum tick boundary (line 169 branch: aligned < minTick)
|
|
490
|
-
function test_computeOrders_nearMinTick_clampsToMin() public {
|
|
462
|
+
function test_computeOrders_nearMinTick_clampsToMin() public view {
|
|
491
463
|
LimitOrderConfig memory params;
|
|
492
464
|
params.multiples = new uint256[](1);
|
|
493
465
|
params.percentages = new uint256[](1);
|
|
@@ -507,7 +479,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
507
479
|
}
|
|
508
480
|
|
|
509
481
|
/// @notice Tests computeOrders with tick too close to base (line 170: isCurrency0 && aligned < minAway)
|
|
510
|
-
function test_computeOrders_currency0_tooCloseToBase_clampsToMinAway() public {
|
|
482
|
+
function test_computeOrders_currency0_tooCloseToBase_clampsToMinAway() public view {
|
|
511
483
|
LimitOrderConfig memory params;
|
|
512
484
|
params.multiples = new uint256[](1);
|
|
513
485
|
params.percentages = new uint256[](1);
|
|
@@ -526,7 +498,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
526
498
|
}
|
|
527
499
|
|
|
528
500
|
/// @notice Tests computeOrders with tick too close to base (line 171: !isCurrency0 && aligned > minAway)
|
|
529
|
-
function test_computeOrders_currency1_tooCloseToBase_clampsToMinAway() public {
|
|
501
|
+
function test_computeOrders_currency1_tooCloseToBase_clampsToMinAway() public view {
|
|
530
502
|
LimitOrderConfig memory params;
|
|
531
503
|
params.multiples = new uint256[](1);
|
|
532
504
|
params.percentages = new uint256[](1);
|
|
@@ -562,7 +534,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
562
534
|
}
|
|
563
535
|
|
|
564
536
|
/// @notice Tests isLimitOrder when not a coin buy (first condition in line 48)
|
|
565
|
-
function test_isLimitOrder_notCoinBuy_returnsFalse() public {
|
|
537
|
+
function test_isLimitOrder_notCoinBuy_returnsFalse() public view {
|
|
566
538
|
LimitOrderConfig memory params;
|
|
567
539
|
params.multiples = new uint256[](1);
|
|
568
540
|
params.percentages = new uint256[](1);
|
|
@@ -577,7 +549,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
577
549
|
}
|
|
578
550
|
|
|
579
551
|
/// @notice Tests isLimitOrder when isCoinBuy is true (ensures we go past first condition)
|
|
580
|
-
function test_isLimitOrder_isCoinBuyTrue_checksOtherConditions() public {
|
|
552
|
+
function test_isLimitOrder_isCoinBuyTrue_checksOtherConditions() public view {
|
|
581
553
|
LimitOrderConfig memory params;
|
|
582
554
|
params.multiples = new uint256[](0); // Empty - no orders
|
|
583
555
|
params.percentages = new uint256[](0);
|
|
@@ -590,7 +562,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
590
562
|
}
|
|
591
563
|
|
|
592
564
|
/// @notice Tests isLimitOrder when no orders in params
|
|
593
|
-
function test_isLimitOrder_noOrders_returnsFalse() public {
|
|
565
|
+
function test_isLimitOrder_noOrders_returnsFalse() public view {
|
|
594
566
|
LimitOrderConfig memory params;
|
|
595
567
|
params.multiples = new uint256[](0);
|
|
596
568
|
params.percentages = new uint256[](0);
|
|
@@ -604,7 +576,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
604
576
|
}
|
|
605
577
|
|
|
606
578
|
/// @notice Tests isLimitOrder when swapper is zero address
|
|
607
|
-
function test_isLimitOrder_zeroSwapper_returnsFalse() public {
|
|
579
|
+
function test_isLimitOrder_zeroSwapper_returnsFalse() public view {
|
|
608
580
|
LimitOrderConfig memory params;
|
|
609
581
|
params.multiples = new uint256[](1);
|
|
610
582
|
params.percentages = new uint256[](1);
|
|
@@ -617,7 +589,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
617
589
|
}
|
|
618
590
|
|
|
619
591
|
/// @notice Tests isLimitOrder when coinDelta is negative
|
|
620
|
-
function test_isLimitOrder_negativeCoinDelta_returnsFalse() public {
|
|
592
|
+
function test_isLimitOrder_negativeCoinDelta_returnsFalse() public view {
|
|
621
593
|
LimitOrderConfig memory params;
|
|
622
594
|
params.multiples = new uint256[](1);
|
|
623
595
|
params.percentages = new uint256[](1);
|
|
@@ -630,7 +602,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
630
602
|
}
|
|
631
603
|
|
|
632
604
|
/// @notice Tests isLimitOrder when coinDelta is zero
|
|
633
|
-
function test_isLimitOrder_zeroCoinDelta_returnsFalse() public {
|
|
605
|
+
function test_isLimitOrder_zeroCoinDelta_returnsFalse() public view {
|
|
634
606
|
LimitOrderConfig memory params;
|
|
635
607
|
params.multiples = new uint256[](1);
|
|
636
608
|
params.percentages = new uint256[](1);
|
|
@@ -643,7 +615,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
643
615
|
}
|
|
644
616
|
|
|
645
617
|
/// @notice Tests isLimitOrder accepts any positive coinDelta
|
|
646
|
-
function test_isLimitOrder_smallSize_returnsTrue() public {
|
|
618
|
+
function test_isLimitOrder_smallSize_returnsTrue() public view {
|
|
647
619
|
LimitOrderConfig memory params;
|
|
648
620
|
params.multiples = new uint256[](1);
|
|
649
621
|
params.percentages = new uint256[](1);
|
|
@@ -656,7 +628,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
656
628
|
}
|
|
657
629
|
|
|
658
630
|
/// @notice Tests isLimitOrder when all conditions are met (success case)
|
|
659
|
-
function test_isLimitOrder_allConditionsMet_returnsTrue() public {
|
|
631
|
+
function test_isLimitOrder_allConditionsMet_returnsTrue() public view {
|
|
660
632
|
LimitOrderConfig memory params;
|
|
661
633
|
params.multiples = new uint256[](1);
|
|
662
634
|
params.percentages = new uint256[](1);
|
|
@@ -672,7 +644,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
672
644
|
|
|
673
645
|
/// @notice Tests computeOrders with misaligned baseTick produces aligned output ticks
|
|
674
646
|
/// @dev This test verifies the fix for MKT-24: tick misalignment in minAway calculation
|
|
675
|
-
function test_computeOrders_misalignedBaseTick_producesValidTicks() public {
|
|
647
|
+
function test_computeOrders_misalignedBaseTick_producesValidTicks() public pure {
|
|
676
648
|
// Use a pool with tickSpacing = 10 for easier verification
|
|
677
649
|
PoolKey memory smallSpacingKey = PoolKey({
|
|
678
650
|
currency0: Currency.wrap(address(0x1000)),
|
|
@@ -807,61 +779,50 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
807
779
|
assertGe(orders4.ticks[0], baseTick4 + 10, "aligned case 4: tick should be >= baseTick + spacing");
|
|
808
780
|
}
|
|
809
781
|
|
|
810
|
-
/// @notice
|
|
811
|
-
|
|
812
|
-
function test_computeOrders_baseTickAtMaxTick_skipsOrders() public view {
|
|
782
|
+
/// @notice Test skip orders when price hits max boundary
|
|
783
|
+
function test_computeOrders_priceAtMax_sentinel_skipsOrders() public view {
|
|
813
784
|
LimitOrderConfig memory params;
|
|
814
785
|
params.multiples = new uint256[](1);
|
|
815
786
|
params.percentages = new uint256[](1);
|
|
816
787
|
params.multiples[0] = 2 * MULTIPLE_SCALE;
|
|
817
788
|
params.percentages[0] = 10000;
|
|
818
789
|
|
|
790
|
+
PoolKey memory key = testKey;
|
|
791
|
+
key.tickSpacing = 1;
|
|
792
|
+
|
|
819
793
|
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
820
|
-
int24 maxTick = TickMath.maxUsableTick(TICK_SPACING);
|
|
821
|
-
int24 baseTick = maxTick;
|
|
822
|
-
// Use MAX_SQRT_PRICE directly since we can't compute sqrt price at maxTick
|
|
823
794
|
uint160 sqrtPriceX96 = TickMath.MAX_SQRT_PRICE - 1;
|
|
795
|
+
int24 baseTick = TickMath.getTickAtSqrtPrice(sqrtPriceX96);
|
|
796
|
+
int24 maxTick = TickMath.maxUsableTick(key.tickSpacing);
|
|
797
|
+
assertLe(baseTick, maxTick, "sanity: tick at/below max");
|
|
824
798
|
|
|
825
799
|
// For currency0 (buy orders), should skip and return all as unallocated
|
|
826
|
-
(Orders memory orders, uint128 allocated, uint128 unallocated) = SwapLimitOrders.computeOrders(
|
|
827
|
-
testKey,
|
|
828
|
-
true,
|
|
829
|
-
totalSize,
|
|
830
|
-
baseTick,
|
|
831
|
-
sqrtPriceX96,
|
|
832
|
-
params
|
|
833
|
-
);
|
|
800
|
+
(Orders memory orders, uint128 allocated, uint128 unallocated) = SwapLimitOrders.computeOrders(key, true, totalSize, baseTick, sqrtPriceX96, params);
|
|
834
801
|
|
|
835
802
|
assertEq(orders.sizes.length, 0, "should create no orders");
|
|
836
803
|
assertEq(allocated, 0, "should not allocate any funds");
|
|
837
804
|
assertEq(unallocated, totalSize, "all funds should be unallocated");
|
|
838
805
|
}
|
|
839
806
|
|
|
840
|
-
/// @notice
|
|
841
|
-
|
|
842
|
-
function test_computeOrders_baseTickAtMinTick_skipsOrders() public view {
|
|
807
|
+
/// @notice Test skip orders when price hits min boundary
|
|
808
|
+
function test_computeOrders_priceAtMin_sentinel_skipsOrders() public view {
|
|
843
809
|
LimitOrderConfig memory params;
|
|
844
810
|
params.multiples = new uint256[](1);
|
|
845
811
|
params.percentages = new uint256[](1);
|
|
846
812
|
params.multiples[0] = 2 * MULTIPLE_SCALE;
|
|
847
813
|
params.percentages[0] = 10000;
|
|
848
814
|
|
|
815
|
+
PoolKey memory key = testKey;
|
|
816
|
+
key.tickSpacing = 1;
|
|
817
|
+
|
|
849
818
|
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
850
|
-
int24 maxTick = TickMath.maxUsableTick(TICK_SPACING);
|
|
851
|
-
int24 minTick = -maxTick;
|
|
852
|
-
int24 baseTick = minTick;
|
|
853
|
-
// Use MIN_SQRT_PRICE directly since we can't compute sqrt price at minTick
|
|
854
819
|
uint160 sqrtPriceX96 = TickMath.MIN_SQRT_PRICE + 1;
|
|
820
|
+
int24 baseTick = TickMath.getTickAtSqrtPrice(sqrtPriceX96);
|
|
821
|
+
int24 maxTick = TickMath.maxUsableTick(key.tickSpacing);
|
|
822
|
+
assertGe(baseTick, -maxTick, "sanity: tick at/above min");
|
|
855
823
|
|
|
856
824
|
// For currency1 (sell orders), should skip and return all as unallocated
|
|
857
|
-
(Orders memory orders, uint128 allocated, uint128 unallocated) = SwapLimitOrders.computeOrders(
|
|
858
|
-
testKey,
|
|
859
|
-
false,
|
|
860
|
-
totalSize,
|
|
861
|
-
baseTick,
|
|
862
|
-
sqrtPriceX96,
|
|
863
|
-
params
|
|
864
|
-
);
|
|
825
|
+
(Orders memory orders, uint128 allocated, uint128 unallocated) = SwapLimitOrders.computeOrders(key, false, totalSize, baseTick, sqrtPriceX96, params);
|
|
865
826
|
|
|
866
827
|
assertEq(orders.sizes.length, 0, "should create no orders");
|
|
867
828
|
assertEq(allocated, 0, "should not allocate any funds");
|
|
@@ -220,14 +220,7 @@ contract SwapLimitOrdersValidationTest is Test {
|
|
|
220
220
|
// Use exactly MIN size which is 1e18
|
|
221
221
|
uint128 totalSize = uint128(TEST_ORDER_SIZE);
|
|
222
222
|
|
|
223
|
-
(Orders memory orders,
|
|
224
|
-
testKey,
|
|
225
|
-
true,
|
|
226
|
-
uint128(totalSize),
|
|
227
|
-
0,
|
|
228
|
-
TickMath.getSqrtPriceAtTick(0),
|
|
229
|
-
params
|
|
230
|
-
);
|
|
223
|
+
(Orders memory orders, , ) = SwapLimitOrders.computeOrders(testKey, true, uint128(totalSize), 0, TickMath.getSqrtPriceAtTick(0), params);
|
|
231
224
|
|
|
232
225
|
// With TEST_ORDER_SIZE (1e18) and 1bp = 1e14, orders should not be skipped
|
|
233
226
|
// Let's just verify we get at least one order
|
|
@@ -266,7 +259,6 @@ contract SwapLimitOrdersValidationTest is Test {
|
|
|
266
259
|
params.multiples[0] = 1000000e18;
|
|
267
260
|
params.percentages[0] = 10000;
|
|
268
261
|
|
|
269
|
-
int24 minTick = -TickMath.maxUsableTick(TICK_SPACING);
|
|
270
262
|
int24 startTick = TickMath.MAX_TICK - 1000;
|
|
271
263
|
|
|
272
264
|
(Orders memory orders, , ) = SwapLimitOrders.computeOrders(
|
|
@@ -386,7 +378,7 @@ contract SwapLimitOrdersValidationTest is Test {
|
|
|
386
378
|
// Test 3 & 4: minAway enforcement tested in previous minimum separation tests
|
|
387
379
|
}
|
|
388
380
|
|
|
389
|
-
function _createValidParams(address maker
|
|
381
|
+
function _createValidParams(address /* maker */, uint256 numOrders) internal pure returns (LimitOrderConfig memory) {
|
|
390
382
|
LimitOrderConfig memory params;
|
|
391
383
|
params.multiples = new uint256[](numOrders);
|
|
392
384
|
params.percentages = new uint256[](numOrders);
|
|
@@ -400,7 +392,7 @@ contract SwapLimitOrdersValidationTest is Test {
|
|
|
400
392
|
return params;
|
|
401
393
|
}
|
|
402
394
|
|
|
403
|
-
function _createEmptyParams(address maker) internal pure returns (LimitOrderConfig memory) {
|
|
395
|
+
function _createEmptyParams(address /* maker */) internal pure returns (LimitOrderConfig memory) {
|
|
404
396
|
LimitOrderConfig memory params;
|
|
405
397
|
params.multiples = new uint256[](0);
|
|
406
398
|
params.percentages = new uint256[](0);
|
package/test/utils/BaseTest.sol
CHANGED
|
@@ -3,7 +3,6 @@ pragma solidity ^0.8.13;
|
|
|
3
3
|
|
|
4
4
|
import {Vm} from "forge-std/Vm.sol";
|
|
5
5
|
import {V4TestSetup} from "@zoralabs/coins/test/utils/V4TestSetup.sol";
|
|
6
|
-
import {IZoraLimitOrderBook} from "../../src/IZoraLimitOrderBook.sol";
|
|
7
6
|
import {TestableZoraLimitOrderBook} from "./TestableZoraLimitOrderBook.sol";
|
|
8
7
|
import {SwapWithLimitOrders} from "../../src/router/SwapWithLimitOrders.sol";
|
|
9
8
|
import {IMsgSender} from "@zoralabs/coins/src/interfaces/IMsgSender.sol";
|
|
@@ -548,6 +547,7 @@ contract BaseTest is V4TestSetup, IMsgSender {
|
|
|
548
547
|
int24 compressed = tick / tickSpacing;
|
|
549
548
|
(int16 wordPos, uint8 bitPos) = TickBitmap.position(compressed);
|
|
550
549
|
uint256 word = _bitmapWord(poolKeyHash, coin, wordPos);
|
|
550
|
+
// forge-lint-ignore incorrect-shift
|
|
551
551
|
return (word & (1 << bitPos)) != 0;
|
|
552
552
|
}
|
|
553
553
|
|