@zoralabs/limit-orders 0.2.0 → 0.2.2
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/.turbo/turbo-build$colon$js.log +50 -49
- package/CHANGELOG.md +73 -0
- package/abis/ISetLimitOrderConfig.json +27 -0
- package/abis/IWETH.json +118 -0
- package/abis/IZoraLimitOrderBook.json +5 -0
- package/abis/LimitOrderLiquidity.json +7 -0
- package/abis/LimitOrderViews.json +62 -0
- package/abis/{SimpleAccessManaged.json → Ownable.json} +29 -10
- package/abis/Ownable2Step.json +115 -0
- package/abis/PermittedCallers.json +181 -0
- package/abis/SwapWithLimitOrders.json +134 -14
- package/abis/ZoraLimitOrderBook.json +187 -35
- package/cache/solidity-files-cache.json +1 -1
- package/dist/index.cjs +219 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +219 -34
- package/dist/index.js.map +1 -1
- package/dist/wagmiGenerated.d.ts +254 -41
- package/dist/wagmiGenerated.d.ts.map +1 -1
- package/out/BalanceDelta.sol/BalanceDeltaLibrary.json +1 -1
- package/out/BeforeSwapDelta.sol/BeforeSwapDeltaLibrary.json +1 -1
- package/out/BitMath.sol/BitMath.json +1 -1
- package/out/BytesLib.sol/BytesLib.json +1 -1
- package/out/CoinCommon.sol/CoinCommon.json +1 -1
- package/out/CoinConfigurationVersions.sol/CoinConfigurationVersions.json +1 -1
- package/out/CoinConstants.sol/CoinConstants.json +1 -1
- package/out/Context.sol/Context.json +1 -1
- package/out/Currency.sol/CurrencyLibrary.json +1 -1
- package/out/CurrencyReserves.sol/CurrencyReserves.json +1 -1
- package/out/CustomRevert.sol/CustomRevert.json +1 -1
- package/out/DopplerMath.sol/DopplerMath.json +1 -1
- package/out/FixedPoint128.sol/FixedPoint128.json +1 -1
- package/out/FixedPoint96.sol/FixedPoint96.json +1 -1
- package/out/FullMath.sol/FullMath.json +1 -1
- package/out/IAllowanceTransfer.sol/IAllowanceTransfer.json +1 -1
- package/out/ICoin.sol/ICoin.json +1 -1
- package/out/ICoin.sol/IHasCoinType.json +1 -1
- package/out/ICoin.sol/IHasPoolKey.json +1 -1
- package/out/ICoin.sol/IHasSwapPath.json +1 -1
- package/out/ICoin.sol/IHasTotalSupplyForPositions.json +1 -1
- package/out/IDeployedCoinVersionLookup.sol/IDeployedCoinVersionLookup.json +1 -1
- package/out/IDopplerErrors.sol/IDopplerErrors.json +1 -1
- package/out/IEIP712.sol/IEIP712.json +1 -1
- package/out/IERC1363.sol/IERC1363.json +1 -1
- package/out/IERC165.sol/IERC165.json +1 -1
- package/out/IERC20.sol/IERC20.json +1 -1
- package/out/IERC20Minimal.sol/IERC20Minimal.json +1 -1
- package/out/IERC6909Claims.sol/IERC6909Claims.json +1 -1
- package/out/IERC7572.sol/IERC7572.json +1 -1
- package/out/IExtsload.sol/IExtsload.json +1 -1
- package/out/IExttload.sol/IExttload.json +1 -1
- package/out/IHasRewardsRecipients.sol/IHasRewardsRecipients.json +1 -1
- package/out/IHooks.sol/IHooks.json +1 -1
- package/out/IMsgSender.sol/IMsgSender.json +1 -1
- package/out/IPoolManager.sol/IPoolManager.json +1 -1
- package/out/IProtocolFees.sol/IProtocolFees.json +1 -1
- package/out/ISetLimitOrderConfig.sol/ISetLimitOrderConfig.json +1 -0
- package/out/ISupportsLimitOrderFill.sol/ISupportsLimitOrderFill.json +1 -1
- package/out/ISwapPathRouter.sol/ISwapPathRouter.json +1 -1
- package/out/ISwapRouter.sol/ISwapRouter.json +1 -1
- package/out/IUniswapV3SwapCallback.sol/IUniswapV3SwapCallback.json +1 -1
- package/out/IUpgradeableV4Hook.sol/IUpgradeableDestinationV4Hook.json +1 -1
- package/out/IUpgradeableV4Hook.sol/IUpgradeableDestinationV4HookWithUpdateableFee.json +1 -1
- package/out/IUpgradeableV4Hook.sol/IUpgradeableV4Hook.json +1 -1
- package/out/IWETH.sol/IWETH.json +1 -0
- package/out/IZoraHookRegistry.sol/IZoraHookRegistry.json +1 -1
- package/out/IZoraLimitOrderBook.sol/IZoraLimitOrderBook.json +1 -1
- package/out/IZoraLimitOrderBookCoinsInterface.sol/IZoraLimitOrderBookCoinsInterface.json +1 -1
- package/out/IZoraV4CoinHook.sol/IZoraV4CoinHook.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/LimitOrderQueues.sol/LimitOrderQueues.json +1 -1
- package/out/LimitOrderStorage.sol/LimitOrderStorage.json +1 -1
- package/out/LimitOrderTypes.sol/LimitOrderTypes.json +1 -1
- package/out/LimitOrderViews.sol/LimitOrderViews.json +1 -0
- package/out/LimitOrderWithdraw.sol/LimitOrderWithdraw.json +1 -1
- package/out/LiquidityAmounts.sol/LiquidityAmounts.json +1 -1
- package/out/LiquidityMath.sol/LiquidityMath.json +1 -1
- package/out/Lock.sol/Lock.json +1 -1
- package/out/NonzeroDeltaCount.sol/NonzeroDeltaCount.json +1 -1
- package/out/Ownable.sol/Ownable.json +1 -0
- package/out/Ownable2Step.sol/Ownable2Step.json +1 -0
- package/out/Path.sol/Path.json +1 -1
- package/out/PathKey.sol/PathKeyLibrary.json +1 -1
- package/out/Permit2Payments.sol/Permit2Payments.json +1 -1
- package/out/PermittedCallers.sol/PermittedCallers.json +1 -0
- package/out/PoolId.sol/PoolIdLibrary.json +1 -1
- package/out/Position.sol/Position.json +1 -1
- package/out/SafeCast.sol/SafeCast.json +1 -1
- package/out/SafeCast160.sol/SafeCast160.json +1 -1
- package/out/SafeERC20.sol/SafeERC20.json +1 -1
- package/out/SqrtPriceMath.sol/SqrtPriceMath.json +1 -1
- package/out/StateLibrary.sol/StateLibrary.json +1 -1
- package/out/SwapLimitOrders.sol/SwapLimitOrders.json +1 -1
- package/out/SwapWithLimitOrders.sol/SwapWithLimitOrders.json +1 -1
- package/out/TickBitmap.sol/TickBitmap.json +1 -1
- package/out/TickMath.sol/TickMath.json +1 -1
- package/out/TransientSlot.sol/TransientSlot.json +1 -1
- package/out/TransientStateLibrary.sol/TransientStateLibrary.json +1 -1
- package/out/UniV4SwapToCurrency.sol/UniV4SwapToCurrency.json +1 -1
- package/out/UnsafeMath.sol/UnsafeMath.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 +1 -0
- package/out/uniswap/BitMath.sol/BitMath.json +1 -1
- package/out/uniswap/CustomRevert.sol/CustomRevert.json +1 -1
- package/out/uniswap/FullMath.sol/FullMath.json +1 -1
- package/out/uniswap/SafeCast.sol/SafeCast.json +1 -1
- package/out/uniswap/TickMath.sol/TickMath.json +1 -1
- package/package/wagmiGenerated.ts +218 -33
- package/package.json +1 -1
- package/src/IZoraLimitOrderBook.sol +5 -5
- package/src/ZoraLimitOrderBook.sol +24 -41
- package/src/access/PermittedCallers.sol +41 -0
- package/src/libs/LimitOrderBitmap.sol +0 -51
- package/src/libs/LimitOrderCommon.sol +48 -30
- package/src/libs/LimitOrderCreate.sol +5 -18
- package/src/libs/LimitOrderFill.sol +32 -161
- package/src/libs/LimitOrderLiquidity.sol +92 -71
- package/src/libs/LimitOrderViews.sol +168 -0
- package/src/libs/LimitOrderWithdraw.sol +13 -4
- package/src/libs/SwapLimitOrders.sol +14 -7
- package/src/router/ISetLimitOrderConfig.sol +12 -0
- package/src/router/SwapWithLimitOrders.sol +46 -33
- package/test/LimitOrderAccessControl.t.sol +173 -156
- package/test/LimitOrderBitmap.t.sol +13 -7
- package/test/LimitOrderFill.t.sol +42 -4
- package/test/LimitOrderLibraries.t.sol +18 -10
- package/test/LimitOrderLiquidityPayouts.t.sol +280 -3
- package/test/LimitOrderWithdraw.t.sol +28 -1
- package/test/SwapWithLimitOrders.t.sol +3 -5
- package/test/SwapWithLimitOrdersRouter.t.sol +108 -13
- package/test/gas/LimitOrderFillGas.t.sol +0 -7
- package/test/gas/LimitOrderSwapGas.t.sol +0 -6
- package/test/unit/LimitOrderBitmapUnit.t.sol +0 -134
- package/test/unit/LimitOrderCreateUnit.t.sol +32 -0
- package/test/unit/SwapLimitOrdersUnit.t.sol +231 -33
- package/test/unit/SwapLimitOrdersValidation.t.sol +28 -42
- package/test/unit/SwapWithLimitOrdersUnit.t.sol +21 -88
- package/test/utils/BaseTest.sol +34 -22
- package/test/utils/MockWETH.sol +39 -0
- package/test/utils/TestableZoraLimitOrderBook.sol +5 -7
- package/abis/IAuthority.json +0 -31
- package/abis/SimpleAccessManager.json +0 -351
- package/out/IAuthority.sol/IAuthority.json +0 -1
- package/out/SimpleAccessManaged.sol/SimpleAccessManaged.json +0 -1
- package/out/SimpleAccessManager.sol/SimpleAccessManager.json +0 -1
- package/out/build-info/69718f10d1dc37f0.json +0 -1
- package/src/access/SimpleAccessManaged.sol +0 -76
- package/src/access/SimpleAccessManager.sol +0 -268
- package/test/SimpleAccessManager.t.sol +0 -420
|
@@ -32,8 +32,8 @@ contract SwapLimitOrdersWrapper {
|
|
|
32
32
|
return false;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// Must be positive
|
|
36
|
-
return coinDelta > 0
|
|
35
|
+
// Must be positive
|
|
36
|
+
return coinDelta > 0;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -44,7 +44,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
44
44
|
int24 constant TICK_SPACING = 200;
|
|
45
45
|
uint256 constant MULTIPLE_SCALE = 1e18;
|
|
46
46
|
uint256 constant PERCENT_SCALE = 10_000;
|
|
47
|
-
uint256 constant
|
|
47
|
+
uint256 constant TEST_ORDER_SIZE = 1e18; // Convenient test size (1 token for 18-decimal)
|
|
48
48
|
|
|
49
49
|
PoolKey internal testKey;
|
|
50
50
|
SwapLimitOrdersWrapper internal wrapper;
|
|
@@ -202,8 +202,8 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
202
202
|
assertEq(totalPercent, 10000, "total percent should be 10000");
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
/// @notice Tests computeOrders with totalSize
|
|
206
|
-
function
|
|
205
|
+
/// @notice Tests computeOrders with totalSize of zero returns empty
|
|
206
|
+
function test_computeOrders_zeroSize_returnsEmpty() public {
|
|
207
207
|
LimitOrderConfig memory params;
|
|
208
208
|
params.multiples = new uint256[](2);
|
|
209
209
|
params.percentages = new uint256[](2);
|
|
@@ -212,7 +212,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
212
212
|
params.percentages[0] = 5000;
|
|
213
213
|
params.percentages[1] = 5000;
|
|
214
214
|
|
|
215
|
-
uint128 totalSize =
|
|
215
|
+
uint128 totalSize = 0;
|
|
216
216
|
int24 baseTick = 0;
|
|
217
217
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
218
218
|
|
|
@@ -229,11 +229,11 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
229
229
|
assertEq(orders.sizes.length, 0, "sizes should be empty");
|
|
230
230
|
assertEq(orders.ticks.length, 0, "ticks should be empty");
|
|
231
231
|
assertEq(allocated, 0, "allocated should be 0");
|
|
232
|
-
assertEq(unallocated,
|
|
232
|
+
assertEq(unallocated, 0, "unallocated should be 0");
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
/// @notice Tests computeOrders with totalSize
|
|
236
|
-
function
|
|
235
|
+
/// @notice Tests computeOrders with small totalSize creates orders
|
|
236
|
+
function test_computeOrders_smallSize_createsOrders() public {
|
|
237
237
|
LimitOrderConfig memory params;
|
|
238
238
|
params.multiples = new uint256[](2);
|
|
239
239
|
params.percentages = new uint256[](2);
|
|
@@ -242,7 +242,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
242
242
|
params.percentages[0] = 5000;
|
|
243
243
|
params.percentages[1] = 5000;
|
|
244
244
|
|
|
245
|
-
uint128 totalSize = uint128(
|
|
245
|
+
uint128 totalSize = uint128(TEST_ORDER_SIZE); // Exactly at minimum
|
|
246
246
|
int24 baseTick = 0;
|
|
247
247
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
248
248
|
|
|
@@ -262,7 +262,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
/// @notice Tests computeOrders with multiple orders (verifying skip logic exists even if hard to trigger)
|
|
265
|
-
/// @dev Note: Zero-rounding skip is virtually impossible with
|
|
265
|
+
/// @dev Note: Zero-rounding skip is virtually impossible with reasonable sizes and PERCENT_SCALE=10000
|
|
266
266
|
/// since even 1 basis point of 1e18 = 1e14. The skip logic exists for safety in edge cases.
|
|
267
267
|
function test_computeOrders_multipleOrders_createsAll() public {
|
|
268
268
|
LimitOrderConfig memory params;
|
|
@@ -273,7 +273,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
273
273
|
params.percentages[0] = 5000;
|
|
274
274
|
params.percentages[1] = 5000;
|
|
275
275
|
|
|
276
|
-
uint128 totalSize = uint128(
|
|
276
|
+
uint128 totalSize = uint128(TEST_ORDER_SIZE * 10);
|
|
277
277
|
int24 baseTick = 0;
|
|
278
278
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
279
279
|
|
|
@@ -302,7 +302,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
302
302
|
params.percentages[i] = 1000; // 10% each (60% total)
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
-
uint128 totalSize = uint128(
|
|
305
|
+
uint128 totalSize = uint128(TEST_ORDER_SIZE * 100);
|
|
306
306
|
int24 baseTick = 0;
|
|
307
307
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
308
308
|
|
|
@@ -328,7 +328,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
328
328
|
params.multiples[0] = 2 * MULTIPLE_SCALE;
|
|
329
329
|
params.percentages[0] = 10000;
|
|
330
330
|
|
|
331
|
-
uint128 totalSize = uint128(
|
|
331
|
+
uint128 totalSize = uint128(TEST_ORDER_SIZE * 10);
|
|
332
332
|
int24 baseTick = 0;
|
|
333
333
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
334
334
|
|
|
@@ -355,7 +355,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
355
355
|
params.percentages[0] = 6000; // 60%
|
|
356
356
|
params.percentages[1] = 3000; // 30% (total 90%)
|
|
357
357
|
|
|
358
|
-
uint128 totalSize = uint128(1000 *
|
|
358
|
+
uint128 totalSize = uint128(1000 * TEST_ORDER_SIZE);
|
|
359
359
|
int24 baseTick = 0;
|
|
360
360
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
361
361
|
|
|
@@ -392,7 +392,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
392
392
|
params.percentages[1] = 2000; // 20% of remaining
|
|
393
393
|
params.percentages[2] = 2000; // 20% of remaining
|
|
394
394
|
|
|
395
|
-
uint128 totalSize = uint128(100 *
|
|
395
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE); // 100 units for easy math
|
|
396
396
|
int24 baseTick = 0;
|
|
397
397
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
398
398
|
|
|
@@ -430,7 +430,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
430
430
|
params.multiples[0] = 1000 * MULTIPLE_SCALE; // 1000x - extremely high
|
|
431
431
|
params.percentages[0] = 10000; // 100%
|
|
432
432
|
|
|
433
|
-
uint128 totalSize = uint128(100 *
|
|
433
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
434
434
|
int24 baseTick = 0;
|
|
435
435
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
436
436
|
|
|
@@ -453,7 +453,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
453
453
|
params.percentages[0] = 5000;
|
|
454
454
|
params.percentages[1] = 5000;
|
|
455
455
|
|
|
456
|
-
uint128 totalSize = uint128(100 *
|
|
456
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
457
457
|
int24 baseTick = 10000;
|
|
458
458
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
459
459
|
|
|
@@ -474,7 +474,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
474
474
|
params.multiples[0] = 1000000 * MULTIPLE_SCALE; // 1,000,000x
|
|
475
475
|
params.percentages[0] = 10000;
|
|
476
476
|
|
|
477
|
-
uint128 totalSize = uint128(100 *
|
|
477
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
478
478
|
// Use moderate base tick (TickMath has max/min around ±887272)
|
|
479
479
|
int24 baseTick = 100000; // Moderate positive tick
|
|
480
480
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
@@ -494,7 +494,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
494
494
|
params.multiples[0] = 2 * MULTIPLE_SCALE;
|
|
495
495
|
params.percentages[0] = 10000;
|
|
496
496
|
|
|
497
|
-
uint128 totalSize = uint128(100 *
|
|
497
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
498
498
|
// Use moderate negative base tick for currency1
|
|
499
499
|
int24 baseTick = -100000; // Moderate negative tick
|
|
500
500
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
@@ -515,7 +515,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
515
515
|
params.multiples[0] = MULTIPLE_SCALE + (MULTIPLE_SCALE / 100); // 1.01x
|
|
516
516
|
params.percentages[0] = 10000;
|
|
517
517
|
|
|
518
|
-
uint128 totalSize = uint128(100 *
|
|
518
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
519
519
|
int24 baseTick = 0;
|
|
520
520
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
521
521
|
|
|
@@ -534,7 +534,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
534
534
|
params.multiples[0] = MULTIPLE_SCALE + (MULTIPLE_SCALE / 100); // 1.01x
|
|
535
535
|
params.percentages[0] = 10000;
|
|
536
536
|
|
|
537
|
-
uint128 totalSize = uint128(100 *
|
|
537
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
538
538
|
int24 baseTick = 0;
|
|
539
539
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
540
540
|
|
|
@@ -553,7 +553,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
553
553
|
params.multiples[0] = 0; // Zero multiple - should revert in _sqrtMultiple
|
|
554
554
|
params.percentages[0] = 10000;
|
|
555
555
|
|
|
556
|
-
uint128 totalSize = uint128(100 *
|
|
556
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
557
557
|
int24 baseTick = 0;
|
|
558
558
|
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
559
559
|
|
|
@@ -571,7 +571,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
571
571
|
|
|
572
572
|
bool isCoinBuy = false; // NOT isCoinBuy - tests first branch
|
|
573
573
|
address swapper = address(0x1234);
|
|
574
|
-
int128 coinDelta = int128(int256(
|
|
574
|
+
int128 coinDelta = int128(int256(TEST_ORDER_SIZE * 2));
|
|
575
575
|
|
|
576
576
|
assertFalse(wrapper.isLimitOrder(isCoinBuy, swapper, coinDelta, params), "should return false when not coin buy");
|
|
577
577
|
}
|
|
@@ -584,7 +584,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
584
584
|
|
|
585
585
|
bool isCoinBuy = true; // Pass first condition
|
|
586
586
|
address swapper = address(0x1234);
|
|
587
|
-
int128 coinDelta = int128(int256(
|
|
587
|
+
int128 coinDelta = int128(int256(TEST_ORDER_SIZE * 2));
|
|
588
588
|
|
|
589
589
|
assertFalse(wrapper.isLimitOrder(isCoinBuy, swapper, coinDelta, params), "should return false when no orders");
|
|
590
590
|
}
|
|
@@ -597,8 +597,8 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
597
597
|
|
|
598
598
|
bool isCoinBuy = true;
|
|
599
599
|
address swapper = address(0x1234);
|
|
600
|
-
// casting to 'int256' is safe because
|
|
601
|
-
int128 coinDelta = int128(int256(
|
|
600
|
+
// casting to 'int256' is safe because TEST_ORDER_SIZE will not overflow int128
|
|
601
|
+
int128 coinDelta = int128(int256(TEST_ORDER_SIZE * 2));
|
|
602
602
|
|
|
603
603
|
assertFalse(wrapper.isLimitOrder(isCoinBuy, swapper, coinDelta, params), "should return false when no orders");
|
|
604
604
|
}
|
|
@@ -611,7 +611,7 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
611
611
|
|
|
612
612
|
bool isCoinBuy = true;
|
|
613
613
|
address swapper = address(0); // Zero address
|
|
614
|
-
int128 coinDelta = int128(int256(
|
|
614
|
+
int128 coinDelta = int128(int256(TEST_ORDER_SIZE * 2));
|
|
615
615
|
|
|
616
616
|
assertFalse(wrapper.isLimitOrder(isCoinBuy, swapper, coinDelta, params), "should return false when swapper is zero");
|
|
617
617
|
}
|
|
@@ -642,17 +642,17 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
642
642
|
assertFalse(wrapper.isLimitOrder(isCoinBuy, swapper, coinDelta, params), "should return false for zero delta");
|
|
643
643
|
}
|
|
644
644
|
|
|
645
|
-
/// @notice Tests isLimitOrder
|
|
646
|
-
function
|
|
645
|
+
/// @notice Tests isLimitOrder accepts any positive coinDelta
|
|
646
|
+
function test_isLimitOrder_smallSize_returnsTrue() public {
|
|
647
647
|
LimitOrderConfig memory params;
|
|
648
648
|
params.multiples = new uint256[](1);
|
|
649
649
|
params.percentages = new uint256[](1);
|
|
650
650
|
|
|
651
651
|
bool isCoinBuy = true;
|
|
652
652
|
address swapper = address(0x1234);
|
|
653
|
-
int128 coinDelta =
|
|
653
|
+
int128 coinDelta = 1; // Small positive amount
|
|
654
654
|
|
|
655
|
-
|
|
655
|
+
assertTrue(wrapper.isLimitOrder(isCoinBuy, swapper, coinDelta, params), "should return true for any positive amount");
|
|
656
656
|
}
|
|
657
657
|
|
|
658
658
|
/// @notice Tests isLimitOrder when all conditions are met (success case)
|
|
@@ -665,8 +665,206 @@ contract SwapLimitOrdersUnitTest is Test {
|
|
|
665
665
|
|
|
666
666
|
bool isCoinBuy = true;
|
|
667
667
|
address swapper = address(0x1234);
|
|
668
|
-
int128 coinDelta = int128(int256(
|
|
668
|
+
int128 coinDelta = int128(int256(TEST_ORDER_SIZE * 2));
|
|
669
669
|
|
|
670
670
|
assertTrue(wrapper.isLimitOrder(isCoinBuy, swapper, coinDelta, params), "should return true when all conditions met");
|
|
671
671
|
}
|
|
672
|
+
|
|
673
|
+
/// @notice Tests computeOrders with misaligned baseTick produces aligned output ticks
|
|
674
|
+
/// @dev This test verifies the fix for MKT-24: tick misalignment in minAway calculation
|
|
675
|
+
function test_computeOrders_misalignedBaseTick_producesValidTicks() public {
|
|
676
|
+
// Use a pool with tickSpacing = 10 for easier verification
|
|
677
|
+
PoolKey memory smallSpacingKey = PoolKey({
|
|
678
|
+
currency0: Currency.wrap(address(0x1000)),
|
|
679
|
+
currency1: Currency.wrap(address(0x2000)),
|
|
680
|
+
fee: 3000,
|
|
681
|
+
tickSpacing: 10, // Small tick spacing to make misalignment easier to reproduce
|
|
682
|
+
hooks: IHooks(address(0))
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
LimitOrderConfig memory params;
|
|
686
|
+
params.multiples = new uint256[](1);
|
|
687
|
+
params.percentages = new uint256[](1);
|
|
688
|
+
// Use small multiple that would normally produce tick close to base
|
|
689
|
+
params.multiples[0] = MULTIPLE_SCALE + (MULTIPLE_SCALE / 100); // 1.01x
|
|
690
|
+
params.percentages[0] = 10000;
|
|
691
|
+
|
|
692
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
693
|
+
|
|
694
|
+
// Use a baseTick that is NOT aligned to tickSpacing=10
|
|
695
|
+
int24 baseTick = 205; // Not divisible by 10 - misaligned
|
|
696
|
+
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(baseTick);
|
|
697
|
+
|
|
698
|
+
// Test for currency0 (buy orders, tick should be >= baseTick + tickSpacing)
|
|
699
|
+
(Orders memory orders, , ) = SwapLimitOrders.computeOrders(
|
|
700
|
+
smallSpacingKey,
|
|
701
|
+
true, // isCurrency0
|
|
702
|
+
totalSize,
|
|
703
|
+
baseTick,
|
|
704
|
+
sqrtPriceX96,
|
|
705
|
+
params
|
|
706
|
+
);
|
|
707
|
+
|
|
708
|
+
// Verify the returned tick is aligned to tickSpacing
|
|
709
|
+
assertEq(orders.ticks[0] % 10, 0, "tick must be aligned to tick spacing of 10");
|
|
710
|
+
|
|
711
|
+
// Verify tick is at least one tickSpacing away from the aligned baseTick
|
|
712
|
+
// For currency0, baseTick=205 should align down to 200, so minAway=210
|
|
713
|
+
assertGe(orders.ticks[0], 210, "tick should be >= aligned baseTick (200) + spacing (10)");
|
|
714
|
+
|
|
715
|
+
// Test for currency1 (sell orders, tick should be <= baseTick - tickSpacing)
|
|
716
|
+
(Orders memory orders1, , ) = SwapLimitOrders.computeOrders(
|
|
717
|
+
smallSpacingKey,
|
|
718
|
+
false, // !isCurrency0
|
|
719
|
+
totalSize,
|
|
720
|
+
baseTick,
|
|
721
|
+
sqrtPriceX96,
|
|
722
|
+
params
|
|
723
|
+
);
|
|
724
|
+
|
|
725
|
+
// Verify the returned tick is aligned to tickSpacing
|
|
726
|
+
assertEq(orders1.ticks[0] % 10, 0, "tick must be aligned to tick spacing of 10");
|
|
727
|
+
|
|
728
|
+
// Verify tick is at least one tickSpacing away from the aligned baseTick
|
|
729
|
+
// For currency1, baseTick=205 should align up to 210, so minAway=200
|
|
730
|
+
assertLe(orders1.ticks[0], 200, "tick should be <= aligned baseTick (210) - spacing (10)");
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
/// @notice Tests computeOrders with various misaligned baseTicks and tick spacings
|
|
734
|
+
function test_computeOrders_variousMisalignments_allProduceValidTicks() public view {
|
|
735
|
+
LimitOrderConfig memory params;
|
|
736
|
+
params.multiples = new uint256[](1);
|
|
737
|
+
params.percentages = new uint256[](1);
|
|
738
|
+
params.multiples[0] = MULTIPLE_SCALE + (MULTIPLE_SCALE / 50); // 1.02x
|
|
739
|
+
params.percentages[0] = 10000;
|
|
740
|
+
|
|
741
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
742
|
+
|
|
743
|
+
// Test case 1: baseTick=205, tickSpacing=10
|
|
744
|
+
PoolKey memory key10 = testKey;
|
|
745
|
+
key10.tickSpacing = 10;
|
|
746
|
+
int24 baseTick1 = 205;
|
|
747
|
+
uint160 sqrtPrice1 = TickMath.getSqrtPriceAtTick(baseTick1);
|
|
748
|
+
(Orders memory orders1, , ) = SwapLimitOrders.computeOrders(key10, true, totalSize, baseTick1, sqrtPrice1, params);
|
|
749
|
+
assertEq(orders1.ticks[0] % 10, 0, "case 1: tick must be aligned to spacing 10");
|
|
750
|
+
|
|
751
|
+
// Test case 2: baseTick=1505, tickSpacing=200
|
|
752
|
+
PoolKey memory key200 = testKey;
|
|
753
|
+
key200.tickSpacing = 200;
|
|
754
|
+
int24 baseTick2 = 1505;
|
|
755
|
+
uint160 sqrtPrice2 = TickMath.getSqrtPriceAtTick(baseTick2);
|
|
756
|
+
(Orders memory orders2, , ) = SwapLimitOrders.computeOrders(key200, true, totalSize, baseTick2, sqrtPrice2, params);
|
|
757
|
+
assertEq(orders2.ticks[0] % 200, 0, "case 2: tick must be aligned to spacing 200");
|
|
758
|
+
|
|
759
|
+
// Test case 3: negative misaligned baseTick=-95, tickSpacing=10
|
|
760
|
+
int24 baseTick3 = -95;
|
|
761
|
+
uint160 sqrtPrice3 = TickMath.getSqrtPriceAtTick(baseTick3);
|
|
762
|
+
(Orders memory orders3, , ) = SwapLimitOrders.computeOrders(key10, true, totalSize, baseTick3, sqrtPrice3, params);
|
|
763
|
+
assertEq(orders3.ticks[0] % 10, 0, "case 3: tick must be aligned to spacing 10");
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/// @notice Tests computeOrders with already-aligned baseTicks remain aligned
|
|
767
|
+
/// @dev Verifies that the fix doesn't break the common case where baseTick is already aligned
|
|
768
|
+
function test_computeOrders_alignedBaseTick_remainsAligned() public view {
|
|
769
|
+
LimitOrderConfig memory params;
|
|
770
|
+
params.multiples = new uint256[](1);
|
|
771
|
+
params.percentages = new uint256[](1);
|
|
772
|
+
params.multiples[0] = MULTIPLE_SCALE + (MULTIPLE_SCALE / 50); // 1.02x
|
|
773
|
+
params.percentages[0] = 10000;
|
|
774
|
+
|
|
775
|
+
uint128 totalSize = uint128(100 * TEST_ORDER_SIZE);
|
|
776
|
+
|
|
777
|
+
// Test case 1: baseTick=200 (aligned), tickSpacing=10
|
|
778
|
+
PoolKey memory key10 = testKey;
|
|
779
|
+
key10.tickSpacing = 10;
|
|
780
|
+
int24 baseTick1 = 200; // Already divisible by 10
|
|
781
|
+
uint160 sqrtPrice1 = TickMath.getSqrtPriceAtTick(baseTick1);
|
|
782
|
+
(Orders memory orders1, , ) = SwapLimitOrders.computeOrders(key10, true, totalSize, baseTick1, sqrtPrice1, params);
|
|
783
|
+
assertEq(orders1.ticks[0] % 10, 0, "aligned case 1: tick must be aligned to spacing 10");
|
|
784
|
+
assertGe(orders1.ticks[0], baseTick1 + 10, "aligned case 1: tick should be >= baseTick + spacing");
|
|
785
|
+
|
|
786
|
+
// Test case 2: baseTick=1400 (aligned), tickSpacing=200
|
|
787
|
+
PoolKey memory key200 = testKey;
|
|
788
|
+
key200.tickSpacing = 200;
|
|
789
|
+
int24 baseTick2 = 1400; // Already divisible by 200
|
|
790
|
+
uint160 sqrtPrice2 = TickMath.getSqrtPriceAtTick(baseTick2);
|
|
791
|
+
(Orders memory orders2, , ) = SwapLimitOrders.computeOrders(key200, true, totalSize, baseTick2, sqrtPrice2, params);
|
|
792
|
+
assertEq(orders2.ticks[0] % 200, 0, "aligned case 2: tick must be aligned to spacing 200");
|
|
793
|
+
assertGe(orders2.ticks[0], baseTick2 + 200, "aligned case 2: tick should be >= baseTick + spacing");
|
|
794
|
+
|
|
795
|
+
// Test case 3: baseTick=0 (aligned), tickSpacing=10
|
|
796
|
+
int24 baseTick3 = 0; // Already divisible by any spacing
|
|
797
|
+
uint160 sqrtPrice3 = TickMath.getSqrtPriceAtTick(baseTick3);
|
|
798
|
+
(Orders memory orders3, , ) = SwapLimitOrders.computeOrders(key10, true, totalSize, baseTick3, sqrtPrice3, params);
|
|
799
|
+
assertEq(orders3.ticks[0] % 10, 0, "aligned case 3: tick must be aligned to spacing 10");
|
|
800
|
+
assertGe(orders3.ticks[0], baseTick3 + 10, "aligned case 3: tick should be >= baseTick + spacing");
|
|
801
|
+
|
|
802
|
+
// Test case 4: negative aligned baseTick=-100, tickSpacing=10
|
|
803
|
+
int24 baseTick4 = -100; // Already divisible by 10
|
|
804
|
+
uint160 sqrtPrice4 = TickMath.getSqrtPriceAtTick(baseTick4);
|
|
805
|
+
(Orders memory orders4, , ) = SwapLimitOrders.computeOrders(key10, true, totalSize, baseTick4, sqrtPrice4, params);
|
|
806
|
+
assertEq(orders4.ticks[0] % 10, 0, "aligned case 4: tick must be aligned to spacing 10");
|
|
807
|
+
assertGe(orders4.ticks[0], baseTick4 + 10, "aligned case 4: tick should be >= baseTick + spacing");
|
|
808
|
+
}
|
|
809
|
+
|
|
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 {
|
|
813
|
+
LimitOrderConfig memory params;
|
|
814
|
+
params.multiples = new uint256[](1);
|
|
815
|
+
params.percentages = new uint256[](1);
|
|
816
|
+
params.multiples[0] = 2 * MULTIPLE_SCALE;
|
|
817
|
+
params.percentages[0] = 10000;
|
|
818
|
+
|
|
819
|
+
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
|
+
uint160 sqrtPriceX96 = TickMath.MAX_SQRT_PRICE - 1;
|
|
824
|
+
|
|
825
|
+
// 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
|
+
);
|
|
834
|
+
|
|
835
|
+
assertEq(orders.sizes.length, 0, "should create no orders");
|
|
836
|
+
assertEq(allocated, 0, "should not allocate any funds");
|
|
837
|
+
assertEq(unallocated, totalSize, "all funds should be unallocated");
|
|
838
|
+
}
|
|
839
|
+
|
|
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 {
|
|
843
|
+
LimitOrderConfig memory params;
|
|
844
|
+
params.multiples = new uint256[](1);
|
|
845
|
+
params.percentages = new uint256[](1);
|
|
846
|
+
params.multiples[0] = 2 * MULTIPLE_SCALE;
|
|
847
|
+
params.percentages[0] = 10000;
|
|
848
|
+
|
|
849
|
+
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
|
+
uint160 sqrtPriceX96 = TickMath.MIN_SQRT_PRICE + 1;
|
|
855
|
+
|
|
856
|
+
// 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
|
+
);
|
|
865
|
+
|
|
866
|
+
assertEq(orders.sizes.length, 0, "should create no orders");
|
|
867
|
+
assertEq(allocated, 0, "should not allocate any funds");
|
|
868
|
+
assertEq(unallocated, totalSize, "all funds should be unallocated");
|
|
869
|
+
}
|
|
672
870
|
}
|