@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.
Files changed (154) hide show
  1. package/.turbo/turbo-build$colon$js.log +50 -49
  2. package/CHANGELOG.md +73 -0
  3. package/abis/ISetLimitOrderConfig.json +27 -0
  4. package/abis/IWETH.json +118 -0
  5. package/abis/IZoraLimitOrderBook.json +5 -0
  6. package/abis/LimitOrderLiquidity.json +7 -0
  7. package/abis/LimitOrderViews.json +62 -0
  8. package/abis/{SimpleAccessManaged.json → Ownable.json} +29 -10
  9. package/abis/Ownable2Step.json +115 -0
  10. package/abis/PermittedCallers.json +181 -0
  11. package/abis/SwapWithLimitOrders.json +134 -14
  12. package/abis/ZoraLimitOrderBook.json +187 -35
  13. package/cache/solidity-files-cache.json +1 -1
  14. package/dist/index.cjs +219 -34
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.js +219 -34
  17. package/dist/index.js.map +1 -1
  18. package/dist/wagmiGenerated.d.ts +254 -41
  19. package/dist/wagmiGenerated.d.ts.map +1 -1
  20. package/out/BalanceDelta.sol/BalanceDeltaLibrary.json +1 -1
  21. package/out/BeforeSwapDelta.sol/BeforeSwapDeltaLibrary.json +1 -1
  22. package/out/BitMath.sol/BitMath.json +1 -1
  23. package/out/BytesLib.sol/BytesLib.json +1 -1
  24. package/out/CoinCommon.sol/CoinCommon.json +1 -1
  25. package/out/CoinConfigurationVersions.sol/CoinConfigurationVersions.json +1 -1
  26. package/out/CoinConstants.sol/CoinConstants.json +1 -1
  27. package/out/Context.sol/Context.json +1 -1
  28. package/out/Currency.sol/CurrencyLibrary.json +1 -1
  29. package/out/CurrencyReserves.sol/CurrencyReserves.json +1 -1
  30. package/out/CustomRevert.sol/CustomRevert.json +1 -1
  31. package/out/DopplerMath.sol/DopplerMath.json +1 -1
  32. package/out/FixedPoint128.sol/FixedPoint128.json +1 -1
  33. package/out/FixedPoint96.sol/FixedPoint96.json +1 -1
  34. package/out/FullMath.sol/FullMath.json +1 -1
  35. package/out/IAllowanceTransfer.sol/IAllowanceTransfer.json +1 -1
  36. package/out/ICoin.sol/ICoin.json +1 -1
  37. package/out/ICoin.sol/IHasCoinType.json +1 -1
  38. package/out/ICoin.sol/IHasPoolKey.json +1 -1
  39. package/out/ICoin.sol/IHasSwapPath.json +1 -1
  40. package/out/ICoin.sol/IHasTotalSupplyForPositions.json +1 -1
  41. package/out/IDeployedCoinVersionLookup.sol/IDeployedCoinVersionLookup.json +1 -1
  42. package/out/IDopplerErrors.sol/IDopplerErrors.json +1 -1
  43. package/out/IEIP712.sol/IEIP712.json +1 -1
  44. package/out/IERC1363.sol/IERC1363.json +1 -1
  45. package/out/IERC165.sol/IERC165.json +1 -1
  46. package/out/IERC20.sol/IERC20.json +1 -1
  47. package/out/IERC20Minimal.sol/IERC20Minimal.json +1 -1
  48. package/out/IERC6909Claims.sol/IERC6909Claims.json +1 -1
  49. package/out/IERC7572.sol/IERC7572.json +1 -1
  50. package/out/IExtsload.sol/IExtsload.json +1 -1
  51. package/out/IExttload.sol/IExttload.json +1 -1
  52. package/out/IHasRewardsRecipients.sol/IHasRewardsRecipients.json +1 -1
  53. package/out/IHooks.sol/IHooks.json +1 -1
  54. package/out/IMsgSender.sol/IMsgSender.json +1 -1
  55. package/out/IPoolManager.sol/IPoolManager.json +1 -1
  56. package/out/IProtocolFees.sol/IProtocolFees.json +1 -1
  57. package/out/ISetLimitOrderConfig.sol/ISetLimitOrderConfig.json +1 -0
  58. package/out/ISupportsLimitOrderFill.sol/ISupportsLimitOrderFill.json +1 -1
  59. package/out/ISwapPathRouter.sol/ISwapPathRouter.json +1 -1
  60. package/out/ISwapRouter.sol/ISwapRouter.json +1 -1
  61. package/out/IUniswapV3SwapCallback.sol/IUniswapV3SwapCallback.json +1 -1
  62. package/out/IUpgradeableV4Hook.sol/IUpgradeableDestinationV4Hook.json +1 -1
  63. package/out/IUpgradeableV4Hook.sol/IUpgradeableDestinationV4HookWithUpdateableFee.json +1 -1
  64. package/out/IUpgradeableV4Hook.sol/IUpgradeableV4Hook.json +1 -1
  65. package/out/IWETH.sol/IWETH.json +1 -0
  66. package/out/IZoraHookRegistry.sol/IZoraHookRegistry.json +1 -1
  67. package/out/IZoraLimitOrderBook.sol/IZoraLimitOrderBook.json +1 -1
  68. package/out/IZoraLimitOrderBookCoinsInterface.sol/IZoraLimitOrderBookCoinsInterface.json +1 -1
  69. package/out/IZoraV4CoinHook.sol/IZoraV4CoinHook.json +1 -1
  70. package/out/LimitOrderBitmap.sol/LimitOrderBitmap.json +1 -1
  71. package/out/LimitOrderCommon.sol/LimitOrderCommon.json +1 -1
  72. package/out/LimitOrderCreate.sol/LimitOrderCreate.json +1 -1
  73. package/out/LimitOrderFill.sol/LimitOrderFill.json +1 -1
  74. package/out/LimitOrderLiquidity.sol/LimitOrderLiquidity.json +1 -1
  75. package/out/LimitOrderQueues.sol/LimitOrderQueues.json +1 -1
  76. package/out/LimitOrderStorage.sol/LimitOrderStorage.json +1 -1
  77. package/out/LimitOrderTypes.sol/LimitOrderTypes.json +1 -1
  78. package/out/LimitOrderViews.sol/LimitOrderViews.json +1 -0
  79. package/out/LimitOrderWithdraw.sol/LimitOrderWithdraw.json +1 -1
  80. package/out/LiquidityAmounts.sol/LiquidityAmounts.json +1 -1
  81. package/out/LiquidityMath.sol/LiquidityMath.json +1 -1
  82. package/out/Lock.sol/Lock.json +1 -1
  83. package/out/NonzeroDeltaCount.sol/NonzeroDeltaCount.json +1 -1
  84. package/out/Ownable.sol/Ownable.json +1 -0
  85. package/out/Ownable2Step.sol/Ownable2Step.json +1 -0
  86. package/out/Path.sol/Path.json +1 -1
  87. package/out/PathKey.sol/PathKeyLibrary.json +1 -1
  88. package/out/Permit2Payments.sol/Permit2Payments.json +1 -1
  89. package/out/PermittedCallers.sol/PermittedCallers.json +1 -0
  90. package/out/PoolId.sol/PoolIdLibrary.json +1 -1
  91. package/out/Position.sol/Position.json +1 -1
  92. package/out/SafeCast.sol/SafeCast.json +1 -1
  93. package/out/SafeCast160.sol/SafeCast160.json +1 -1
  94. package/out/SafeERC20.sol/SafeERC20.json +1 -1
  95. package/out/SqrtPriceMath.sol/SqrtPriceMath.json +1 -1
  96. package/out/StateLibrary.sol/StateLibrary.json +1 -1
  97. package/out/SwapLimitOrders.sol/SwapLimitOrders.json +1 -1
  98. package/out/SwapWithLimitOrders.sol/SwapWithLimitOrders.json +1 -1
  99. package/out/TickBitmap.sol/TickBitmap.json +1 -1
  100. package/out/TickMath.sol/TickMath.json +1 -1
  101. package/out/TransientSlot.sol/TransientSlot.json +1 -1
  102. package/out/TransientStateLibrary.sol/TransientStateLibrary.json +1 -1
  103. package/out/UniV4SwapToCurrency.sol/UniV4SwapToCurrency.json +1 -1
  104. package/out/UnsafeMath.sol/UnsafeMath.json +1 -1
  105. package/out/V3ToV4SwapLib.sol/V3ToV4SwapLib.json +1 -1
  106. package/out/ZoraLimitOrderBook.sol/ZoraLimitOrderBook.json +1 -1
  107. package/out/build-info/37e0124d88d60569.json +1 -0
  108. package/out/uniswap/BitMath.sol/BitMath.json +1 -1
  109. package/out/uniswap/CustomRevert.sol/CustomRevert.json +1 -1
  110. package/out/uniswap/FullMath.sol/FullMath.json +1 -1
  111. package/out/uniswap/SafeCast.sol/SafeCast.json +1 -1
  112. package/out/uniswap/TickMath.sol/TickMath.json +1 -1
  113. package/package/wagmiGenerated.ts +218 -33
  114. package/package.json +1 -1
  115. package/src/IZoraLimitOrderBook.sol +5 -5
  116. package/src/ZoraLimitOrderBook.sol +24 -41
  117. package/src/access/PermittedCallers.sol +41 -0
  118. package/src/libs/LimitOrderBitmap.sol +0 -51
  119. package/src/libs/LimitOrderCommon.sol +48 -30
  120. package/src/libs/LimitOrderCreate.sol +5 -18
  121. package/src/libs/LimitOrderFill.sol +32 -161
  122. package/src/libs/LimitOrderLiquidity.sol +92 -71
  123. package/src/libs/LimitOrderViews.sol +168 -0
  124. package/src/libs/LimitOrderWithdraw.sol +13 -4
  125. package/src/libs/SwapLimitOrders.sol +14 -7
  126. package/src/router/ISetLimitOrderConfig.sol +12 -0
  127. package/src/router/SwapWithLimitOrders.sol +46 -33
  128. package/test/LimitOrderAccessControl.t.sol +173 -156
  129. package/test/LimitOrderBitmap.t.sol +13 -7
  130. package/test/LimitOrderFill.t.sol +42 -4
  131. package/test/LimitOrderLibraries.t.sol +18 -10
  132. package/test/LimitOrderLiquidityPayouts.t.sol +280 -3
  133. package/test/LimitOrderWithdraw.t.sol +28 -1
  134. package/test/SwapWithLimitOrders.t.sol +3 -5
  135. package/test/SwapWithLimitOrdersRouter.t.sol +108 -13
  136. package/test/gas/LimitOrderFillGas.t.sol +0 -7
  137. package/test/gas/LimitOrderSwapGas.t.sol +0 -6
  138. package/test/unit/LimitOrderBitmapUnit.t.sol +0 -134
  139. package/test/unit/LimitOrderCreateUnit.t.sol +32 -0
  140. package/test/unit/SwapLimitOrdersUnit.t.sol +231 -33
  141. package/test/unit/SwapLimitOrdersValidation.t.sol +28 -42
  142. package/test/unit/SwapWithLimitOrdersUnit.t.sol +21 -88
  143. package/test/utils/BaseTest.sol +34 -22
  144. package/test/utils/MockWETH.sol +39 -0
  145. package/test/utils/TestableZoraLimitOrderBook.sol +5 -7
  146. package/abis/IAuthority.json +0 -31
  147. package/abis/SimpleAccessManager.json +0 -351
  148. package/out/IAuthority.sol/IAuthority.json +0 -1
  149. package/out/SimpleAccessManaged.sol/SimpleAccessManaged.json +0 -1
  150. package/out/SimpleAccessManager.sol/SimpleAccessManager.json +0 -1
  151. package/out/build-info/69718f10d1dc37f0.json +0 -1
  152. package/src/access/SimpleAccessManaged.sol +0 -76
  153. package/src/access/SimpleAccessManager.sol +0 -268
  154. package/test/SimpleAccessManager.t.sol +0 -420
@@ -10,7 +10,6 @@ pragma solidity ^0.8.28;
10
10
  import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
11
11
  import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
12
12
  import {TransientStateLibrary} from "@uniswap/v4-core/src/libraries/TransientStateLibrary.sol";
13
- import {SimpleAccessManaged} from "./access/SimpleAccessManaged.sol";
14
13
 
15
14
  import {IDeployedCoinVersionLookup} from "@zoralabs/coins/src/interfaces/IDeployedCoinVersionLookup.sol";
16
15
  import {IZoraHookRegistry} from "@zoralabs/coins/src/interfaces/IZoraHookRegistry.sol";
@@ -19,21 +18,26 @@ import {LimitOrderStorage} from "./libs/LimitOrderStorage.sol";
19
18
  import {LimitOrderCreate} from "./libs/LimitOrderCreate.sol";
20
19
  import {LimitOrderFill} from "./libs/LimitOrderFill.sol";
21
20
  import {LimitOrderWithdraw} from "./libs/LimitOrderWithdraw.sol";
21
+ import {LimitOrderViews} from "./libs/LimitOrderViews.sol";
22
22
  import {LimitOrderTypes} from "./libs/LimitOrderTypes.sol";
23
+ import {PermittedCallers} from "./access/PermittedCallers.sol";
23
24
 
24
- contract ZoraLimitOrderBook is IZoraLimitOrderBook, SimpleAccessManaged {
25
+ contract ZoraLimitOrderBook is IZoraLimitOrderBook, PermittedCallers {
25
26
  IPoolManager public immutable poolManager;
26
27
  IDeployedCoinVersionLookup public immutable zoraCoinVersionLookup;
27
28
  IZoraHookRegistry public immutable zoraHookRegistry;
29
+ address public immutable weth;
30
+
31
+ constructor(address poolManager_, address zoraCoinVersionLookup_, address zoraHookRegistry_, address owner_, address weth_) PermittedCallers(owner_) {
32
+ require(poolManager_ != address(0), AddressZero());
33
+ require(zoraCoinVersionLookup_ != address(0), AddressZero());
34
+ require(zoraHookRegistry_ != address(0), AddressZero());
35
+ require(weth_ != address(0), AddressZero());
28
36
 
29
- constructor(address poolManager_, address zoraCoinVersionLookup_, address zoraHookRegistry_, address authority_) SimpleAccessManaged(authority_) {
30
37
  poolManager = IPoolManager(poolManager_);
31
38
  zoraCoinVersionLookup = IDeployedCoinVersionLookup(zoraCoinVersionLookup_);
32
39
  zoraHookRegistry = IZoraHookRegistry(zoraHookRegistry_);
33
- }
34
-
35
- function tickQueueBalance(bytes32 poolKeyHash, address coin, int24 tick) internal view returns (uint256) {
36
- return LimitOrderStorage.layout().tickQueues[poolKeyHash][coin][tick].balance;
40
+ weth = weth_;
37
41
  }
38
42
 
39
43
  /// @inheritdoc IZoraLimitOrderBook
@@ -41,18 +45,10 @@ contract ZoraLimitOrderBook is IZoraLimitOrderBook, SimpleAccessManaged {
41
45
  return LimitOrderStorage.layout().makerBalances[maker][coin];
42
46
  }
43
47
 
44
- function getOrder(bytes32 id) internal view returns (LimitOrderTypes.LimitOrder memory) {
45
- return LimitOrderStorage.layout().limitOrders[id];
46
- }
47
-
48
48
  function getTickQueue(bytes32 poolKeyHash, address coin, int24 tick) internal view returns (LimitOrderTypes.Queue memory) {
49
49
  return LimitOrderStorage.layout().tickQueues[poolKeyHash][coin][tick];
50
50
  }
51
51
 
52
- function getPoolKey(bytes32 poolKeyHash) internal view returns (PoolKey memory) {
53
- return LimitOrderStorage.layout().poolKeys[poolKeyHash];
54
- }
55
-
56
52
  function getPoolEpoch(bytes32 poolKeyHash) internal view returns (uint256) {
57
53
  return LimitOrderStorage.layout().poolEpochs[poolKeyHash];
58
54
  }
@@ -61,10 +57,6 @@ contract ZoraLimitOrderBook is IZoraLimitOrderBook, SimpleAccessManaged {
61
57
  return LimitOrderStorage.layout().makerNonces[maker];
62
58
  }
63
59
 
64
- function getOrderId(bytes32 poolKeyHash, address coin, int24 tick, address maker, uint256 nonce) internal pure returns (bytes32) {
65
- return keccak256(abi.encodePacked(poolKeyHash, coin, tick, maker, nonce));
66
- }
67
-
68
60
  /// @inheritdoc IZoraLimitOrderBook
69
61
  function create(
70
62
  PoolKey memory key,
@@ -72,15 +64,15 @@ contract ZoraLimitOrderBook is IZoraLimitOrderBook, SimpleAccessManaged {
72
64
  uint256[] memory orderSizes,
73
65
  int24[] memory orderTicks,
74
66
  address maker
75
- ) external payable override returns (bytes32[] memory) {
76
- _checkCanCall(this.create.selector);
67
+ ) external payable override onlyPermitted returns (bytes32[] memory) {
77
68
  return LimitOrderCreate.create(LimitOrderStorage.layout(), poolManager, key, isCurrency0, orderSizes, orderTicks, maker);
78
69
  }
79
70
 
80
71
  /// @inheritdoc IZoraLimitOrderBook
81
72
  function fill(PoolKey calldata key, bool isCurrency0, int24 startTick, int24 endTick, uint256 maxFillCount, address fillReferral) external override {
82
- if (maxFillCount == 0) {
83
- maxFillCount = getMaxFillCount();
73
+ uint256 defaultMaxFillCount = getMaxFillCount();
74
+ if (maxFillCount == 0 || maxFillCount > defaultMaxFillCount) {
75
+ maxFillCount = defaultMaxFillCount;
84
76
  }
85
77
 
86
78
  bool isUnlocked = TransientStateLibrary.isUnlocked(poolManager);
@@ -93,9 +85,9 @@ contract ZoraLimitOrderBook is IZoraLimitOrderBook, SimpleAccessManaged {
93
85
  LimitOrderStorage.Layout storage state = LimitOrderStorage.layout();
94
86
  LimitOrderFill.Context memory ctx = _fillContext();
95
87
 
96
- (PoolKey memory canonicalKey, int24 resolvedStart, int24 resolvedEnd) = LimitOrderFill.validateTickRange(
88
+ (PoolKey memory canonicalKey, int24 resolvedStart, int24 resolvedEnd) = LimitOrderViews.validateTickRange(
97
89
  state,
98
- ctx,
90
+ ctx.poolManager,
99
91
  key,
100
92
  isCurrency0,
101
93
  startTick,
@@ -139,8 +131,10 @@ contract ZoraLimitOrderBook is IZoraLimitOrderBook, SimpleAccessManaged {
139
131
 
140
132
  /// @inheritdoc IZoraLimitOrderBook
141
133
  function withdraw(bytes32[] calldata orderIds, address coin, uint256 minAmountOut, address recipient) external override {
142
- bytes32[] memory orderIdsCopy = orderIds;
143
- _unlock(CallbackId.WITHDRAW_ORDERS, _encodeWithdrawOrders(msg.sender, orderIdsCopy, coin, minAmountOut, recipient));
134
+ _unlock(
135
+ CallbackId.WITHDRAW_ORDERS,
136
+ abi.encode(WithdrawOrdersCallbackData({maker: msg.sender, orderIds: orderIds, coin: coin, minAmountOut: minAmountOut, recipient: recipient}))
137
+ );
144
138
  }
145
139
 
146
140
  /// @notice Processes pool-manager unlock callbacks and routes them to the correct handler.
@@ -159,7 +153,7 @@ contract ZoraLimitOrderBook is IZoraLimitOrderBook, SimpleAccessManaged {
159
153
  if (callbackId == CallbackId.FILL) {
160
154
  LimitOrderFill.handleFillCallback(state, _fillContext(), callbackData);
161
155
  } else if (callbackId == CallbackId.WITHDRAW_ORDERS) {
162
- LimitOrderWithdraw.handleWithdrawOrdersCallback(state, poolManager, callbackData);
156
+ LimitOrderWithdraw.handleWithdrawOrdersCallback(state, poolManager, weth, callbackData);
163
157
  } else {
164
158
  revert UnknownCallback();
165
159
  }
@@ -171,9 +165,7 @@ contract ZoraLimitOrderBook is IZoraLimitOrderBook, SimpleAccessManaged {
171
165
  return LimitOrderStorage.layout().maxFillCount;
172
166
  }
173
167
 
174
- function setMaxFillCount(uint256 maxFillCount) external {
175
- _checkCanCall(this.setMaxFillCount.selector);
176
-
168
+ function setMaxFillCount(uint256 maxFillCount) external onlyOwner {
177
169
  LimitOrderStorage.layout().maxFillCount = maxFillCount;
178
170
  }
179
171
 
@@ -184,6 +176,7 @@ contract ZoraLimitOrderBook is IZoraLimitOrderBook, SimpleAccessManaged {
184
176
  function _fillContext() private view returns (LimitOrderFill.Context memory ctx) {
185
177
  ctx.poolManager = poolManager;
186
178
  ctx.versionLookup = zoraCoinVersionLookup;
179
+ ctx.weth = weth;
187
180
  }
188
181
 
189
182
  function _fillData(
@@ -204,16 +197,6 @@ contract ZoraLimitOrderBook is IZoraLimitOrderBook, SimpleAccessManaged {
204
197
  data.orderIds = orderIds;
205
198
  }
206
199
 
207
- function _encodeWithdrawOrders(
208
- address maker,
209
- bytes32[] memory orderIds,
210
- address coin,
211
- uint256 minAmountOut,
212
- address recipient
213
- ) private pure returns (bytes memory) {
214
- return abi.encode(WithdrawOrdersCallbackData({maker: maker, orderIds: orderIds, coin: coin, minAmountOut: minAmountOut, recipient: recipient}));
215
- }
216
-
217
200
  function _unlock(CallbackId callbackId, bytes memory payload) private {
218
201
  poolManager.unlock(abi.encode(callbackId, payload));
219
202
  }
@@ -0,0 +1,41 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
5
+ import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
6
+
7
+ abstract contract PermittedCallers is Ownable2Step {
8
+ address private constant PUBLIC_ACCESS = address(0);
9
+
10
+ mapping(address caller => bool permitted) private _permittedCallers;
11
+
12
+ event PermittedCallerUpdated(address indexed caller, bool permitted);
13
+
14
+ error CallerNotPermitted();
15
+ error PermittedCallersLengthMismatch();
16
+
17
+ constructor(address owner_) Ownable(owner_) {
18
+ _permittedCallers[PUBLIC_ACCESS] = true;
19
+ }
20
+
21
+ modifier onlyPermitted() {
22
+ require(_isPermitted(msg.sender), CallerNotPermitted());
23
+ _;
24
+ }
25
+
26
+ function isPermittedCaller(address caller) public view returns (bool) {
27
+ return _isPermitted(caller);
28
+ }
29
+
30
+ function setPermittedCallers(address[] calldata callers, bool[] calldata permitted) external onlyOwner {
31
+ require(callers.length == permitted.length, PermittedCallersLengthMismatch());
32
+ for (uint256 i = 0; i < callers.length; i++) {
33
+ _permittedCallers[callers[i]] = permitted[i];
34
+ emit PermittedCallerUpdated(callers[i], permitted[i]);
35
+ }
36
+ }
37
+
38
+ function _isPermitted(address caller) internal view returns (bool) {
39
+ return _permittedCallers[PUBLIC_ACCESS] || _permittedCallers[caller];
40
+ }
41
+ }
@@ -27,57 +27,6 @@ library LimitOrderBitmap {
27
27
  }
28
28
  }
29
29
 
30
- function getExecutableTicks(
31
- mapping(int16 => uint256) storage bm,
32
- mapping(int24 => LimitOrderTypes.Queue) storage poolQueue,
33
- int24 tickSpacing,
34
- bool zeroForOne,
35
- int24 tickBeforeSwap,
36
- int24 tickAfterSwap
37
- ) internal view returns (int24[] memory) {
38
- uint256 numTicksCrossed = uint256(int256(_abs(tickBeforeSwap - tickAfterSwap)));
39
- uint256 numTicksToCheck = numTicksCrossed / uint256(int256(tickSpacing)) + 1;
40
-
41
- int24[] memory ticksToCheck = new int24[](numTicksToCheck);
42
- uint256 numExecutableTicks;
43
-
44
- int24 targetTick = tickAfterSwap;
45
- int24 currentTick = tickBeforeSwap;
46
-
47
- while (true) {
48
- if (zeroForOne ? currentTick <= targetTick : currentTick >= targetTick) {
49
- break;
50
- }
51
-
52
- (int24 nextInitializedTick, bool initialized) = TickBitmap.nextInitializedTickWithinOneWord(bm, currentTick, tickSpacing, zeroForOne);
53
-
54
- bool crossesTarget = zeroForOne ? nextInitializedTick <= targetTick : nextInitializedTick > targetTick;
55
-
56
- if (crossesTarget) {
57
- nextInitializedTick = targetTick;
58
- initialized = false;
59
- }
60
-
61
- if (initialized) {
62
- if (poolQueue[nextInitializedTick].length > 0) {
63
- ticksToCheck[numExecutableTicks++] = nextInitializedTick;
64
- }
65
- }
66
-
67
- if (nextInitializedTick == targetTick) {
68
- break;
69
- }
70
-
71
- currentTick = zeroForOne ? nextInitializedTick - 1 : nextInitializedTick;
72
- }
73
-
74
- assembly {
75
- mstore(ticksToCheck, numExecutableTicks)
76
- }
77
-
78
- return ticksToCheck;
79
- }
80
-
81
30
  function _abs(int24 x) private pure returns (int24) {
82
31
  return x < 0 ? -x : x;
83
32
  }
@@ -15,12 +15,13 @@ import {LimitOrderStorage} from "./LimitOrderStorage.sol";
15
15
  import {LimitOrderTypes} from "./LimitOrderTypes.sol";
16
16
  import {LimitOrderQueues} from "./LimitOrderQueues.sol";
17
17
  import {LimitOrderBitmap} from "./LimitOrderBitmap.sol";
18
+ import {LimitOrderCreate} from "./LimitOrderCreate.sol";
18
19
 
19
20
  library LimitOrderCommon {
20
- /// @dev Currency0 orders are executed when the price rises to the lower tick.
21
- /// Currency1 orders are executed when the price falls to the upper tick.
21
+ /// @dev Currency0 orders are executed when the price rises to the upper tick.
22
+ /// Currency1 orders are executed when the price falls to the lower tick.
22
23
  function getOrderTick(LimitOrderTypes.LimitOrder storage order) internal view returns (int24) {
23
- return order.isCurrency0 ? order.tickLower : order.tickUpper;
24
+ return order.isCurrency0 ? order.tickUpper : order.tickLower;
24
25
  }
25
26
 
26
27
  function getOrderCoin(PoolKey memory key, bool isCurrency0) internal pure returns (address) {
@@ -29,42 +30,59 @@ library LimitOrderCommon {
29
30
 
30
31
  function recordCreation(
31
32
  LimitOrderStorage.Layout storage state,
32
- PoolKey memory key,
33
- bytes32 poolKeyHash,
34
- bytes32 orderId,
35
- address maker,
36
- address coin,
37
- bool isCurrency0,
33
+ LimitOrderCreate.CreateContext memory ctx,
34
+ LimitOrderCreate.MintParams memory mintParams,
38
35
  int24 orderTick,
39
- int24 currentTick,
40
- uint256 epoch,
41
- uint128 liquidity,
42
- uint128 realizedSize,
43
- int24 tickLower,
44
- int24 tickUpper
36
+ uint128 realizedSize
45
37
  ) internal {
46
- LimitOrderTypes.LimitOrder storage order = state.limitOrders[orderId];
38
+ _initializeOrder(state.limitOrders[mintParams.orderId], ctx, mintParams, realizedSize);
39
+ _addToQueue(state, ctx, mintParams, orderTick, realizedSize);
40
+ _updateMakerBalanceAndEmit(state, ctx, mintParams.orderId, orderTick, realizedSize);
41
+ }
42
+
43
+ function _initializeOrder(
44
+ LimitOrderTypes.LimitOrder storage order,
45
+ LimitOrderCreate.CreateContext memory ctx,
46
+ LimitOrderCreate.MintParams memory mintParams,
47
+ uint128 realizedSize
48
+ ) private {
47
49
  order.orderSize = realizedSize;
48
- order.liquidity = liquidity;
49
- order.tickLower = tickLower;
50
- order.tickUpper = tickUpper;
51
- order.createdEpoch = uint32(epoch);
50
+ order.liquidity = mintParams.liquidity;
51
+ order.tickLower = mintParams.tickLower;
52
+ order.tickUpper = mintParams.tickUpper;
53
+ order.createdEpoch = uint32(ctx.epoch);
52
54
  order.status = LimitOrderTypes.OrderStatus.OPEN;
53
- order.isCurrency0 = isCurrency0;
54
- order.maker = maker;
55
- order.poolKeyHash = poolKeyHash;
55
+ order.isCurrency0 = ctx.isCurrency0;
56
+ order.maker = ctx.maker;
57
+ order.poolKeyHash = ctx.poolKeyHash;
58
+ }
56
59
 
57
- LimitOrderTypes.Queue storage tickQueue = state.tickQueues[poolKeyHash][coin][orderTick];
60
+ function _addToQueue(
61
+ LimitOrderStorage.Layout storage state,
62
+ LimitOrderCreate.CreateContext memory ctx,
63
+ LimitOrderCreate.MintParams memory mintParams,
64
+ int24 orderTick,
65
+ uint128 realizedSize
66
+ ) private {
67
+ LimitOrderTypes.Queue storage tickQueue = state.tickQueues[ctx.poolKeyHash][ctx.coin][orderTick];
58
68
  tickQueue.balance += realizedSize;
59
69
 
60
- LimitOrderBitmap.setIfFirst(state.tickBitmaps[poolKeyHash][coin], orderTick, key.tickSpacing, tickQueue.length);
61
- LimitOrderQueues.enqueue(tickQueue, state.limitOrders, orderId);
70
+ LimitOrderBitmap.setIfFirst(state.tickBitmaps[ctx.poolKeyHash][ctx.coin], orderTick, mintParams.key.tickSpacing, tickQueue.length);
71
+ LimitOrderQueues.enqueue(tickQueue, state.limitOrders, mintParams.orderId);
72
+ }
62
73
 
63
- uint256 newMakerBalance = state.makerBalances[maker][coin] + realizedSize;
64
- state.makerBalances[maker][coin] = newMakerBalance;
74
+ function _updateMakerBalanceAndEmit(
75
+ LimitOrderStorage.Layout storage state,
76
+ LimitOrderCreate.CreateContext memory ctx,
77
+ bytes32 orderId,
78
+ int24 orderTick,
79
+ uint128 realizedSize
80
+ ) private {
81
+ uint256 newMakerBalance = state.makerBalances[ctx.maker][ctx.coin] + realizedSize;
82
+ state.makerBalances[ctx.maker][ctx.coin] = newMakerBalance;
65
83
 
66
- emit IZoraLimitOrderBook.LimitOrderCreated(maker, coin, poolKeyHash, isCurrency0, orderTick, currentTick, realizedSize, orderId);
67
- emit IZoraLimitOrderBook.MakerBalanceUpdated(maker, coin, newMakerBalance);
84
+ emit IZoraLimitOrderBook.LimitOrderCreated(ctx.maker, ctx.coin, ctx.poolKeyHash, ctx.isCurrency0, orderTick, ctx.currentTick, realizedSize, orderId);
85
+ emit IZoraLimitOrderBook.MakerBalanceUpdated(ctx.maker, ctx.coin, newMakerBalance);
68
86
  }
69
87
 
70
88
  function removeOrder(
@@ -17,6 +17,7 @@ import {LimitOrderStorage} from "./LimitOrderStorage.sol";
17
17
  import {IZoraLimitOrderBook} from "../IZoraLimitOrderBook.sol";
18
18
  import {LimitOrderLiquidity} from "./LimitOrderLiquidity.sol";
19
19
  import {LimitOrderCommon} from "./LimitOrderCommon.sol";
20
+ import {LimitOrderViews} from "./LimitOrderViews.sol";
20
21
  import {CoinCommon} from "@zoralabs/coins/src/libs/CoinCommon.sol";
21
22
  import {TransientStateLibrary} from "@uniswap/v4-core/src/libraries/TransientStateLibrary.sol";
22
23
  import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
@@ -71,7 +72,6 @@ library LimitOrderCreate {
71
72
 
72
73
  function handleCreateCallback(LimitOrderStorage.Layout storage state, IPoolManager poolManager, bytes memory payload) internal returns (bytes memory) {
73
74
  IZoraLimitOrderBook.CreateCallbackData memory data = abi.decode(payload, (IZoraLimitOrderBook.CreateCallbackData));
74
- _validateOrderInputs(data.orderSizes, data.orderTicks, data.maker);
75
75
 
76
76
  bytes32[] memory orderIds = _create(state, poolManager, data);
77
77
 
@@ -159,8 +159,10 @@ library LimitOrderCreate {
159
159
  }
160
160
 
161
161
  (int24 tickLower, int24 tickUpper) = _calculateTickRange(ctx.isCurrency0, orderTick, key.tickSpacing);
162
+ // Record the tick where the order becomes fillable
163
+ orderTick = ctx.isCurrency0 ? tickUpper : tickLower;
162
164
 
163
- uint128 liquidity = LimitOrderLiquidity.liquidityForOrder(ctx.isCurrency0, orderSize, tickLower, tickUpper);
165
+ uint128 liquidity = LimitOrderViews.liquidityForOrder(ctx.isCurrency0, orderSize, tickLower, tickUpper);
164
166
  require(liquidity != 0, IZoraLimitOrderBook.ZeroRealizedOrder());
165
167
 
166
168
  orderId = _generateOrderId(ctx.poolKeyHash, ctx.coin, orderTick, ctx.maker, ++state.makerNonces[ctx.maker]);
@@ -212,22 +214,7 @@ library LimitOrderCreate {
212
214
  LimitOrderLiquidity.refundResidual(mintParams.key, ctx.isCurrency0, ctx.maker, refunded);
213
215
  }
214
216
 
215
- LimitOrderCommon.recordCreation(
216
- state,
217
- mintParams.key,
218
- ctx.poolKeyHash,
219
- mintParams.orderId,
220
- ctx.maker,
221
- ctx.coin,
222
- ctx.isCurrency0,
223
- orderTick,
224
- ctx.currentTick,
225
- ctx.epoch,
226
- mintParams.liquidity,
227
- realized,
228
- mintParams.tickLower,
229
- mintParams.tickUpper
230
- );
217
+ LimitOrderCommon.recordCreation(state, ctx, mintParams, orderTick, realized);
231
218
  }
232
219
 
233
220
  function _mintLiquidity(IPoolManager poolManager, bool isCurrency0, MintParams memory params) private returns (uint128 realizedSize, uint128 refunded) {