@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.
Files changed (37) hide show
  1. package/.abi-stability +70 -0
  2. package/.turbo/turbo-build$colon$js.log +40 -40
  3. package/CHANGELOG.md +23 -0
  4. package/cache/solidity-files-cache.json +1 -1
  5. package/out/CoinConfigurationVersions.sol/CoinConfigurationVersions.json +1 -1
  6. package/out/CoinConstants.sol/CoinConstants.json +1 -1
  7. package/out/DopplerMath.sol/DopplerMath.json +1 -1
  8. package/out/ISetLimitOrderConfig.sol/ISetLimitOrderConfig.json +1 -1
  9. package/out/LimitOrderBitmap.sol/LimitOrderBitmap.json +1 -1
  10. package/out/LimitOrderCommon.sol/LimitOrderCommon.json +1 -1
  11. package/out/LimitOrderCreate.sol/LimitOrderCreate.json +1 -1
  12. package/out/LimitOrderFill.sol/LimitOrderFill.json +1 -1
  13. package/out/LimitOrderLiquidity.sol/LimitOrderLiquidity.json +1 -1
  14. package/out/LimitOrderWithdraw.sol/LimitOrderWithdraw.json +1 -1
  15. package/out/PermittedCallers.sol/PermittedCallers.json +1 -1
  16. package/out/SwapLimitOrders.sol/SwapLimitOrders.json +1 -1
  17. package/out/SwapWithLimitOrders.sol/SwapWithLimitOrders.json +1 -1
  18. package/out/UniV4SwapToCurrency.sol/UniV4SwapToCurrency.json +1 -1
  19. package/out/V3ToV4SwapLib.sol/V3ToV4SwapLib.json +1 -1
  20. package/out/ZoraLimitOrderBook.sol/ZoraLimitOrderBook.json +1 -1
  21. package/out/build-info/{37e0124d88d60569.json → 68b2e124c4a02a45.json} +1 -1
  22. package/package.json +4 -2
  23. package/src/access/PermittedCallers.sol +5 -1
  24. package/src/libs/LimitOrderBitmap.sol +0 -1
  25. package/src/libs/LimitOrderCommon.sol +14 -0
  26. package/src/libs/LimitOrderCreate.sol +6 -0
  27. package/src/libs/LimitOrderFill.sol +3 -20
  28. package/src/libs/LimitOrderLiquidity.sol +61 -38
  29. package/src/libs/LimitOrderWithdraw.sol +2 -6
  30. package/src/libs/SwapLimitOrders.sol +13 -7
  31. package/src/router/SwapWithLimitOrders.sol +1 -0
  32. package/test/LimitOrderLiquidityPayouts.t.sol +14 -14
  33. package/test/SwapWithLimitOrdersRouter.t.sol +4 -0
  34. package/test/unit/LimitOrderCreateUnit.t.sol +17 -17
  35. package/test/unit/SwapLimitOrdersUnit.t.sol +47 -86
  36. package/test/unit/SwapLimitOrdersValidation.t.sol +3 -11
  37. 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, uint128 unallocated) = SwapLimitOrders.computeOrders(
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, uint128 allocated, uint128 unallocated) = SwapLimitOrders.computeOrders(
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, uint128 allocated, uint128 unallocated) = SwapLimitOrders.computeOrders(
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, uint128 allocated, uint128 unallocated) = SwapLimitOrders.computeOrders(
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 Tests fix for MKT-35: skip orders when baseTick at maxTick
811
- /// @dev Uses baseTick at maxTick to simulate swap exhausting liquidity
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 Tests fix for MKT-35: skip orders when baseTick at minTick
841
- /// @dev Uses baseTick at minTick to simulate swap exhausting liquidity
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, uint128 allocated, uint128 unallocated) = SwapLimitOrders.computeOrders(
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, uint256 numOrders) internal pure returns (LimitOrderConfig memory) {
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);
@@ -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