@paraswap/dex-lib 2.42.27 → 2.42.29

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