@paraswap/dex-lib 2.28.10-ramses-v2 → 2.28.10

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 (50) hide show
  1. package/build/abi/uniswap-v3/UniswapV3QuoterV2.abi.json +155 -0
  2. package/build/dex/index.js +0 -2
  3. package/build/dex/index.js.map +1 -1
  4. package/build/dex/uniswap-v3/config.js +0 -22
  5. package/build/dex/uniswap-v3/config.js.map +1 -1
  6. package/build/dex/uniswap-v3/types.d.ts +1 -6
  7. package/build/dex/uniswap-v3/types.js.map +1 -1
  8. package/build/dex/uniswap-v3/uniswap-v3-pool.d.ts +2 -3
  9. package/build/dex/uniswap-v3/uniswap-v3-pool.js +2 -5
  10. package/build/dex/uniswap-v3/uniswap-v3-pool.js.map +1 -1
  11. package/build/dex/uniswap-v3/uniswap-v3.js +5 -9
  12. package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
  13. package/build/lib/multi-wrapper.js +3 -5
  14. package/build/lib/multi-wrapper.js.map +1 -1
  15. package/package.json +1 -1
  16. package/src/dex/index.ts +0 -2
  17. package/src/dex/uniswap-v3/config.ts +0 -22
  18. package/src/dex/uniswap-v3/types.ts +1 -7
  19. package/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +354 -445
  20. package/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +3 -26
  21. package/src/dex/uniswap-v3/uniswap-v3-pool.ts +4 -9
  22. package/src/dex/uniswap-v3/uniswap-v3.ts +4 -9
  23. package/src/lib/multi-wrapper.ts +4 -4
  24. package/tests/constants-e2e.ts +5 -1
  25. package/src/abi/RamsesV2Pool.abi.json +0 -1554
  26. package/src/abi/RamsesV2StateMulticall.abi.json +0 -891
  27. package/src/dex/ramses-v2/config.ts +0 -31
  28. package/src/dex/ramses-v2/constants.ts +0 -41
  29. package/src/dex/ramses-v2/contract-math/BitMath.ts +0 -90
  30. package/src/dex/ramses-v2/contract-math/FixedPoint128.ts +0 -3
  31. package/src/dex/ramses-v2/contract-math/FixedPoint96.ts +0 -4
  32. package/src/dex/ramses-v2/contract-math/FullMath.ts +0 -30
  33. package/src/dex/ramses-v2/contract-math/LiquidityMath.ts +0 -17
  34. package/src/dex/ramses-v2/contract-math/Oracle.ts +0 -226
  35. package/src/dex/ramses-v2/contract-math/SqrtPriceMath.ts +0 -226
  36. package/src/dex/ramses-v2/contract-math/SwapMath.ts +0 -139
  37. package/src/dex/ramses-v2/contract-math/Tick.ts +0 -82
  38. package/src/dex/ramses-v2/contract-math/TickBitMap.ts +0 -128
  39. package/src/dex/ramses-v2/contract-math/TickMath.ts +0 -211
  40. package/src/dex/ramses-v2/contract-math/UnsafeMath.ts +0 -5
  41. package/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts +0 -666
  42. package/src/dex/ramses-v2/contract-math/utils.ts +0 -11
  43. package/src/dex/ramses-v2/ramses-v2-e2e.test.ts +0 -100
  44. package/src/dex/ramses-v2/ramses-v2-events.test.ts +0 -182
  45. package/src/dex/ramses-v2/ramses-v2-integration.test.ts +0 -462
  46. package/src/dex/ramses-v2/ramses-v2-pool.ts +0 -513
  47. package/src/dex/ramses-v2/ramses-v2.ts +0 -1136
  48. package/src/dex/ramses-v2/types.ts +0 -177
  49. package/src/dex/ramses-v2/utils.ts +0 -90
  50. package/src/dex/uniswap-v3/forks/ramses-v2/utils.ts +0 -72
@@ -1,513 +0,0 @@
1
- import _ from 'lodash';
2
- import { Contract } from 'web3-eth-contract';
3
- import { Interface } from '@ethersproject/abi';
4
- import { ethers } from 'ethers';
5
- import { assert, DeepReadonly } from 'ts-essentials';
6
- import { Log, Logger, BlockHeader, Address } from '../../types';
7
- import {
8
- InitializeStateOptions,
9
- StatefulEventSubscriber,
10
- } from '../../stateful-event-subscriber';
11
- import { IDexHelper } from '../../dex-helper/idex-helper';
12
- import {
13
- PoolState,
14
- DecodedStateMultiCallResultWithRelativeBitmaps,
15
- TickInfo,
16
- TickBitMapMappingsWithBigNumber,
17
- TickInfoMappingsWithBigNumber,
18
- } from './types';
19
- import UniswapV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json';
20
- import { bigIntify, catchParseLogError, isSampled } from '../../utils';
21
- import { uniswapV3Math } from './contract-math/uniswap-v3-math';
22
- import { MultiCallParams } from '../../lib/multi-wrapper';
23
- import { NumberAsString } from '@paraswap/core';
24
- import {
25
- DEFAULT_POOL_INIT_CODE_HASH,
26
- OUT_OF_RANGE_ERROR_POSTFIX,
27
- TICK_BITMAP_BUFFER,
28
- TICK_BITMAP_TO_USE,
29
- } from './constants';
30
- import { TickBitMap } from './contract-math/TickBitMap';
31
- import { uint256ToBigInt } from '../../lib/decoders';
32
- import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils';
33
- import { _reduceTickBitmap, _reduceTicks } from '../uniswap-v3/contract-math/utils';
34
-
35
- export class RamsesV2EventPool extends StatefulEventSubscriber<PoolState> {
36
- handlers: {
37
- [event: string]: (
38
- event: any,
39
- pool: PoolState,
40
- log: Log,
41
- blockHeader: Readonly<BlockHeader>,
42
- ) => PoolState;
43
- } = {};
44
-
45
- logDecoder: (log: Log) => any;
46
-
47
- readonly token0: Address;
48
-
49
- readonly token1: Address;
50
-
51
- private _poolAddress?: Address;
52
-
53
- private _stateRequestCallData?: MultiCallParams<
54
- bigint | DecodedStateMultiCallResultWithRelativeBitmaps
55
- >[];
56
-
57
- public readonly poolIface = new Interface(UniswapV3PoolABI);
58
-
59
- public readonly feeCodeAsString;
60
-
61
- constructor(
62
- readonly dexHelper: IDexHelper,
63
- parentName: string,
64
- readonly stateMultiContract: Contract,
65
- readonly erc20Interface: Interface,
66
- protected readonly factoryAddress: Address,
67
- public readonly feeCode: bigint,
68
- token0: Address,
69
- token1: Address,
70
- logger: Logger,
71
- mapKey: string = '',
72
- readonly poolInitCodeHash: string,
73
- ) {
74
- super(
75
- parentName,
76
- `${token0}_${token1}_${feeCode}`,
77
- dexHelper,
78
- logger,
79
- true,
80
- mapKey,
81
- );
82
- this.feeCodeAsString = feeCode.toString();
83
- this.token0 = token0.toLowerCase();
84
- this.token1 = token1.toLowerCase();
85
- this.logDecoder = (log: Log) => this.poolIface.parseLog(log);
86
- this.addressesSubscribed = new Array<Address>(1);
87
-
88
- // Add handlers
89
- this.handlers['Swap'] = this.handleSwapEvent.bind(this);
90
- this.handlers['Burn'] = this.handleBurnEvent.bind(this);
91
- this.handlers['Mint'] = this.handleMintEvent.bind(this);
92
- this.handlers['SetFeeProtocol'] = this.handleSetFeeProtocolEvent.bind(this);
93
- this.handlers['IncreaseObservationCardinalityNext'] =
94
- this.handleIncreaseObservationCardinalityNextEvent.bind(this);
95
-
96
- // Wen need them to keep balance of the pool up to date
97
- this.handlers['Collect'] = this.handleCollectEvent.bind(this);
98
- // Almost the same as Collect, but for pool owners
99
- this.handlers['CollectProtocol'] = this.handleCollectEvent.bind(this);
100
- this.handlers['Flash'] = this.handleFlashEvent.bind(this);
101
- }
102
-
103
- get poolAddress() {
104
- if (this._poolAddress === undefined) {
105
- this._poolAddress = this._computePoolAddress(
106
- this.token0,
107
- this.token1,
108
- this.feeCode,
109
- );
110
- }
111
- return this._poolAddress;
112
- }
113
-
114
- set poolAddress(address: Address) {
115
- this._poolAddress = address.toLowerCase();
116
- }
117
-
118
- async initialize(
119
- blockNumber: number,
120
- options?: InitializeStateOptions<PoolState>,
121
- ) {
122
- await super.initialize(blockNumber, options);
123
- }
124
-
125
- protected async processBlockLogs(
126
- state: DeepReadonly<PoolState>,
127
- logs: Readonly<Log>[],
128
- blockHeader: Readonly<BlockHeader>,
129
- ): Promise<DeepReadonly<PoolState> | null> {
130
- const newState = await super.processBlockLogs(state, logs, blockHeader);
131
- if (newState && !newState.isValid) {
132
- return await this.generateState(blockHeader.number);
133
- }
134
- return newState;
135
- }
136
-
137
- protected processLog(
138
- state: DeepReadonly<PoolState>,
139
- log: Readonly<Log>,
140
- blockHeader: Readonly<BlockHeader>,
141
- ): DeepReadonly<PoolState> | null {
142
- try {
143
- const event = this.logDecoder(log);
144
-
145
- const uniswapV3EventLoggingSampleRate =
146
- this.dexHelper.config.data.uniswapV3EventLoggingSampleRate;
147
- if (
148
- !this.dexHelper.config.isSlave &&
149
- uniswapV3EventLoggingSampleRate &&
150
- isSampled(uniswapV3EventLoggingSampleRate)
151
- ) {
152
- this.logger.info(
153
- `event=${event.name} - block=${
154
- blockHeader.number
155
- }. Log sampled at rate ${uniswapV3EventLoggingSampleRate * 100}%`,
156
- );
157
- }
158
-
159
- if (event.name in this.handlers) {
160
- // Because we have observations in array which is mutable by nature, there is a
161
- // ts compile error: https://stackoverflow.com/questions/53412934/disable-allowing-assigning-readonly-types-to-non-readonly-types
162
- // And there is no good workaround, so turn off the type checker for this line
163
- const _state = _.cloneDeep(state) as PoolState;
164
- try {
165
- return this.handlers[event.name](event, _state, log, blockHeader);
166
- } catch (e) {
167
- if (
168
- e instanceof Error &&
169
- e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX)
170
- ) {
171
- this.logger.warn(
172
- `${this.parentName}: Pool ${this.poolAddress} on ${
173
- this.dexHelper.config.data.network
174
- } is out of TickBitmap requested range. Re-query the state. ${JSON.stringify(
175
- event,
176
- )}`,
177
- e,
178
- );
179
- } else {
180
- this.logger.error(
181
- `${this.parentName}: Pool ${this.poolAddress}, ` +
182
- `network=${this.dexHelper.config.data.network}: Unexpected ` +
183
- `error while handling event on blockNumber=${blockHeader.number}, ` +
184
- `blockHash=${blockHeader.hash} and parentHash=${
185
- blockHeader.parentHash
186
- } for UniswapV3, ${JSON.stringify(event)}`,
187
- e,
188
- );
189
- }
190
- _state.isValid = false;
191
- return _state;
192
- }
193
- }
194
- } catch (e) {
195
- catchParseLogError(e, this.logger);
196
- }
197
- return null; // ignore unrecognized event
198
- }
199
-
200
- private _getStateRequestCallData() {
201
- if (!this._stateRequestCallData) {
202
- const callData: MultiCallParams<
203
- bigint | DecodedStateMultiCallResultWithRelativeBitmaps
204
- >[] = [
205
- {
206
- target: this.token0,
207
- callData: this.erc20Interface.encodeFunctionData('balanceOf', [
208
- this.poolAddress,
209
- ]),
210
- decodeFunction: uint256ToBigInt,
211
- },
212
- {
213
- target: this.token1,
214
- callData: this.erc20Interface.encodeFunctionData('balanceOf', [
215
- this.poolAddress,
216
- ]),
217
- decodeFunction: uint256ToBigInt,
218
- },
219
- {
220
- target: this.stateMultiContract.options.address,
221
- callData: this.stateMultiContract.methods
222
- .getFullStateWithRelativeBitmaps(
223
- this.factoryAddress,
224
- this.token0,
225
- this.token1,
226
- this.feeCode,
227
- this.getBitmapRangeToRequest(),
228
- this.getBitmapRangeToRequest(),
229
- )
230
- .encodeABI(),
231
- decodeFunction: decodeStateMultiCallResultWithRelativeBitmaps,
232
- },
233
- ];
234
- this._stateRequestCallData = callData;
235
- }
236
- return this._stateRequestCallData;
237
- }
238
-
239
- getBitmapRangeToRequest() {
240
- return TICK_BITMAP_TO_USE + TICK_BITMAP_BUFFER;
241
- }
242
-
243
- async generateState(blockNumber: number): Promise<Readonly<PoolState>> {
244
- const callData = this._getStateRequestCallData();
245
-
246
- const [resBalance0, resBalance1, resState] =
247
- await this.dexHelper.multiWrapper.tryAggregate<
248
- bigint | DecodedStateMultiCallResultWithRelativeBitmaps
249
- >(
250
- false,
251
- callData,
252
- blockNumber,
253
- this.dexHelper.multiWrapper.defaultBatchSize,
254
- false,
255
- );
256
-
257
- // Quite ugly solution, but this is the one that fits to current flow.
258
- // I think UniswapV3 callbacks subscriptions are complexified for no reason.
259
- // Need to be revisited later
260
- assert(resState.success, 'Pool does not exist');
261
-
262
- const [balance0, balance1, _state] = [
263
- resBalance0.returnData,
264
- resBalance1.returnData,
265
- resState.returnData,
266
- ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmaps];
267
-
268
- const tickBitmap = {};
269
- const ticks = {};
270
-
271
- _reduceTickBitmap(tickBitmap, _state.tickBitmap);
272
- _reduceTicks(ticks, _state.ticks);
273
-
274
- const observations = {
275
- [_state.slot0.observationIndex]: {
276
- blockTimestamp: bigIntify(_state.observation.blockTimestamp),
277
- tickCumulative: bigIntify(_state.observation.tickCumulative),
278
- secondsPerLiquidityCumulativeX128: bigIntify(
279
- _state.observation.secondsPerLiquidityCumulativeX128,
280
- ),
281
- initialized: _state.observation.initialized,
282
- },
283
- };
284
-
285
- const currentTick = bigIntify(_state.slot0.tick);
286
- const tickSpacing = bigIntify(_state.tickSpacing);
287
-
288
- const startTickBitmap = TickBitMap.position(currentTick / tickSpacing)[0];
289
- const requestedRange = this.getBitmapRangeToRequest();
290
-
291
- return {
292
- pool: _state.pool,
293
- blockTimestamp: bigIntify(_state.blockTimestamp),
294
- slot0: {
295
- sqrtPriceX96: bigIntify(_state.slot0.sqrtPriceX96),
296
- tick: currentTick,
297
- observationIndex: +_state.slot0.observationIndex,
298
- observationCardinality: +_state.slot0.observationCardinality,
299
- observationCardinalityNext: +_state.slot0.observationCardinalityNext,
300
- feeProtocol: bigIntify(_state.slot0.feeProtocol),
301
- },
302
- liquidity: bigIntify(_state.liquidity),
303
- fee: this.feeCode,
304
- tickSpacing,
305
- maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick),
306
- tickBitmap,
307
- ticks,
308
- observations,
309
- isValid: true,
310
- startTickBitmap,
311
- lowestKnownTick:
312
- (BigInt.asIntN(24, startTickBitmap - requestedRange) << 8n) *
313
- tickSpacing,
314
- highestKnownTick:
315
- ((BigInt.asIntN(24, startTickBitmap + requestedRange) << 8n) +
316
- BigInt.asIntN(24, 255n)) *
317
- tickSpacing,
318
- balance0,
319
- balance1,
320
- };
321
- }
322
-
323
- handleSwapEvent(
324
- event: any,
325
- pool: PoolState,
326
- log: Log,
327
- blockHeader: BlockHeader,
328
- ) {
329
- const newSqrtPriceX96 = bigIntify(event.args.sqrtPriceX96);
330
- const amount0 = bigIntify(event.args.amount0);
331
- const amount1 = bigIntify(event.args.amount1);
332
- const newTick = bigIntify(event.args.tick);
333
- const newLiquidity = bigIntify(event.args.liquidity);
334
- pool.blockTimestamp = bigIntify(blockHeader.timestamp);
335
-
336
- if (amount0 <= 0n && amount1 <= 0n) {
337
- this.logger.error(
338
- `${this.parentName}: amount0 <= 0n && amount1 <= 0n for ` +
339
- `${this.poolAddress} and ${blockHeader.number}. Check why it happened`,
340
- );
341
- pool.isValid = false;
342
- return pool;
343
- } else {
344
- const zeroForOne = amount0 > 0n;
345
-
346
- uniswapV3Math.swapFromEvent(
347
- pool,
348
- newSqrtPriceX96,
349
- newTick,
350
- newLiquidity,
351
- zeroForOne,
352
- );
353
-
354
- if (zeroForOne) {
355
- if (amount1 < 0n) {
356
- pool.balance1 -= BigInt.asUintN(256, -amount1);
357
- } else {
358
- this.logger.error(
359
- `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount1}`,
360
- );
361
- pool.isValid = false;
362
- }
363
- // This is not correct fully, because pool may get more tokens then it needs, but
364
- // it is not accounted in internal state, it should be good enough
365
- pool.balance0 += BigInt.asUintN(256, amount0);
366
- } else {
367
- if (amount0 < 0n) {
368
- pool.balance0 -= BigInt.asUintN(256, -amount0);
369
- } else {
370
- this.logger.error(
371
- `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount0}`,
372
- );
373
- pool.isValid = false;
374
- }
375
- pool.balance1 += BigInt.asUintN(256, amount1);
376
- }
377
-
378
- return pool;
379
- }
380
- }
381
-
382
- handleBurnEvent(
383
- event: any,
384
- pool: PoolState,
385
- log: Log,
386
- blockHeader: BlockHeader,
387
- ) {
388
- const amount = bigIntify(event.args.amount);
389
- const tickLower = bigIntify(event.args.tickLower);
390
- const tickUpper = bigIntify(event.args.tickUpper);
391
- pool.blockTimestamp = bigIntify(blockHeader.timestamp);
392
-
393
- uniswapV3Math._modifyPosition(pool, {
394
- tickLower,
395
- tickUpper,
396
- liquidityDelta: -BigInt.asIntN(128, BigInt.asIntN(256, amount)),
397
- });
398
-
399
- // From this transaction I conclude that there is no balance change from
400
- // Burn event: https://dashboard.tenderly.co/tx/mainnet/0xfccf5341147ac3ad0e66452273d12dfc3219e81f8fb369a6cdecfb24b9b9d078/logs
401
- // And it aligns with UniswapV3 doc:
402
- // https://github.com/Uniswap/v3-core/blob/05c10bf6d547d6121622ac51c457f93775e1df09/contracts/interfaces/pool/IUniswapV3PoolActions.sol#L59
403
- // It just updates positions and tokensOwed which may be requested calling collect
404
- // So, we don't need to update pool.balances0 and pool.balances1 here
405
-
406
- return pool;
407
- }
408
-
409
- handleMintEvent(
410
- event: any,
411
- pool: PoolState,
412
- log: Log,
413
- blockHeader: BlockHeader,
414
- ) {
415
- const amount = bigIntify(event.args.amount);
416
- const tickLower = bigIntify(event.args.tickLower);
417
- const tickUpper = bigIntify(event.args.tickUpper);
418
- const amount0 = bigIntify(event.args.amount0);
419
- const amount1 = bigIntify(event.args.amount1);
420
- pool.blockTimestamp = bigIntify(blockHeader.timestamp);
421
-
422
- uniswapV3Math._modifyPosition(pool, {
423
- tickLower,
424
- tickUpper,
425
- liquidityDelta: amount,
426
- });
427
-
428
- pool.balance0 += amount0;
429
- pool.balance1 += amount1;
430
-
431
- return pool;
432
- }
433
-
434
- handleSetFeeProtocolEvent(
435
- event: any,
436
- pool: PoolState,
437
- log: Log,
438
- blockHeader: BlockHeader,
439
- ) {
440
- const feeProtocol0 = bigIntify(event.args.feeProtocol0New);
441
- const feeProtocol1 = bigIntify(event.args.feeProtocol1New);
442
- pool.slot0.feeProtocol = feeProtocol0 + (feeProtocol1 << 4n);
443
- pool.blockTimestamp = bigIntify(blockHeader.timestamp);
444
-
445
- return pool;
446
- }
447
-
448
- handleCollectEvent(
449
- event: any,
450
- pool: PoolState,
451
- log: Log,
452
- blockHeader: BlockHeader,
453
- ) {
454
- const amount0 = bigIntify(event.args.amount0);
455
- const amount1 = bigIntify(event.args.amount1);
456
- pool.balance0 -= amount0;
457
- pool.balance1 -= amount1;
458
- pool.blockTimestamp = bigIntify(blockHeader.timestamp);
459
-
460
- return pool;
461
- }
462
-
463
- handleFlashEvent(
464
- event: any,
465
- pool: PoolState,
466
- log: Log,
467
- blockHeader: BlockHeader,
468
- ) {
469
- const paid0 = bigIntify(event.args.paid0);
470
- const paid1 = bigIntify(event.args.paid1);
471
- pool.balance0 += paid0;
472
- pool.balance1 += paid1;
473
- pool.blockTimestamp = bigIntify(blockHeader.timestamp);
474
-
475
- return pool;
476
- }
477
-
478
- handleIncreaseObservationCardinalityNextEvent(
479
- event: any,
480
- pool: PoolState,
481
- log: Log,
482
- blockHeader: BlockHeader,
483
- ) {
484
- pool.slot0.observationCardinalityNext = parseInt(
485
- event.args.observationCardinalityNextNew,
486
- 10,
487
- );
488
- pool.blockTimestamp = bigIntify(blockHeader.timestamp);
489
- return pool;
490
- }
491
-
492
- private _computePoolAddress(
493
- token0: Address,
494
- token1: Address,
495
- fee: bigint,
496
- ): Address {
497
- // https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/PoolAddress.sol
498
- if (token0 > token1) [token0, token1] = [token1, token0];
499
-
500
- const encodedKey = ethers.utils.keccak256(
501
- ethers.utils.defaultAbiCoder.encode(
502
- ['address', 'address', 'uint24'],
503
- [token0, token1, BigInt.asUintN(24, fee)],
504
- ),
505
- );
506
-
507
- return ethers.utils.getCreate2Address(
508
- this.factoryAddress,
509
- encodedKey,
510
- this.poolInitCodeHash,
511
- );
512
- }
513
- }