@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.
- package/build/dex/algebra/algebra-pool-v1_1.js +3 -2
- package/build/dex/algebra/algebra-pool-v1_1.js.map +1 -1
- package/build/dex/algebra/algebra-pool-v1_9.js +3 -2
- package/build/dex/algebra/algebra-pool-v1_9.js.map +1 -1
- package/build/dex/algebra/algebra.js.map +1 -1
- package/build/dex/algebra/config.js +2 -2
- package/build/dex/algebra/lib/AlgebraMath.d.ts +1 -1
- package/build/dex/algebra/lib/AlgebraMath.js +12 -12
- package/build/dex/algebra/lib/AlgebraMath.js.map +1 -1
- package/build/dex/algebra/lib/TickManager.d.ts +4 -0
- package/build/dex/algebra/lib/TickManager.js +60 -0
- package/build/dex/algebra/lib/TickManager.js.map +1 -0
- package/build/dex/algebra/lib/TickTable.d.ts +10 -0
- package/build/dex/algebra/lib/TickTable.js +146 -0
- package/build/dex/algebra/lib/TickTable.js.map +1 -0
- package/build/dex/algebra/lib/yul-helper.d.ts +9 -0
- package/build/dex/algebra/lib/yul-helper.js +28 -0
- package/build/dex/algebra/lib/yul-helper.js.map +1 -0
- package/build/dex/algebra/types.d.ts +3 -0
- package/build/dex/balancer-v2/optimizer.js +32 -34
- package/build/dex/balancer-v2/optimizer.js.map +1 -1
- package/build/dex/test-dex/config.d.ts +4 -0
- package/build/dex/test-dex/config.js +15 -0
- package/build/dex/test-dex/config.js.map +1 -0
- package/build/dex/test-dex/test-dex-pool.d.ts +39 -0
- package/build/dex/test-dex/test-dex-pool.js +63 -0
- package/build/dex/test-dex/test-dex-pool.js.map +1 -0
- package/build/dex/test-dex/test-dex.d.ts +37 -0
- package/build/dex/test-dex/test-dex.js +126 -0
- package/build/dex/test-dex/test-dex.js.map +1 -0
- package/build/dex/test-dex/types.d.ts +6 -0
- package/build/dex/{pancakeswap-v3 → test-dex}/types.js.map +1 -1
- package/build/dex/uniswap-v3/contract-math/TickBitMap.d.ts +0 -1
- package/build/dex/uniswap-v3/contract-math/TickBitMap.js +0 -3
- package/build/dex/uniswap-v3/contract-math/TickBitMap.js.map +1 -1
- package/build/dex/uniswap-v3/contract-math/utils.js +10 -8
- package/build/dex/uniswap-v3/contract-math/utils.js.map +1 -1
- package/build/dex/uniswap-v3/uniswap-v3.js +1 -1
- package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
- package/build/dex/woo-fi-v2/woo-fi-math.d.ts +16 -0
- package/build/dex/woo-fi-v2/woo-fi-math.js +137 -0
- package/build/dex/woo-fi-v2/woo-fi-math.js.map +1 -0
- package/package.json +1 -1
- package/src/dex/algebra/algebra-events.test.ts +73 -7
- package/src/dex/algebra/algebra-integration.test.ts +3 -2
- package/src/dex/algebra/algebra-pool-v1_1.ts +3 -2
- package/src/dex/algebra/algebra-pool-v1_9.ts +3 -4
- package/src/dex/algebra/algebra.ts +1 -2
- package/src/dex/algebra/config.ts +2 -2
- package/src/dex/algebra/lib/AlgebraMath.ts +23 -15
- package/src/dex/algebra/lib/TickManager.ts +91 -0
- package/src/dex/algebra/lib/TickTable.ts +216 -0
- package/src/dex/algebra/lib/yul-helper.ts +29 -0
- package/src/dex/algebra/types.ts +4 -0
- package/src/dex/balancer-v2/optimizer.ts +37 -39
- package/src/dex/uniswap-v2/uniswap-v2-e2e-arbitrum.test.ts +10 -2
- package/src/dex/uniswap-v3/contract-math/TickBitMap.ts +0 -9
- package/src/dex/uniswap-v3/contract-math/utils.ts +12 -10
- package/src/dex/uniswap-v3/uniswap-v3.ts +1 -1
- package/tests/constants-e2e.ts +9 -1
- package/.idea/aws.xml +0 -17
- package/.idea/codeStyles/Project.xml +0 -19
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/misc.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/paraswap-dex-lib.iml +0 -9
- package/.idea/vcs.xml +0 -6
- package/build/abi/algebra/AlgebraPool.abi.json +0 -727
- package/build/abi/curve-v1/StableSwapFRXETH.json +0 -889
- package/build/abi/curve-v1/StableSwapWBETH.json +0 -1223
- package/build/abi/wBETH.json +0 -1527
- package/build/dex/algebra/algebra-pool.d.ts +0 -46
- package/build/dex/algebra/algebra-pool.js +0 -336
- package/build/dex/algebra/algebra-pool.js.map +0 -1
- package/build/dex/curve-v1/pools/frxETHpool.d.ts +0 -7
- package/build/dex/curve-v1/pools/frxETHpool.js +0 -27
- package/build/dex/curve-v1/pools/frxETHpool.js.map +0 -1
- package/build/dex/curve-v1/pools/wbETHpool.d.ts +0 -29
- package/build/dex/curve-v1/pools/wbETHpool.js +0 -408
- package/build/dex/curve-v1/pools/wbETHpool.js.map +0 -1
- package/build/dex/pancakeswap-v3/types.d.ts +0 -14
- package/build/dex/solidly/forks-override/ramses.d.ts +0 -8
- package/build/dex/solidly/forks-override/ramses.js +0 -15
- package/build/dex/solidly/forks-override/ramses.js.map +0 -1
- /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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
451
|
+
TickTable.toggleTick(
|
|
452
|
+
state,
|
|
453
|
+
bottomTick,
|
|
454
|
+
state.areTicksCompressed ? state.tickSpacing : undefined,
|
|
455
|
+
);
|
|
451
456
|
}
|
|
452
457
|
if (
|
|
453
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
+
}
|
package/src/dex/algebra/types.ts
CHANGED
|
@@ -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
|
|
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((
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
39
|
-
BigInt(
|
|
32
|
+
newBalancer.destAmount = (
|
|
33
|
+
BigInt(newBalancer.destAmount) + BigInt(s.destAmount)
|
|
40
34
|
).toString();
|
|
41
35
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
parseFloat(
|
|
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
|
-
|
|
42
|
+
newBalancer.data.swaps.push({
|
|
50
43
|
poolId: s.data.poolId,
|
|
51
44
|
amount: side === SwapSide.SELL ? s.srcAmount : s.destAmount,
|
|
52
45
|
});
|
|
53
|
-
|
|
46
|
+
newBalancer.poolAddresses!.push(s.poolAddresses![0]);
|
|
54
47
|
} else {
|
|
55
|
-
optimizedSwap.push(
|
|
48
|
+
optimizedSwap.push(_s);
|
|
56
49
|
}
|
|
57
50
|
});
|
|
58
|
-
|
|
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
|
-
|
|
66
|
-
|
|
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
|
-
{
|
|
385
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
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}`,
|
package/tests/constants-e2e.ts
CHANGED
|
@@ -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: {
|