@paraswap/dex-lib 4.8.26 → 4.8.28-uni-v3-rust.0

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 (299) hide show
  1. package/build/dex/balancer-v2/balancer-v2.d.ts +0 -1
  2. package/build/dex/balancer-v2/balancer-v2.js +0 -4
  3. package/build/dex/balancer-v2/balancer-v2.js.map +1 -1
  4. package/build/dex/bebop/bebop.d.ts +0 -1
  5. package/build/dex/bebop/bebop.js +0 -8
  6. package/build/dex/bebop/bebop.js.map +1 -1
  7. package/build/dex/cables/cables.d.ts +0 -1
  8. package/build/dex/cables/cables.js +0 -3
  9. package/build/dex/cables/cables.js.map +1 -1
  10. package/build/dex/curve-v1/curve-v1.d.ts +0 -1
  11. package/build/dex/curve-v1/curve-v1.js +0 -4
  12. package/build/dex/curve-v1/curve-v1.js.map +1 -1
  13. package/build/dex/curve-v1-factory/curve-v1-factory.d.ts +0 -1
  14. package/build/dex/curve-v1-factory/curve-v1-factory.js +0 -4
  15. package/build/dex/curve-v1-factory/curve-v1-factory.js.map +1 -1
  16. package/build/dex/curve-v2/curve-v2.d.ts +0 -1
  17. package/build/dex/curve-v2/curve-v2.js +0 -4
  18. package/build/dex/curve-v2/curve-v2.js.map +1 -1
  19. package/build/dex/hashflow/hashflow.d.ts +0 -1
  20. package/build/dex/hashflow/hashflow.js +0 -5
  21. package/build/dex/hashflow/hashflow.js.map +1 -1
  22. package/build/dex/idex.d.ts +1 -2
  23. package/build/dex/lite-psm/lite-psm.d.ts +0 -1
  24. package/build/dex/lite-psm/lite-psm.js +0 -3
  25. package/build/dex/lite-psm/lite-psm.js.map +1 -1
  26. package/build/dex/native/native.d.ts +0 -1
  27. package/build/dex/native/native.js +0 -6
  28. package/build/dex/native/native.js.map +1 -1
  29. package/build/dex/paraswap-limit-orders/paraswap-limit-orders.d.ts +0 -1
  30. package/build/dex/paraswap-limit-orders/paraswap-limit-orders.js +0 -5
  31. package/build/dex/paraswap-limit-orders/paraswap-limit-orders.js.map +1 -1
  32. package/build/dex/solidly-v3/solidly-v3.d.ts +0 -1
  33. package/build/dex/solidly-v3/solidly-v3.js +0 -4
  34. package/build/dex/solidly-v3/solidly-v3.js.map +1 -1
  35. package/build/dex/uniswap-v3/contract-math/native-bridge.d.ts +15 -0
  36. package/build/dex/uniswap-v3/contract-math/native-bridge.js +71 -0
  37. package/build/dex/uniswap-v3/contract-math/native-bridge.js.map +1 -0
  38. package/build/dex/uniswap-v3/scripts/measure-calc-time.js +222 -110
  39. package/build/dex/uniswap-v3/scripts/measure-calc-time.js.map +1 -1
  40. package/build/dex/uniswap-v3/uniswap-v3-pool.d.ts +3 -0
  41. package/build/dex/uniswap-v3/uniswap-v3-pool.js +6 -0
  42. package/build/dex/uniswap-v3/uniswap-v3-pool.js.map +1 -1
  43. package/build/dex/uniswap-v3/uniswap-v3.d.ts +8 -4
  44. package/build/dex/uniswap-v3/uniswap-v3.js +8 -9
  45. package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
  46. package/build/dex/uniswap-v4/api-go/compare-pricing.d.ts +1 -0
  47. package/build/dex/uniswap-v4/api-go/compare-pricing.js +187 -0
  48. package/build/dex/uniswap-v4/api-go/compare-pricing.js.map +1 -0
  49. package/build/dex/uniswap-v4/api-go/compare-states.d.ts +1 -0
  50. package/build/dex/uniswap-v4/api-go/compare-states.js +149 -0
  51. package/build/dex/uniswap-v4/api-go/compare-states.js.map +1 -0
  52. package/build/dex/uniswap-v4/api-go/fetch-pool-key.d.ts +0 -0
  53. package/build/dex/uniswap-v4/api-go/fetch-pool-key.js +140 -0
  54. package/build/dex/uniswap-v4/api-go/fetch-pool-key.js.map +1 -0
  55. package/build/implementations/local-paraswap-sdk.js +9 -4
  56. package/build/implementations/local-paraswap-sdk.js.map +1 -1
  57. package/build/pricing-helper.d.ts +1 -1
  58. package/build/pricing-helper.js +2 -2
  59. package/build/pricing-helper.js.map +1 -1
  60. package/build/tenderly-simulation.d.ts +221 -0
  61. package/build/tenderly-simulation.js +517 -0
  62. package/build/tenderly-simulation.js.map +1 -0
  63. package/native/Cargo.lock +279 -0
  64. package/native/Cargo.toml +21 -0
  65. package/native/build.rs +5 -0
  66. package/native/package-lock.json +32 -0
  67. package/native/package.json +20 -0
  68. package/native/src/config.rs +40 -0
  69. package/native/src/lib.rs +216 -0
  70. package/native/src/math/bit_math.rs +177 -0
  71. package/native/src/math/full_math.rs +217 -0
  72. package/native/src/math/liquidity_math.rs +72 -0
  73. package/native/src/math/mod.rs +10 -0
  74. package/native/src/math/oracle.rs +493 -0
  75. package/native/src/math/sqrt_price_math.rs +272 -0
  76. package/native/src/math/swap_math.rs +306 -0
  77. package/native/src/math/tick.rs +239 -0
  78. package/native/src/math/tick_bitmap.rs +292 -0
  79. package/native/src/math/tick_math.rs +321 -0
  80. package/native/src/math/unsafe_math.rs +67 -0
  81. package/native/src/pool_state.rs +36 -0
  82. package/native/src/query_outputs.rs +379 -0
  83. package/package.json +2 -1
  84. package/build/abi/BProtocol.json +0 -1155
  85. package/build/abi/Jarvis.json +0 -1172
  86. package/build/abi/MStableAsset.json +0 -1545
  87. package/build/abi/OneInchLp.json +0 -1304
  88. package/build/abi/Onebit.json +0 -736
  89. package/build/abi/Shell.json +0 -1294
  90. package/build/abi/TraderJoeV2Router.json +0 -50
  91. package/build/abi/idle-dao/idle-cdo-factory.json +0 -38
  92. package/build/abi/idle-dao/idle-cdo.json +0 -1245
  93. package/build/abi/infusion/InfusionFactory.json +0 -147
  94. package/build/abi/infusion/InfusionPair.json +0 -658
  95. package/build/abi/infusion/InfusionRouter.json +0 -442
  96. package/build/abi/maker-psm/pot.json +0 -322
  97. package/build/abi/maker-psm/psm.json +0 -243
  98. package/build/abi/maker-psm/vat.json +0 -363
  99. package/build/abi/nomiswap-v2/nomiswap-v2-pool.json +0 -773
  100. package/build/abi/quick-perps/fast-price-events.json +0 -70
  101. package/build/abi/quick-perps/fast-price-feed.json +0 -741
  102. package/build/abi/quick-perps/reader.json +0 -313
  103. package/build/abi/quick-perps/vault-price-feed.json +0 -323
  104. package/build/abi/quick-perps/vault.json +0 -1953
  105. package/build/abi/uniswap-v2/excalibur-pool.json +0 -881
  106. package/build/abi/uniswap-v2/mdex-factory.json +0 -759
  107. package/build/abi/wUSDM.json +0 -757
  108. package/build/abi/zrx.v2.json +0 -1967
  109. package/build/abi/zrx.v3.json +0 -3454
  110. package/build/abi/zrx.v4.json +0 -2193
  111. package/build/dex/OneInchLp.d.ts +0 -24
  112. package/build/dex/OneInchLp.js +0 -43
  113. package/build/dex/OneInchLp.js.map +0 -1
  114. package/build/dex/bProtocol/bProtocol.d.ts +0 -15
  115. package/build/dex/bProtocol/bProtocol.js +0 -56
  116. package/build/dex/bProtocol/bProtocol.js.map +0 -1
  117. package/build/dex/bProtocol/types.d.ts +0 -11
  118. package/build/dex/bProtocol/types.js +0 -8
  119. package/build/dex/bProtocol/types.js.map +0 -1
  120. package/build/dex/ekubo/pools/base-pool.d.ts +0 -47
  121. package/build/dex/ekubo/pools/base-pool.js +0 -184
  122. package/build/dex/ekubo/pools/base-pool.js.map +0 -1
  123. package/build/dex/ekubo/pools/iface.d.ts +0 -46
  124. package/build/dex/ekubo/pools/iface.js +0 -75
  125. package/build/dex/ekubo/pools/iface.js.map +0 -1
  126. package/build/dex/ekubo/pools/math/price.d.ts +0 -7
  127. package/build/dex/ekubo/pools/math/price.js +0 -112
  128. package/build/dex/ekubo/pools/math/price.js.map +0 -1
  129. package/build/dex/ekubo/pools/oracle-pool.d.ts +0 -10
  130. package/build/dex/ekubo/pools/oracle-pool.js +0 -19
  131. package/build/dex/ekubo/pools/oracle-pool.js.map +0 -1
  132. package/build/dex/ekubo/pools/pool-utils.d.ts +0 -44
  133. package/build/dex/ekubo/pools/pool-utils.js +0 -240
  134. package/build/dex/ekubo/pools/pool-utils.js.map +0 -1
  135. package/build/dex/idle-dao/config.d.ts +0 -5
  136. package/build/dex/idle-dao/config.js +0 -24
  137. package/build/dex/idle-dao/config.js.map +0 -1
  138. package/build/dex/idle-dao/idle-dao.d.ts +0 -42
  139. package/build/dex/idle-dao/idle-dao.js +0 -279
  140. package/build/dex/idle-dao/idle-dao.js.map +0 -1
  141. package/build/dex/idle-dao/token_list.d.ts +0 -4
  142. package/build/dex/idle-dao/token_list.js +0 -289
  143. package/build/dex/idle-dao/token_list.js.map +0 -1
  144. package/build/dex/idle-dao/tokens.d.ts +0 -9
  145. package/build/dex/idle-dao/tokens.js +0 -68
  146. package/build/dex/idle-dao/tokens.js.map +0 -1
  147. package/build/dex/idle-dao/types.d.ts +0 -35
  148. package/build/dex/idle-dao/types.js +0 -11
  149. package/build/dex/idle-dao/types.js.map +0 -1
  150. package/build/dex/idle-dao/utils.d.ts +0 -8
  151. package/build/dex/idle-dao/utils.js +0 -149
  152. package/build/dex/idle-dao/utils.js.map +0 -1
  153. package/build/dex/infusion/config.d.ts +0 -3
  154. package/build/dex/infusion/config.js +0 -20
  155. package/build/dex/infusion/config.js.map +0 -1
  156. package/build/dex/infusion/infusion-stable-pool.d.ts +0 -4
  157. package/build/dex/infusion/infusion-stable-pool.js +0 -74
  158. package/build/dex/infusion/infusion-stable-pool.js.map +0 -1
  159. package/build/dex/infusion/infusion.d.ts +0 -51
  160. package/build/dex/infusion/infusion.js +0 -500
  161. package/build/dex/infusion/infusion.js.map +0 -1
  162. package/build/dex/infusion/types.d.ts +0 -45
  163. package/build/dex/infusion/types.js +0 -3
  164. package/build/dex/infusion/types.js.map +0 -1
  165. package/build/dex/infusion/utils/isStablePair.d.ts +0 -2
  166. package/build/dex/infusion/utils/isStablePair.js +0 -18
  167. package/build/dex/infusion/utils/isStablePair.js.map +0 -1
  168. package/build/dex/jarvis.d.ts +0 -56
  169. package/build/dex/jarvis.js +0 -163
  170. package/build/dex/jarvis.js.map +0 -1
  171. package/build/dex/mStable.d.ts +0 -44
  172. package/build/dex/mStable.js +0 -75
  173. package/build/dex/mStable.js.map +0 -1
  174. package/build/dex/maker-psm/config.d.ts +0 -11
  175. package/build/dex/maker-psm/config.js +0 -53
  176. package/build/dex/maker-psm/config.js.map +0 -1
  177. package/build/dex/maker-psm/maker-psm.d.ts +0 -103
  178. package/build/dex/maker-psm/maker-psm.js +0 -493
  179. package/build/dex/maker-psm/maker-psm.js.map +0 -1
  180. package/build/dex/maker-psm/types.d.ts +0 -39
  181. package/build/dex/maker-psm/types.js +0 -3
  182. package/build/dex/maker-psm/types.js.map +0 -1
  183. package/build/dex/onebit/onebit.d.ts +0 -16
  184. package/build/dex/onebit/onebit.js +0 -61
  185. package/build/dex/onebit/onebit.js.map +0 -1
  186. package/build/dex/onebit/types.d.ts +0 -14
  187. package/build/dex/onebit/types.js +0 -8
  188. package/build/dex/onebit/types.js.map +0 -1
  189. package/build/dex/quick-perps/config.d.ts +0 -11
  190. package/build/dex/quick-perps/config.js +0 -27
  191. package/build/dex/quick-perps/config.js.map +0 -1
  192. package/build/dex/quick-perps/fast-price-feed.d.ts +0 -26
  193. package/build/dex/quick-perps/fast-price-feed.js +0 -184
  194. package/build/dex/quick-perps/fast-price-feed.js.map +0 -1
  195. package/build/dex/quick-perps/pool.d.ts +0 -21
  196. package/build/dex/quick-perps/pool.js +0 -229
  197. package/build/dex/quick-perps/pool.js.map +0 -1
  198. package/build/dex/quick-perps/quick-perps.d.ts +0 -53
  199. package/build/dex/quick-perps/quick-perps.js +0 -247
  200. package/build/dex/quick-perps/quick-perps.js.map +0 -1
  201. package/build/dex/quick-perps/types.d.ts +0 -98
  202. package/build/dex/quick-perps/types.js +0 -3
  203. package/build/dex/quick-perps/types.js.map +0 -1
  204. package/build/dex/quick-perps/usdq.d.ts +0 -15
  205. package/build/dex/quick-perps/usdq.js +0 -62
  206. package/build/dex/quick-perps/usdq.js.map +0 -1
  207. package/build/dex/quick-perps/vault-price-feed.d.ts +0 -43
  208. package/build/dex/quick-perps/vault-price-feed.js +0 -203
  209. package/build/dex/quick-perps/vault-price-feed.js.map +0 -1
  210. package/build/dex/quick-perps/vault-utils.d.ts +0 -8
  211. package/build/dex/quick-perps/vault-utils.js +0 -42
  212. package/build/dex/quick-perps/vault-utils.js.map +0 -1
  213. package/build/dex/quick-perps/vault.d.ts +0 -46
  214. package/build/dex/quick-perps/vault.js +0 -182
  215. package/build/dex/quick-perps/vault.js.map +0 -1
  216. package/build/dex/se-vlr/config.d.ts +0 -3
  217. package/build/dex/se-vlr/config.js +0 -24
  218. package/build/dex/se-vlr/config.js.map +0 -1
  219. package/build/dex/se-vlr/se-vlr-pool.d.ts +0 -39
  220. package/build/dex/se-vlr/se-vlr-pool.js +0 -70
  221. package/build/dex/se-vlr/se-vlr-pool.js.map +0 -1
  222. package/build/dex/se-vlr/se-vlr.d.ts +0 -35
  223. package/build/dex/se-vlr/se-vlr.js +0 -131
  224. package/build/dex/se-vlr/se-vlr.js.map +0 -1
  225. package/build/dex/se-vlr/types.d.ts +0 -6
  226. package/build/dex/se-vlr/types.js +0 -3
  227. package/build/dex/se-vlr/types.js.map +0 -1
  228. package/build/dex/shell.d.ts +0 -25
  229. package/build/dex/shell.js +0 -41
  230. package/build/dex/shell.js.map +0 -1
  231. package/build/dex/solidly/forks-override/aerodrome.d.ts +0 -14
  232. package/build/dex/solidly/forks-override/aerodrome.js +0 -46
  233. package/build/dex/solidly/forks-override/aerodrome.js.map +0 -1
  234. package/build/dex/solidly/forks-override/chronos.d.ts +0 -23
  235. package/build/dex/solidly/forks-override/chronos.js +0 -141
  236. package/build/dex/solidly/forks-override/chronos.js.map +0 -1
  237. package/build/dex/solidly/forks-override/usdfi.d.ts +0 -8
  238. package/build/dex/solidly/forks-override/usdfi.js +0 -15
  239. package/build/dex/solidly/forks-override/usdfi.js.map +0 -1
  240. package/build/dex/solidly/forks-override/velocimeter.d.ts +0 -23
  241. package/build/dex/solidly/forks-override/velocimeter.js +0 -77
  242. package/build/dex/solidly/forks-override/velocimeter.js.map +0 -1
  243. package/build/dex/trader-joe-v2.d.ts +0 -40
  244. package/build/dex/trader-joe-v2.js +0 -74
  245. package/build/dex/trader-joe-v2.js.map +0 -1
  246. package/build/dex/uniswap-v2/dfyn.d.ts +0 -19
  247. package/build/dex/uniswap-v2/dfyn.js +0 -61
  248. package/build/dex/uniswap-v2/dfyn.js.map +0 -1
  249. package/build/dex/uniswap-v2/excalibur.d.ts +0 -24
  250. package/build/dex/uniswap-v2/excalibur.js +0 -47
  251. package/build/dex/uniswap-v2/excalibur.js.map +0 -1
  252. package/build/dex/uniswap-v2/mdex.d.ts +0 -24
  253. package/build/dex/uniswap-v2/mdex.js +0 -50
  254. package/build/dex/uniswap-v2/mdex.js.map +0 -1
  255. package/build/dex/uniswap-v2/nomiswap-v2.d.ts +0 -24
  256. package/build/dex/uniswap-v2/nomiswap-v2.js +0 -57
  257. package/build/dex/uniswap-v2/nomiswap-v2.js.map +0 -1
  258. package/build/dex/uniswap-v3/uniswap-v3-new.d.ts +0 -94
  259. package/build/dex/uniswap-v3/uniswap-v3-new.js +0 -923
  260. package/build/dex/uniswap-v3/uniswap-v3-new.js.map +0 -1
  261. package/build/dex/uniswap-v4/contract-math/Position.d.ts +0 -3
  262. package/build/dex/uniswap-v4/contract-math/Position.js +0 -10
  263. package/build/dex/uniswap-v4/contract-math/Position.js.map +0 -1
  264. package/build/dex/usual-bond/config.d.ts +0 -3
  265. package/build/dex/usual-bond/config.js +0 -13
  266. package/build/dex/usual-bond/config.js.map +0 -1
  267. package/build/dex/usual-bond/types.d.ts +0 -7
  268. package/build/dex/usual-bond/types.js +0 -3
  269. package/build/dex/usual-bond/types.js.map +0 -1
  270. package/build/dex/usual-bond/usual-bond.d.ts +0 -35
  271. package/build/dex/usual-bond/usual-bond.js +0 -176
  272. package/build/dex/usual-bond/usual-bond.js.map +0 -1
  273. package/build/dex/wusdm/config.d.ts +0 -3
  274. package/build/dex/wusdm/config.js +0 -43
  275. package/build/dex/wusdm/config.js.map +0 -1
  276. package/build/dex/wusdm/constants.d.ts +0 -2
  277. package/build/dex/wusdm/constants.js +0 -6
  278. package/build/dex/wusdm/constants.js.map +0 -1
  279. package/build/dex/wusdm/types.d.ts +0 -18
  280. package/build/dex/wusdm/types.js +0 -11
  281. package/build/dex/wusdm/types.js.map +0 -1
  282. package/build/dex/wusdm/wusdm-pool.d.ts +0 -21
  283. package/build/dex/wusdm/wusdm-pool.js +0 -74
  284. package/build/dex/wusdm/wusdm-pool.js.map +0 -1
  285. package/build/dex/wusdm/wusdm.d.ts +0 -46
  286. package/build/dex/wusdm/wusdm.js +0 -243
  287. package/build/dex/wusdm/wusdm.js.map +0 -1
  288. package/build/dex/zerox/config.d.ts +0 -2
  289. package/build/dex/zerox/config.js +0 -33
  290. package/build/dex/zerox/config.js.map +0 -1
  291. package/build/dex/zerox/index.d.ts +0 -22
  292. package/build/dex/zerox/index.js +0 -225
  293. package/build/dex/zerox/index.js.map +0 -1
  294. package/build/dex/zerox/order.d.ts +0 -88
  295. package/build/dex/zerox/order.js +0 -53
  296. package/build/dex/zerox/order.js.map +0 -1
  297. package/build/dex/zerox/types.d.ts +0 -73
  298. package/build/dex/zerox/types.js +0 -21
  299. package/build/dex/zerox/types.js.map +0 -1
@@ -0,0 +1,239 @@
1
+ use ethnum::{I256, U256};
2
+ use std::collections::HashMap;
3
+ use super::liquidity_math;
4
+
5
+ /// Information stored for each initialized individual tick.
6
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
7
+ pub struct TickInfo {
8
+ pub liquidity_gross: U256,
9
+ pub liquidity_net: I256,
10
+ pub initialized: bool,
11
+ }
12
+
13
+ impl Default for TickInfo {
14
+ fn default() -> Self {
15
+ TickInfo {
16
+ liquidity_gross: U256::ZERO,
17
+ liquidity_net: I256::ZERO,
18
+ initialized: false,
19
+ }
20
+ }
21
+ }
22
+
23
+ /// Truncate an I256 to signed 128-bit range, matching `BigInt.asIntN(128, x)`.
24
+ fn as_int128(val: I256) -> I256 {
25
+ // Mask to 128 bits, then sign-extend from bit 127
26
+ let mask: I256 = (I256::ONE << 128) - I256::ONE;
27
+ let masked = val & mask;
28
+ if masked & (I256::ONE << 127) != I256::ZERO {
29
+ masked | !mask
30
+ } else {
31
+ masked
32
+ }
33
+ }
34
+
35
+ /// Updates a tick and returns whether the tick was flipped from initialized to uninitialized,
36
+ /// or vice versa.
37
+ ///
38
+ /// Parameters:
39
+ /// - `ticks`: mutable reference to tick storage
40
+ /// - `tick`: the tick to update
41
+ /// - `tick_current`: the current tick
42
+ /// - `liquidity_delta`: signed liquidity change
43
+ /// - `upper`: true if this is the upper tick of a position being modified
44
+ /// - `max_liquidity`: maximum liquidity per tick
45
+ ///
46
+ /// Returns `true` if the tick was flipped (transitioned between zero and non-zero gross liquidity).
47
+ pub fn update(
48
+ ticks: &mut HashMap<i32, TickInfo>,
49
+ tick: i32,
50
+ _tick_current: I256,
51
+ liquidity_delta: I256,
52
+ upper: bool,
53
+ max_liquidity: U256,
54
+ ) -> bool {
55
+ let info = ticks.entry(tick).or_insert_with(TickInfo::default);
56
+
57
+ let liquidity_gross_before = info.liquidity_gross;
58
+ let liquidity_gross_after = liquidity_math::add_delta(liquidity_gross_before, liquidity_delta);
59
+
60
+ assert!(
61
+ liquidity_gross_after <= max_liquidity,
62
+ "LO"
63
+ );
64
+
65
+ let flipped = (liquidity_gross_after == U256::ZERO) != (liquidity_gross_before == U256::ZERO);
66
+
67
+ if liquidity_gross_before == U256::ZERO {
68
+ info.initialized = true;
69
+ }
70
+
71
+ info.liquidity_gross = liquidity_gross_after;
72
+
73
+ // info.liquidityNet = upper
74
+ // ? BigInt.asIntN(128, BigInt.asIntN(256, info.liquidityNet) - liquidityDelta)
75
+ // : BigInt.asIntN(128, BigInt.asIntN(256, info.liquidityNet) + liquidityDelta)
76
+ let net_i256 = info.liquidity_net; // already I256 (256-bit signed)
77
+ info.liquidity_net = if upper {
78
+ as_int128(net_i256 - liquidity_delta)
79
+ } else {
80
+ as_int128(net_i256 + liquidity_delta)
81
+ };
82
+
83
+ flipped
84
+ }
85
+
86
+ /// Clears tick data. Equivalent to `delete state.ticks[tick]`.
87
+ pub fn clear(ticks: &mut HashMap<i32, TickInfo>, tick: i32) {
88
+ ticks.remove(&tick);
89
+ }
90
+
91
+ /// Transitions to the next tick as needed by crossing an initialized tick.
92
+ /// Returns the `liquidity_net` of the crossed tick.
93
+ pub fn cross(ticks: &HashMap<i32, TickInfo>, tick: i32) -> I256 {
94
+ let info = ticks.get(&tick).expect("tick not found in cross");
95
+ info.liquidity_net
96
+ }
97
+
98
+ #[cfg(test)]
99
+ mod tests {
100
+ use super::*;
101
+
102
+ #[test]
103
+ fn test_update_new_tick() {
104
+ let mut ticks = HashMap::new();
105
+ let flipped = update(
106
+ &mut ticks,
107
+ 100,
108
+ I256::from(50i64),
109
+ I256::from(1000i64),
110
+ false,
111
+ U256::from(1_000_000u64),
112
+ );
113
+ assert!(flipped);
114
+ let info = ticks.get(&100).unwrap();
115
+ assert_eq!(info.liquidity_gross, U256::from(1000u64));
116
+ assert_eq!(info.liquidity_net, I256::from(1000i64));
117
+ assert!(info.initialized);
118
+ }
119
+
120
+ #[test]
121
+ fn test_update_existing_tick() {
122
+ let mut ticks = HashMap::new();
123
+ update(
124
+ &mut ticks,
125
+ 100,
126
+ I256::from(50i64),
127
+ I256::from(1000i64),
128
+ false,
129
+ U256::from(1_000_000u64),
130
+ );
131
+ let flipped = update(
132
+ &mut ticks,
133
+ 100,
134
+ I256::from(50i64),
135
+ I256::from(500i64),
136
+ false,
137
+ U256::from(1_000_000u64),
138
+ );
139
+ assert!(!flipped); // Not flipped because it was already initialized
140
+ let info = ticks.get(&100).unwrap();
141
+ assert_eq!(info.liquidity_gross, U256::from(1500u64));
142
+ assert_eq!(info.liquidity_net, I256::from(1500i64));
143
+ }
144
+
145
+ #[test]
146
+ fn test_update_upper_tick() {
147
+ let mut ticks = HashMap::new();
148
+ let flipped = update(
149
+ &mut ticks,
150
+ 200,
151
+ I256::from(50i64),
152
+ I256::from(1000i64),
153
+ true,
154
+ U256::from(1_000_000u64),
155
+ );
156
+ assert!(flipped);
157
+ let info = ticks.get(&200).unwrap();
158
+ assert_eq!(info.liquidity_gross, U256::from(1000u64));
159
+ // Upper tick: liquidityNet = -liquidityDelta
160
+ assert_eq!(info.liquidity_net, I256::from(-1000i64));
161
+ }
162
+
163
+ #[test]
164
+ fn test_update_removes_liquidity_flips() {
165
+ let mut ticks = HashMap::new();
166
+ update(
167
+ &mut ticks,
168
+ 100,
169
+ I256::from(50i64),
170
+ I256::from(1000i64),
171
+ false,
172
+ U256::from(1_000_000u64),
173
+ );
174
+ let flipped = update(
175
+ &mut ticks,
176
+ 100,
177
+ I256::from(50i64),
178
+ I256::from(-1000i64),
179
+ false,
180
+ U256::from(1_000_000u64),
181
+ );
182
+ assert!(flipped);
183
+ let info = ticks.get(&100).unwrap();
184
+ assert_eq!(info.liquidity_gross, U256::ZERO);
185
+ assert_eq!(info.liquidity_net, I256::ZERO);
186
+ }
187
+
188
+ #[test]
189
+ #[should_panic(expected = "LO")]
190
+ fn test_update_exceeds_max_liquidity() {
191
+ let mut ticks = HashMap::new();
192
+ update(
193
+ &mut ticks,
194
+ 100,
195
+ I256::from(50i64),
196
+ I256::from(2000i64),
197
+ false,
198
+ U256::from(1000u64), // max is 1000
199
+ );
200
+ }
201
+
202
+ #[test]
203
+ fn test_clear() {
204
+ let mut ticks = HashMap::new();
205
+ update(
206
+ &mut ticks,
207
+ 100,
208
+ I256::from(50i64),
209
+ I256::from(1000i64),
210
+ false,
211
+ U256::from(1_000_000u64),
212
+ );
213
+ assert!(ticks.contains_key(&100));
214
+ clear(&mut ticks, 100);
215
+ assert!(!ticks.contains_key(&100));
216
+ }
217
+
218
+ #[test]
219
+ fn test_cross() {
220
+ let mut ticks = HashMap::new();
221
+ update(
222
+ &mut ticks,
223
+ 100,
224
+ I256::from(50i64),
225
+ I256::from(1000i64),
226
+ false,
227
+ U256::from(1_000_000u64),
228
+ );
229
+ let net = cross(&ticks, 100);
230
+ assert_eq!(net, I256::from(1000i64));
231
+ }
232
+
233
+ #[test]
234
+ #[should_panic]
235
+ fn test_cross_nonexistent_tick() {
236
+ let ticks = HashMap::new();
237
+ cross(&ticks, 100);
238
+ }
239
+ }
@@ -0,0 +1,292 @@
1
+ use ethnum::{I256, U256};
2
+ use std::collections::HashMap;
3
+ use super::bit_math;
4
+
5
+ /// Computes the word position and bit position within that word for a given tick.
6
+ ///
7
+ /// Equivalent to: `[BigInt.asIntN(16, tick >> 8), BigInt.asUintN(8, tick % 256)]`
8
+ ///
9
+ /// Returns `(word_pos, bit_pos)` where `word_pos` is an i16 and `bit_pos` is a u8.
10
+ pub fn position(tick: I256) -> (i16, u8) {
11
+ // word_pos = asIntN(16, tick >> 8)
12
+ let shifted = tick >> 8u32;
13
+ // Take the low 16 bits and sign-extend from bit 15
14
+ let word_pos = shifted.0[0] as i16;
15
+
16
+ // bit_pos = asUintN(8, tick % 256)
17
+ // BigInt.asUintN(8, x) takes the low 8 bits of the two's complement representation.
18
+ let bit_pos = tick.0[0] as u8;
19
+
20
+ (word_pos, bit_pos)
21
+ }
22
+
23
+ /// Flips the tick's initialized state in the bitmap.
24
+ ///
25
+ /// `tick` must be divisible by `tick_spacing`.
26
+ pub fn flip_tick(bitmap: &mut HashMap<i16, U256>, tick: I256, tick_spacing: I256) {
27
+ assert!(
28
+ tick % tick_spacing == I256::ZERO,
29
+ "tick % tick_spacing == 0"
30
+ );
31
+ let (word_pos, bit_pos) = position(tick / tick_spacing);
32
+ let mask = U256::ONE << bit_pos;
33
+
34
+ let entry = bitmap.entry(word_pos).or_insert(U256::ZERO);
35
+ *entry ^= mask;
36
+ }
37
+
38
+ /// Returns the next initialized tick within one word of the current tick.
39
+ ///
40
+ /// `lte` indicates whether we're searching to the left (less-than-or-equal) or right.
41
+ /// `is_price_query` controls whether we create default entries for missing bitmap words.
42
+ ///
43
+ /// Returns `(next_tick, initialized)`.
44
+ pub fn next_initialized_tick_within_one_word(
45
+ bitmap: &HashMap<i16, U256>,
46
+ tick: I256,
47
+ tick_spacing: I256,
48
+ lte: bool,
49
+ _is_price_query: bool,
50
+ ) -> (I256, bool) {
51
+ let mut compressed = tick / tick_spacing;
52
+ if tick < I256::ZERO && tick % tick_spacing != I256::ZERO {
53
+ compressed = compressed - I256::ONE;
54
+ }
55
+
56
+ if lte {
57
+ let (word_pos, bit_pos) = position(compressed);
58
+ // mask = (1 << bitPos) - 1 + (1 << bitPos) = (2 << bitPos) - 1
59
+ // This creates a mask of all bits from 0 to bit_pos inclusive
60
+ let mask = (U256::ONE << bit_pos) - U256::ONE + (U256::ONE << bit_pos);
61
+
62
+ // Read bitmap value, defaulting to 0 for missing entries
63
+ let tick_bitmap_value = bitmap.get(&word_pos).copied().unwrap_or(U256::ZERO);
64
+
65
+ let masked = tick_bitmap_value & mask;
66
+
67
+ let initialized = masked != U256::ZERO;
68
+ let next = if initialized {
69
+ let msb = bit_math::most_significant_bit(masked);
70
+ // compressed - asIntN(24, bitPos - msb)
71
+ let diff = I256::from(bit_pos as i32) - I256::from(msb as i32);
72
+ let diff_i24 = sign_extend_i24(diff);
73
+ (compressed - diff_i24) * tick_spacing
74
+ } else {
75
+ // compressed - asIntN(24, bitPos)
76
+ let bp = I256::from(bit_pos as i32);
77
+ let bp_i24 = sign_extend_i24(bp);
78
+ (compressed - bp_i24) * tick_spacing
79
+ };
80
+
81
+ (next, initialized)
82
+ } else {
83
+ // Start from the word of the next tick
84
+ let (word_pos, bit_pos) = position(compressed + I256::ONE);
85
+ // mask = ~((1 << bitPos) - 1)
86
+ // In 256-bit context: invert all bits of ((1 << bitPos) - 1)
87
+ let mask = !((U256::ONE << bit_pos) - U256::ONE);
88
+
89
+ let tick_bitmap_value = bitmap.get(&word_pos).copied().unwrap_or(U256::ZERO);
90
+
91
+ let masked = tick_bitmap_value & mask;
92
+
93
+ let initialized = masked != U256::ZERO;
94
+ let next = if initialized {
95
+ let lsb = bit_math::least_significant_bit(masked);
96
+ // compressed + 1 + asIntN(24, lsb - bitPos)
97
+ let diff = I256::from(lsb as i32) - I256::from(bit_pos as i32);
98
+ let diff_i24 = sign_extend_i24(diff);
99
+ (compressed + I256::ONE + diff_i24) * tick_spacing
100
+ } else {
101
+ // compressed + 1 + asIntN(24, 255 - bitPos)
102
+ let diff = I256::from(255i32) - I256::from(bit_pos as i32);
103
+ let diff_i24 = sign_extend_i24(diff);
104
+ (compressed + I256::ONE + diff_i24) * tick_spacing
105
+ };
106
+
107
+ (next, initialized)
108
+ }
109
+ }
110
+
111
+ /// Sign-extend a value to 24-bit signed (equivalent to BigInt.asIntN(24, x)).
112
+ fn sign_extend_i24(val: I256) -> I256 {
113
+ let mask = I256::new(0x00FFFFFF);
114
+ let masked = val & mask;
115
+ if masked & I256::new(0x00800000) != I256::ZERO {
116
+ masked | !mask
117
+ } else {
118
+ masked
119
+ }
120
+ }
121
+
122
+ #[cfg(test)]
123
+ mod tests {
124
+ use super::*;
125
+
126
+ #[test]
127
+ fn test_position_zero() {
128
+ let (word, bit) = position(I256::ZERO);
129
+ assert_eq!(word, 0);
130
+ assert_eq!(bit, 0);
131
+ }
132
+
133
+ #[test]
134
+ fn test_position_positive() {
135
+ // tick = 256 => word_pos = 256 >> 8 = 1, bit_pos = 256 % 256 = 0
136
+ let (word, bit) = position(I256::from(256i64));
137
+ assert_eq!(word, 1);
138
+ assert_eq!(bit, 0);
139
+
140
+ // tick = 257 => word_pos = 257 >> 8 = 1, bit_pos = 257 % 256 = 1
141
+ let (word, bit) = position(I256::from(257i64));
142
+ assert_eq!(word, 1);
143
+ assert_eq!(bit, 1);
144
+ }
145
+
146
+ #[test]
147
+ fn test_position_negative() {
148
+ // tick = -1 => in two's complement, tick >> 8 = -1 => word_pos = -1
149
+ // bit_pos = low 8 bits of -1 = 0xFF = 255
150
+ let (word, bit) = position(I256::from(-1i64));
151
+ assert_eq!(word, -1);
152
+ assert_eq!(bit, 255);
153
+
154
+ // tick = -256 => tick >> 8 = -1, bit_pos = low 8 bits of -256 = 0
155
+ let (word, bit) = position(I256::from(-256i64));
156
+ assert_eq!(word, -1);
157
+ assert_eq!(bit, 0);
158
+ }
159
+
160
+ #[test]
161
+ fn test_flip_tick() {
162
+ let mut bitmap = HashMap::new();
163
+ let tick_spacing = I256::ONE;
164
+
165
+ // Flip tick 0
166
+ flip_tick(&mut bitmap, I256::ZERO, tick_spacing);
167
+ let (word, bit) = position(I256::ZERO);
168
+ assert_eq!(*bitmap.get(&word).unwrap() & (U256::ONE << bit), U256::ONE);
169
+
170
+ // Flip tick 0 again (should toggle back to 0)
171
+ flip_tick(&mut bitmap, I256::ZERO, tick_spacing);
172
+ assert_eq!(
173
+ *bitmap.get(&word).unwrap() & (U256::ONE << bit),
174
+ U256::ZERO
175
+ );
176
+ }
177
+
178
+ #[test]
179
+ fn test_flip_tick_with_spacing() {
180
+ let mut bitmap = HashMap::new();
181
+ let tick_spacing = I256::from(60i64);
182
+
183
+ flip_tick(&mut bitmap, I256::from(120i64), tick_spacing);
184
+ // 120 / 60 = 2, position(2) = (0, 2)
185
+ let val = *bitmap.get(&0i16).unwrap_or(&U256::ZERO);
186
+ assert_eq!(val & (U256::ONE << 2), U256::from(4u64));
187
+ }
188
+
189
+ #[test]
190
+ #[should_panic]
191
+ fn test_flip_tick_not_aligned() {
192
+ let mut bitmap = HashMap::new();
193
+ flip_tick(&mut bitmap, I256::from(1i64), I256::from(60i64));
194
+ }
195
+
196
+ #[test]
197
+ fn test_next_initialized_tick_lte() {
198
+ let mut bitmap = HashMap::new();
199
+ let tick_spacing = I256::ONE;
200
+
201
+ // Set tick 10 as initialized
202
+ flip_tick(&mut bitmap, I256::from(10i64), tick_spacing);
203
+
204
+ // Search from tick 15, going left (lte=true)
205
+ let (next, initialized) = next_initialized_tick_within_one_word(
206
+ &bitmap,
207
+ I256::from(15i64),
208
+ tick_spacing,
209
+ true,
210
+ false,
211
+ );
212
+ assert!(initialized);
213
+ assert_eq!(next, I256::from(10i64));
214
+ }
215
+
216
+ #[test]
217
+ fn test_next_initialized_tick_gt() {
218
+ let mut bitmap = HashMap::new();
219
+ let tick_spacing = I256::ONE;
220
+
221
+ // Set tick 20 as initialized
222
+ flip_tick(&mut bitmap, I256::from(20i64), tick_spacing);
223
+
224
+ // Search from tick 10, going right (lte=false)
225
+ let (next, initialized) = next_initialized_tick_within_one_word(
226
+ &bitmap,
227
+ I256::from(10i64),
228
+ tick_spacing,
229
+ false,
230
+ false,
231
+ );
232
+ assert!(initialized);
233
+ assert_eq!(next, I256::from(20i64));
234
+ }
235
+
236
+ #[test]
237
+ fn test_next_initialized_tick_not_found_lte() {
238
+ let bitmap = HashMap::new();
239
+ let tick_spacing = I256::ONE;
240
+
241
+ // No ticks initialized; searching left from tick 100
242
+ let (next, initialized) = next_initialized_tick_within_one_word(
243
+ &bitmap,
244
+ I256::from(100i64),
245
+ tick_spacing,
246
+ true,
247
+ false,
248
+ );
249
+ assert!(!initialized);
250
+ // Should return the leftmost tick in this word
251
+ // compressed = 100, position(100) = (0, 100), next = (100 - 100) * 1 = 0
252
+ assert_eq!(next, I256::ZERO);
253
+ }
254
+
255
+ #[test]
256
+ fn test_next_initialized_tick_not_found_gt() {
257
+ let bitmap = HashMap::new();
258
+ let tick_spacing = I256::ONE;
259
+
260
+ // No ticks initialized; searching right from tick 0
261
+ let (next, initialized) = next_initialized_tick_within_one_word(
262
+ &bitmap,
263
+ I256::ZERO,
264
+ tick_spacing,
265
+ false,
266
+ false,
267
+ );
268
+ assert!(!initialized);
269
+ // compressed = 0, position(1) = (0, 1), next = (0 + 1 + (255 - 1)) * 1 = 255
270
+ assert_eq!(next, I256::from(255i64));
271
+ }
272
+
273
+ #[test]
274
+ fn test_next_initialized_tick_negative_range() {
275
+ let mut bitmap = HashMap::new();
276
+ let tick_spacing = I256::ONE;
277
+
278
+ // Set tick -10 as initialized
279
+ flip_tick(&mut bitmap, I256::from(-10i64), tick_spacing);
280
+
281
+ // Search from tick -5, going left
282
+ let (next, initialized) = next_initialized_tick_within_one_word(
283
+ &bitmap,
284
+ I256::from(-5i64),
285
+ tick_spacing,
286
+ true,
287
+ false,
288
+ );
289
+ assert!(initialized);
290
+ assert_eq!(next, I256::from(-10i64));
291
+ }
292
+ }