@paraswap/dex-lib 2.28.8 → 2.28.9-ramses-v2

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