@paraswap/dex-lib 2.28.5 → 2.28.7-balancer-v2-multihop.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 (85) hide show
  1. package/build/dex/algebra/algebra-pool-v1_1.js +3 -2
  2. package/build/dex/algebra/algebra-pool-v1_1.js.map +1 -1
  3. package/build/dex/algebra/algebra-pool-v1_9.js +3 -2
  4. package/build/dex/algebra/algebra-pool-v1_9.js.map +1 -1
  5. package/build/dex/algebra/algebra.js.map +1 -1
  6. package/build/dex/algebra/config.js +2 -2
  7. package/build/dex/algebra/lib/AlgebraMath.d.ts +1 -1
  8. package/build/dex/algebra/lib/AlgebraMath.js +12 -12
  9. package/build/dex/algebra/lib/AlgebraMath.js.map +1 -1
  10. package/build/dex/algebra/lib/TickManager.d.ts +4 -0
  11. package/build/dex/algebra/lib/TickManager.js +60 -0
  12. package/build/dex/algebra/lib/TickManager.js.map +1 -0
  13. package/build/dex/algebra/lib/TickTable.d.ts +10 -0
  14. package/build/dex/algebra/lib/TickTable.js +146 -0
  15. package/build/dex/algebra/lib/TickTable.js.map +1 -0
  16. package/build/dex/algebra/lib/yul-helper.d.ts +9 -0
  17. package/build/dex/algebra/lib/yul-helper.js +28 -0
  18. package/build/dex/algebra/lib/yul-helper.js.map +1 -0
  19. package/build/dex/algebra/types.d.ts +3 -0
  20. package/build/dex/balancer-v2/optimizer.js +32 -34
  21. package/build/dex/balancer-v2/optimizer.js.map +1 -1
  22. package/build/dex/test-dex/config.d.ts +4 -0
  23. package/build/dex/test-dex/config.js +15 -0
  24. package/build/dex/test-dex/config.js.map +1 -0
  25. package/build/dex/test-dex/test-dex-pool.d.ts +39 -0
  26. package/build/dex/test-dex/test-dex-pool.js +63 -0
  27. package/build/dex/test-dex/test-dex-pool.js.map +1 -0
  28. package/build/dex/test-dex/test-dex.d.ts +37 -0
  29. package/build/dex/test-dex/test-dex.js +126 -0
  30. package/build/dex/test-dex/test-dex.js.map +1 -0
  31. package/build/dex/test-dex/types.d.ts +6 -0
  32. package/build/dex/{pancakeswap-v3 → test-dex}/types.js.map +1 -1
  33. package/build/dex/uniswap-v3/contract-math/TickBitMap.d.ts +0 -1
  34. package/build/dex/uniswap-v3/contract-math/TickBitMap.js +0 -3
  35. package/build/dex/uniswap-v3/contract-math/TickBitMap.js.map +1 -1
  36. package/build/dex/uniswap-v3/contract-math/utils.js +10 -8
  37. package/build/dex/uniswap-v3/contract-math/utils.js.map +1 -1
  38. package/build/dex/uniswap-v3/uniswap-v3.js +1 -1
  39. package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
  40. package/build/dex/woo-fi-v2/woo-fi-math.d.ts +16 -0
  41. package/build/dex/woo-fi-v2/woo-fi-math.js +137 -0
  42. package/build/dex/woo-fi-v2/woo-fi-math.js.map +1 -0
  43. package/package.json +1 -1
  44. package/src/dex/algebra/algebra-events.test.ts +73 -7
  45. package/src/dex/algebra/algebra-integration.test.ts +3 -2
  46. package/src/dex/algebra/algebra-pool-v1_1.ts +3 -2
  47. package/src/dex/algebra/algebra-pool-v1_9.ts +3 -4
  48. package/src/dex/algebra/algebra.ts +1 -2
  49. package/src/dex/algebra/config.ts +2 -2
  50. package/src/dex/algebra/lib/AlgebraMath.ts +23 -15
  51. package/src/dex/algebra/lib/TickManager.ts +91 -0
  52. package/src/dex/algebra/lib/TickTable.ts +216 -0
  53. package/src/dex/algebra/lib/yul-helper.ts +29 -0
  54. package/src/dex/algebra/types.ts +4 -0
  55. package/src/dex/balancer-v2/optimizer.ts +37 -39
  56. package/src/dex/uniswap-v2/uniswap-v2-e2e-arbitrum.test.ts +10 -2
  57. package/src/dex/uniswap-v3/contract-math/TickBitMap.ts +0 -9
  58. package/src/dex/uniswap-v3/contract-math/utils.ts +12 -10
  59. package/src/dex/uniswap-v3/uniswap-v3.ts +1 -1
  60. package/tests/constants-e2e.ts +9 -1
  61. package/.idea/aws.xml +0 -17
  62. package/.idea/codeStyles/Project.xml +0 -19
  63. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  64. package/.idea/misc.xml +0 -6
  65. package/.idea/modules.xml +0 -8
  66. package/.idea/paraswap-dex-lib.iml +0 -9
  67. package/.idea/vcs.xml +0 -6
  68. package/build/abi/algebra/AlgebraPool.abi.json +0 -727
  69. package/build/abi/curve-v1/StableSwapFRXETH.json +0 -889
  70. package/build/abi/curve-v1/StableSwapWBETH.json +0 -1223
  71. package/build/abi/wBETH.json +0 -1527
  72. package/build/dex/algebra/algebra-pool.d.ts +0 -46
  73. package/build/dex/algebra/algebra-pool.js +0 -336
  74. package/build/dex/algebra/algebra-pool.js.map +0 -1
  75. package/build/dex/curve-v1/pools/frxETHpool.d.ts +0 -7
  76. package/build/dex/curve-v1/pools/frxETHpool.js +0 -27
  77. package/build/dex/curve-v1/pools/frxETHpool.js.map +0 -1
  78. package/build/dex/curve-v1/pools/wbETHpool.d.ts +0 -29
  79. package/build/dex/curve-v1/pools/wbETHpool.js +0 -408
  80. package/build/dex/curve-v1/pools/wbETHpool.js.map +0 -1
  81. package/build/dex/pancakeswap-v3/types.d.ts +0 -14
  82. package/build/dex/solidly/forks-override/ramses.d.ts +0 -8
  83. package/build/dex/solidly/forks-override/ramses.js +0 -15
  84. package/build/dex/solidly/forks-override/ramses.js.map +0 -1
  85. /package/build/dex/{pancakeswap-v3 → test-dex}/types.js +0 -0
@@ -3,7 +3,6 @@ import { PoolStateV1_1, PoolState_v1_9 } from '../types';
3
3
  import { NumberAsString, SwapSide } from '@paraswap/core';
4
4
  import { OutputResult, TickInfo } from '../../uniswap-v3/types';
5
5
  import { Tick } from '../../uniswap-v3/contract-math/Tick';
6
- import { TickBitMap } from '../../uniswap-v3/contract-math/TickBitMap';
7
6
  import { SqrtPriceMath } from '../../uniswap-v3/contract-math/SqrtPriceMath';
8
7
  import { TickMath } from '../../uniswap-v3/contract-math/TickMath';
9
8
  import { LiquidityMath } from '../../uniswap-v3/contract-math/LiquidityMath';
@@ -21,6 +20,8 @@ import {
21
20
  MAX_PRICING_COMPUTATION_STEPS_ALLOWED,
22
21
  OUT_OF_RANGE_ERROR_POSTFIX,
23
22
  } from '../../uniswap-v3/constants';
23
+ import { TickManager } from './TickManager';
24
+ import { TickTable } from './TickTable';
24
25
 
25
26
  type UpdatePositionCache = {
26
27
  price: bigint;
@@ -112,12 +113,12 @@ function _priceComputationCycles(
112
113
 
113
114
  try {
114
115
  [step.tickNext, step.initialized] =
115
- TickBitMap.nextInitializedTickWithinOneWord(
116
+ TickTable.nextInitializedTickWithinOneWord(
116
117
  poolState,
117
118
  state.tick,
118
- poolState.tickSpacing,
119
119
  zeroForOne,
120
120
  true,
121
+ poolState.areTicksCompressed ? poolState.tickSpacing : undefined,
121
122
  );
122
123
  } catch (e) {
123
124
  if (
@@ -378,9 +379,9 @@ class AlgebraMathClass {
378
379
  currentTick: bigint,
379
380
  currentPrice: bigint,
380
381
  ) {
381
- let amount0;
382
- let amount1;
383
- let globalLiquidityDelta;
382
+ let amount0 = 0n;
383
+ let amount1 = 0n;
384
+ let globalLiquidityDelta = 0n;
384
385
  // If current tick is less than the provided bottom one then only the token0 has to be provided
385
386
  if (currentTick < bottomTick) {
386
387
  amount0 = SqrtPriceMath._getAmount0DeltaO(
@@ -434,7 +435,7 @@ class AlgebraMathClass {
434
435
  const time = this._blockTimestamp(state);
435
436
 
436
437
  if (
437
- Tick.update(
438
+ TickManager.update(
438
439
  state,
439
440
  bottomTick,
440
441
  cache.tick,
@@ -447,10 +448,14 @@ class AlgebraMathClass {
447
448
  )
448
449
  ) {
449
450
  toggledBottom = true;
450
- TickBitMap.flipTick(state, bottomTick, state.tickSpacing);
451
+ TickTable.toggleTick(
452
+ state,
453
+ bottomTick,
454
+ state.areTicksCompressed ? state.tickSpacing : undefined,
455
+ );
451
456
  }
452
457
  if (
453
- Tick.update(
458
+ TickManager.update(
454
459
  state,
455
460
  topTick,
456
461
  cache.tick,
@@ -463,13 +468,17 @@ class AlgebraMathClass {
463
468
  )
464
469
  ) {
465
470
  toggledTop = true;
466
- TickBitMap.flipTick(state, topTick, state.tickSpacing);
471
+ TickTable.toggleTick(
472
+ state,
473
+ topTick,
474
+ state.areTicksCompressed ? state.tickSpacing : undefined,
475
+ );
467
476
  }
468
477
  }
469
478
 
470
479
  // skip fee && position related stuffs
471
480
 
472
- // same as UniwapV3Pool.sol line 327 -> if (params.liquidityDelta != 0) {
481
+ // same as UniswapV3Pool.sol line 327 -> if (params.liquidityDelta != 0) {
473
482
  if (liquidityDelta !== 0n) {
474
483
  // if liquidityDelta is negative and the tick was toggled, it means that it should not be initialized anymore, so we delete it
475
484
  if (liquidityDelta < 0) {
@@ -510,7 +519,7 @@ class AlgebraMathClass {
510
519
 
511
520
  let cache: SwapCalculationCache = {
512
521
  amountCalculated: 0n,
513
- amountRequiredInitial: BI_MAX_INT, // similarly to waht we did for uniswap
522
+ amountRequiredInitial: BI_MAX_INT, // similarly to what we did for uniswap
514
523
  communityFee: 0n,
515
524
  exactInput: false,
516
525
  fee: 0n,
@@ -563,19 +572,18 @@ class AlgebraMathClass {
563
572
  stepSqrtPrice: 0n,
564
573
  tickCount: 0,
565
574
  };
566
- let i = 0;
567
575
  // swap until there is remaining input or output tokens or we reach the price limit
568
576
  while (true) {
569
577
  step.stepSqrtPrice = currentPrice;
570
578
 
571
579
  //equivalent of tickTable.nextTickInTheSameRow(currentTick, zeroToOne);
572
580
  [step.nextTick, step.initialized] =
573
- TickBitMap.nextInitializedTickWithinOneWord(
581
+ TickTable.nextInitializedTickWithinOneWord(
574
582
  poolState,
575
583
  currentTick,
576
- poolState.tickSpacing,
577
584
  zeroToOne,
578
585
  false,
586
+ poolState.areTicksCompressed ? poolState.tickSpacing : undefined,
579
587
  );
580
588
 
581
589
  step.nextTickPrice = TickMath.getSqrtRatioAtTick(step.nextTick);
@@ -0,0 +1,91 @@
1
+ import { IAlgebraPoolState } from '../types';
2
+ import { LiquidityMath } from '../../uniswap-v3/contract-math/LiquidityMath';
3
+ import { _require } from '../../../utils';
4
+ import { NumberAsString } from '@paraswap/core';
5
+ import { ZERO_TICK_INFO } from '../../uniswap-v3/constants';
6
+ import { TickInfo } from '../../uniswap-v3/types';
7
+
8
+ export class TickManager {
9
+ static update(
10
+ state: Pick<IAlgebraPoolState, 'ticks'>,
11
+ tick: bigint,
12
+ tickCurrent: bigint,
13
+ liquidityDelta: bigint,
14
+ secondsPerLiquidityCumulativeX128: bigint,
15
+ tickCumulative: bigint,
16
+ time: bigint,
17
+ upper: boolean,
18
+ maxLiquidity: bigint,
19
+ ): boolean {
20
+ let info = state.ticks[Number(tick)];
21
+
22
+ if (info === undefined) {
23
+ info = { ...ZERO_TICK_INFO };
24
+ state.ticks[Number(tick)] = info;
25
+ }
26
+
27
+ // uint128 liquidityTotalBefore = data.liquidityTotal;
28
+ // uint128 liquidityTotalAfter = LiquidityMath.addDelta(liquidityTotalBefore, liquidityDelta);
29
+ // require(liquidityTotalAfter < Constants.MAX_LIQUIDITY_PER_TICK + 1, 'LO');
30
+ const liquidityGrossBefore = info.liquidityGross;
31
+ const liquidityGrossAfter = LiquidityMath.addDelta(
32
+ liquidityGrossBefore,
33
+ liquidityDelta,
34
+ );
35
+ _require(
36
+ liquidityGrossAfter <= maxLiquidity,
37
+ 'LO',
38
+ { liquidityGrossAfter, maxLiquidity },
39
+ 'liquidityGrossAfter <= maxLiquidity',
40
+ );
41
+
42
+ // int128 liquidityDeltaBefore = data.liquidityDelta;
43
+ const liquidityNetBefore = info.liquidityNet;
44
+
45
+ // // when the lower (upper) tick is crossed left to right (right to left), liquidity must be added (removed)
46
+ // data.liquidityDelta = upper
47
+ // ? int256(liquidityDeltaBefore).sub(liquidityDelta).toInt128()
48
+ // : int256(liquidityDeltaBefore).add(liquidityDelta).toInt128();
49
+ //
50
+ // data.liquidityTotal = liquidityTotalAfter;
51
+ info.liquidityNet = upper
52
+ ? BigInt.asIntN(
53
+ 128,
54
+ BigInt.asIntN(256, liquidityNetBefore) - liquidityDelta,
55
+ )
56
+ : BigInt.asIntN(
57
+ 128,
58
+ BigInt.asIntN(256, liquidityNetBefore) + liquidityDelta,
59
+ );
60
+
61
+ // flipped = (liquidityTotalAfter == 0);
62
+ // if (liquidityTotalBefore == 0) {
63
+ // flipped = !flipped;
64
+ // // by convention, we assume that all growth before a tick was initialized happened _below_ the tick
65
+ // if (tick <= currentTick) {
66
+ // data.outerFeeGrowth0Token = totalFeeGrowth0Token;
67
+ // data.outerFeeGrowth1Token = totalFeeGrowth1Token;
68
+ // data.outerSecondsPerLiquidity = secondsPerLiquidityCumulative;
69
+ // data.outerTickCumulative = tickCumulative;
70
+ // data.outerSecondsSpent = time;
71
+ // }
72
+ // data.initialized = true;
73
+ // }
74
+
75
+ let flipped = liquidityGrossAfter === 0n;
76
+ if (liquidityGrossBefore === 0n) {
77
+ flipped = !flipped;
78
+ if (tick <= tickCurrent) {
79
+ info.secondsPerLiquidityOutsideX128 = secondsPerLiquidityCumulativeX128;
80
+ info.tickCumulativeOutside = tickCumulative;
81
+ info.secondsOutside = time;
82
+ }
83
+ info.initialized = true;
84
+ }
85
+
86
+ // data.liquidityTotal = liquidityTotalAfter;
87
+ info.liquidityGross = liquidityGrossAfter;
88
+
89
+ return flipped;
90
+ }
91
+ }
@@ -0,0 +1,216 @@
1
+ import { IAlgebraPoolState } from '../types';
2
+ import { _require } from '../../../utils';
3
+ import { DeepReadonly } from 'ts-essentials';
4
+ import {
5
+ OUT_OF_RANGE_ERROR_POSTFIX,
6
+ TICK_BITMAP_BUFFER,
7
+ TICK_BITMAP_TO_USE,
8
+ } from '../../uniswap-v3/constants';
9
+ import { TickMath } from '../../uniswap-v3/contract-math/TickMath';
10
+ import { Yul } from './yul-helper';
11
+
12
+ function isWordPosOut(
13
+ wordPos: bigint,
14
+ startTickBitmap: bigint,
15
+ // For pricing we use wider range to check price impact. If function called from event
16
+ // it must always be within buffer
17
+ isPriceQuery: boolean,
18
+ ) {
19
+ let lowerTickBitmapLimit;
20
+ let upperTickBitmapLimit;
21
+
22
+ if (isPriceQuery) {
23
+ lowerTickBitmapLimit =
24
+ startTickBitmap - (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE);
25
+ upperTickBitmapLimit =
26
+ startTickBitmap + (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE);
27
+ } else {
28
+ lowerTickBitmapLimit = startTickBitmap - TICK_BITMAP_BUFFER;
29
+ upperTickBitmapLimit = startTickBitmap + TICK_BITMAP_BUFFER;
30
+ }
31
+
32
+ _require(
33
+ wordPos >= lowerTickBitmapLimit && wordPos <= upperTickBitmapLimit,
34
+ `wordPos is out of safe state tickBitmap request range: ${OUT_OF_RANGE_ERROR_POSTFIX}`,
35
+ { wordPos },
36
+ `wordPos >= LOWER_TICK_REQUEST_LIMIT && wordPos <= UPPER_TICK_REQUEST_LIMIT`,
37
+ );
38
+ }
39
+
40
+ export class TickTable {
41
+ static position(tick: bigint) {
42
+ return [
43
+ // wordPos
44
+ BigInt.asIntN(16, tick >> 8n),
45
+ // bitPos
46
+ BigInt.asUintN(8, tick & BigInt(0xff)),
47
+ ];
48
+ }
49
+
50
+ static toggleTick(
51
+ state: Pick<IAlgebraPoolState, 'startTickBitmap' | 'tickBitmap'>,
52
+ tick: bigint,
53
+ tickSpacing?: bigint,
54
+ ) {
55
+ if (tickSpacing !== undefined) {
56
+ tick /= tickSpacing;
57
+ }
58
+ const [rowNumber, bitNumber] = TickTable.position(tick);
59
+ const mask = 1n << bitNumber;
60
+
61
+ // toggleTick is used only in _updatePosition which is always state changing event
62
+ // Therefore it is never used in price query
63
+ isWordPosOut(rowNumber, state.startTickBitmap, false);
64
+
65
+ const stringWordPos = rowNumber.toString();
66
+ if (state.tickBitmap[stringWordPos] === undefined) {
67
+ state.tickBitmap[stringWordPos] = 0n;
68
+ }
69
+
70
+ state.tickBitmap[stringWordPos] ^= mask;
71
+ if (state.tickBitmap[stringWordPos] === 0n) {
72
+ delete state.tickBitmap[stringWordPos];
73
+ }
74
+ }
75
+
76
+ static nextInitializedTickWithinOneWord(
77
+ state: DeepReadonly<
78
+ Pick<IAlgebraPoolState, 'startTickBitmap' | 'tickBitmap'>
79
+ >,
80
+ tick: bigint,
81
+ lte: boolean,
82
+ isPriceQuery: boolean,
83
+ tickSpacing?: bigint,
84
+ ): [bigint, boolean] {
85
+ if (tickSpacing !== undefined) {
86
+ tick = Yul.sub(
87
+ Yul.sdiv(tick, tickSpacing),
88
+ Yul.and(
89
+ Yul.slt(tick, 0n),
90
+ Yul.not(Yul.iszero(Yul.smod(tick, tickSpacing))),
91
+ ),
92
+ );
93
+ }
94
+ const [rowNumber, bitNumber] = TickTable.position(tick);
95
+ isWordPosOut(rowNumber, state.startTickBitmap, isPriceQuery);
96
+ let tickBitmapValue = state.tickBitmap[rowNumber.toString()];
97
+ tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue;
98
+ if (lte) {
99
+ const _row = tickBitmapValue << (255n - bitNumber);
100
+ if (_row != 0n) {
101
+ tick -= BigInt.asIntN(24, 255n - TickTable.getMostSignificantBit(_row));
102
+ return [TickTable.boundTick(tick, tickSpacing), true];
103
+ } else {
104
+ tick -= BigInt.asIntN(24, bitNumber);
105
+ return [TickTable.boundTick(tick, tickSpacing), false];
106
+ }
107
+ } else {
108
+ tick += 1n;
109
+ const _row = tickBitmapValue >> bitNumber;
110
+ if (_row !== 0n) {
111
+ tick += BigInt.asIntN(
112
+ 24,
113
+ TickTable.getSingleSignificantBit(-_row & _row),
114
+ );
115
+ return [TickTable.boundTick(tick, tickSpacing), true];
116
+ } else {
117
+ tick += BigInt.asIntN(24, 255n - bitNumber);
118
+ return [TickTable.boundTick(tick, tickSpacing), false];
119
+ }
120
+ }
121
+ }
122
+
123
+ static getSingleSignificantBit(word: bigint): bigint {
124
+ let singleBitPos = 0n;
125
+ singleBitPos = Yul.iszero(
126
+ word &&
127
+ BigInt(
128
+ '0x5555555555555555555555555555555555555555555555555555555555555555',
129
+ ),
130
+ );
131
+ singleBitPos =
132
+ singleBitPos ||
133
+ Yul.iszero(
134
+ word &&
135
+ BigInt(
136
+ '0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff',
137
+ ),
138
+ ) << 7n;
139
+ singleBitPos =
140
+ singleBitPos ||
141
+ Yul.iszero(
142
+ word &&
143
+ BigInt(
144
+ '0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff',
145
+ ),
146
+ ) << 6n;
147
+ singleBitPos =
148
+ singleBitPos ||
149
+ Yul.iszero(
150
+ word &&
151
+ BigInt(
152
+ '0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff',
153
+ ),
154
+ ) << 5n;
155
+ singleBitPos =
156
+ singleBitPos ||
157
+ Yul.iszero(
158
+ word &&
159
+ BigInt(
160
+ '0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff',
161
+ ),
162
+ ) << 4n;
163
+ singleBitPos =
164
+ singleBitPos ||
165
+ Yul.iszero(
166
+ word &&
167
+ BigInt(
168
+ '0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff',
169
+ ),
170
+ ) << 3n;
171
+ singleBitPos =
172
+ singleBitPos ||
173
+ Yul.iszero(
174
+ word &&
175
+ BigInt(
176
+ '0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f',
177
+ ),
178
+ ) << 2n;
179
+ singleBitPos =
180
+ singleBitPos ||
181
+ Yul.iszero(
182
+ word &&
183
+ BigInt(
184
+ '0x3333333333333333333333333333333333333333333333333333333333333333',
185
+ ),
186
+ ) << 1n;
187
+
188
+ return BigInt.asUintN(8, singleBitPos);
189
+ }
190
+
191
+ static getMostSignificantBit(word: bigint): bigint {
192
+ word = word || word >> 1n;
193
+ word = word || word >> 2n;
194
+ word = word || word >> 4n;
195
+ word = word || word >> 8n;
196
+ word = word || word >> 16n;
197
+ word = word || word >> 32n;
198
+ word = word || word >> 64n;
199
+ word = word || word >> 128n;
200
+ word = word - (word >> 1n);
201
+ return TickTable.getSingleSignificantBit(BigInt.asUintN(256, word));
202
+ }
203
+
204
+ static boundTick(tick: bigint, tickSpacing?: bigint): bigint {
205
+ if (tickSpacing !== undefined) {
206
+ tick *= tickSpacing;
207
+ }
208
+ let boundedTick = tick;
209
+ if (boundedTick < TickMath.MIN_TICK) {
210
+ boundedTick = TickMath.MIN_TICK;
211
+ } else if (boundedTick > TickMath.MAX_TICK) {
212
+ boundedTick = TickMath.MAX_TICK;
213
+ }
214
+ return boundedTick;
215
+ }
216
+ }
@@ -0,0 +1,29 @@
1
+ export class Yul {
2
+ static sub(x: bigint, y: bigint): bigint {
3
+ return x - y;
4
+ }
5
+
6
+ static sdiv(x: bigint, y: bigint): bigint {
7
+ return y === 0n ? 0n : x / y;
8
+ }
9
+
10
+ static and(x: bigint, y: bigint): bigint {
11
+ return x & y;
12
+ }
13
+
14
+ static slt(x: bigint, y: bigint): bigint {
15
+ return x < y ? 1n : 0n;
16
+ }
17
+
18
+ static not(x: bigint): bigint {
19
+ return ~x;
20
+ }
21
+
22
+ static iszero(x: bigint): bigint {
23
+ return x === 0n ? 1n : 0n;
24
+ }
25
+
26
+ static smod(x: bigint, y: bigint): bigint {
27
+ return y === 0n ? 0n : x % y;
28
+ }
29
+ }
@@ -23,6 +23,7 @@ export type PoolStateV1_1 = {
23
23
  startTickBitmap: bigint;
24
24
  balance0: bigint;
25
25
  balance1: bigint;
26
+ areTicksCompressed: boolean;
26
27
  };
27
28
 
28
29
  type GlobalState_v1_9 = {
@@ -47,6 +48,7 @@ export type PoolState_v1_9 = {
47
48
  startTickBitmap: bigint;
48
49
  balance0: bigint;
49
50
  balance1: bigint;
51
+ areTicksCompressed: boolean;
50
52
  };
51
53
 
52
54
  export type AlgebraData = {
@@ -71,6 +73,8 @@ export type DexParams = {
71
73
  version: 'v1.1' | 'v1.9';
72
74
  };
73
75
 
76
+ export type IAlgebraPoolState = PoolStateV1_1 | PoolState_v1_9;
77
+
74
78
  export type TickBitMapMappingsWithBigNumber = {
75
79
  index: number;
76
80
  value: BigNumber;
@@ -3,68 +3,66 @@ import { BalancerSwapV2 } from './types';
3
3
  import { SwapSide } from '../../constants';
4
4
  import { BalancerConfig } from './config';
5
5
 
6
- const MAX_UINT256 =
7
- '115792089237316195423570985008687907853269984665640564039457584007913129639935';
8
-
9
- const AllBalancerV2Forks = Object.keys(BalancerConfig);
10
-
11
6
  export function balancerV2Merge(or: UnoptimizedRate): UnoptimizedRate {
12
7
  const fixSwap = (
13
8
  rawSwap: OptimalSwapExchange<any>[],
9
+ exchange: string,
14
10
  side: SwapSide,
15
11
  ): OptimalSwapExchange<any>[] => {
16
- const newBalancers: { [key: string]: OptimalSwapExchange<any> } = {};
12
+ const exchangeLower = exchange.toLowerCase();
13
+ const newBalancer: OptimalSwapExchange<any> = {
14
+ exchange,
15
+ srcAmount: '0',
16
+ destAmount: '0',
17
+ percent: 0,
18
+ poolAddresses: [],
19
+ data: {
20
+ swaps: new Array<BalancerSwapV2>(),
21
+ gasUSD: '0',
22
+ },
23
+ };
17
24
  let optimizedSwap = new Array<OptimalSwapExchange<any>>();
18
- rawSwap.forEach((s: OptimalSwapExchange<any>) => {
19
- const exchangeKey = s.exchange.toLowerCase();
20
- if (AllBalancerV2Forks.some(d => d.toLowerCase() === exchangeKey)) {
21
- if (!(exchangeKey in newBalancers)) {
22
- newBalancers[exchangeKey] = {
23
- exchange: s.exchange,
24
- srcAmount: '0',
25
- destAmount: '0',
26
- percent: 0,
27
- poolAddresses: [],
28
- data: {
29
- swaps: new Array<BalancerSwapV2>(),
30
- gasUSD: '0',
31
- },
32
- };
33
- }
34
- newBalancers[exchangeKey].srcAmount = (
35
- BigInt(newBalancers[exchangeKey].srcAmount) + BigInt(s.srcAmount)
25
+ rawSwap.forEach((_s: OptimalSwapExchange<any>) => {
26
+ if (_s.exchange.toLowerCase() === exchangeLower) {
27
+ const s = _s;
28
+ newBalancer.srcAmount = (
29
+ BigInt(newBalancer.srcAmount) + BigInt(s.srcAmount)
36
30
  ).toString();
37
31
 
38
- newBalancers[exchangeKey].destAmount = (
39
- BigInt(newBalancers[exchangeKey].destAmount) + BigInt(s.destAmount)
32
+ newBalancer.destAmount = (
33
+ BigInt(newBalancer.destAmount) + BigInt(s.destAmount)
40
34
  ).toString();
41
35
 
42
- newBalancers[exchangeKey].percent += s.percent;
43
- newBalancers[exchangeKey].data.exchangeProxy = s.data.exchangeProxy;
44
- newBalancers[exchangeKey].data.gasUSD = (
45
- parseFloat(newBalancers[exchangeKey].data.gasUSD) +
46
- parseFloat(s.data.gasUSD)
36
+ newBalancer.percent += s.percent;
37
+ newBalancer.data.exchangeProxy = s.data.exchangeProxy;
38
+ newBalancer.data.gasUSD = (
39
+ parseFloat(newBalancer.data.gasUSD) + parseFloat(s.data.gasUSD)
47
40
  ).toFixed(6);
48
41
 
49
- newBalancers[exchangeKey].data.swaps.push({
42
+ newBalancer.data.swaps.push({
50
43
  poolId: s.data.poolId,
51
44
  amount: side === SwapSide.SELL ? s.srcAmount : s.destAmount,
52
45
  });
53
- newBalancers[exchangeKey].poolAddresses!.push(s.poolAddresses![0]);
46
+ newBalancer.poolAddresses!.push(s.poolAddresses![0]);
54
47
  } else {
55
- optimizedSwap.push(s);
48
+ optimizedSwap.push(_s);
56
49
  }
57
50
  });
58
- optimizedSwap = optimizedSwap.concat(Object.values(newBalancers));
51
+ if (newBalancer.data!.swaps.length) optimizedSwap.push(newBalancer);
59
52
  return optimizedSwap;
60
53
  };
61
54
 
62
55
  or.bestRoute = or.bestRoute.map(r => ({
63
56
  ...r,
64
- swaps: r.swaps.map(s => ({
65
- ...s,
66
- swapExchanges: fixSwap(s.swapExchanges, or.side),
67
- })),
57
+ swaps: r.swaps.map(s => {
58
+ return {
59
+ ...s,
60
+ swapExchanges: Object.keys(BalancerConfig).reduce(
61
+ (acc, exchange) => fixSwap(acc, exchange, or.side),
62
+ s.swapExchanges,
63
+ ),
64
+ };
65
+ }),
68
66
  }));
69
67
  return or;
70
68
  }
@@ -381,8 +381,16 @@ describe('UniswapV2 E2E Arbitrum', () => {
381
381
  { name: 'USDC', sellAmount: '940617', buyAmount: '505000000000000' },
382
382
  ],
383
383
  [
384
- { name: 'ETH', sellAmount: '631955000000000', buyAmount: '1000000000000000000' },
385
- { name: 'ARB', sellAmount: '1000000000000000000', buyAmount: '631955000000000' },
384
+ {
385
+ name: 'ETH',
386
+ sellAmount: '631955000000000',
387
+ buyAmount: '1000000000000000000',
388
+ },
389
+ {
390
+ name: 'ARB',
391
+ sellAmount: '1000000000000000000',
392
+ buyAmount: '631955000000000',
393
+ },
386
394
  ],
387
395
  ];
388
396
 
@@ -120,13 +120,4 @@ export class TickBitMap {
120
120
 
121
121
  return [next, initialized];
122
122
  }
123
-
124
- static _putZeroIfUndefined(
125
- state: PoolState,
126
- tickBitmapValue: bigint | undefined,
127
- wordPos: bigint,
128
- isPriceQuery: boolean = false,
129
- ): bigint {
130
- return tickBitmapValue === undefined ? 0n : tickBitmapValue;
131
- }
132
123
  }
@@ -38,16 +38,18 @@ export function _reduceTicks(
38
38
  ) {
39
39
  return ticksToReduce.reduce<Record<string, TickInfo>>((acc, curr) => {
40
40
  const { index, value } = curr;
41
- acc[index] = {
42
- liquidityGross: bigIntify(value.liquidityGross),
43
- liquidityNet: bigIntify(value.liquidityNet),
44
- tickCumulativeOutside: bigIntify(value.tickCumulativeOutside),
45
- secondsPerLiquidityOutsideX128: bigIntify(
46
- value.secondsPerLiquidityOutsideX128,
47
- ),
48
- secondsOutside: bigIntify(value.secondsOutside),
49
- initialized: value.initialized,
50
- };
41
+ if (value.initialized) {
42
+ acc[index] = {
43
+ liquidityGross: bigIntify(value.liquidityGross),
44
+ liquidityNet: bigIntify(value.liquidityNet),
45
+ tickCumulativeOutside: bigIntify(value.tickCumulativeOutside),
46
+ secondsPerLiquidityOutsideX128: bigIntify(
47
+ value.secondsPerLiquidityOutsideX128,
48
+ ),
49
+ secondsOutside: bigIntify(value.secondsOutside),
50
+ initialized: value.initialized,
51
+ };
52
+ }
51
53
  return acc;
52
54
  }, ticks);
53
55
  }
@@ -276,7 +276,7 @@ export class UniswapV3
276
276
  e,
277
277
  );
278
278
  } else {
279
- // on unkown error mark as failed and increase retryCount for retry init strategy
279
+ // on unknown error mark as failed and increase retryCount for retry init strategy
280
280
  // note: state would be null by default which allows to fallback
281
281
  this.logger.warn(
282
282
  `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`,
@@ -705,7 +705,7 @@ export const Tokens: {
705
705
  HATCHY: {
706
706
  address: '0x502580fc390606b47fc3b741d6d49909383c28a9',
707
707
  decimals: 18,
708
- }
708
+ },
709
709
  },
710
710
  [Network.ARBITRUM]: {
711
711
  DAI: {
@@ -785,6 +785,14 @@ export const Tokens: {
785
785
  address: '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f',
786
786
  decimals: 8,
787
787
  },
788
+ USDCe: {
789
+ address: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8',
790
+ decimals: 6,
791
+ },
792
+ LEX: {
793
+ address: '0x6bB7A17AcC227fd1F6781D1EEDEAE01B42047eE0',
794
+ decimals: 18,
795
+ },
788
796
  },
789
797
  [Network.OPTIMISM]: {
790
798
  DAI: {