@paraswap/dex-lib 3.7.7-skip-approval.3 → 3.7.8-oswap

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 (222) hide show
  1. package/build/abi/inception/inception-ineth-pool.json +1062 -0
  2. package/build/abi/inception/inception-ineth.json +609 -0
  3. package/build/abi/inception/inception-vault.json +991 -0
  4. package/build/abi/oswap/oswap.abi.json +452 -0
  5. package/build/dex/aave-v1/aave-v1.d.ts +2 -1
  6. package/build/dex/aave-v1/aave-v1.js +22 -0
  7. package/build/dex/aave-v1/aave-v1.js.map +1 -1
  8. package/build/dex/aave-v3/aave-v3.js +1 -2
  9. package/build/dex/aave-v3/aave-v3.js.map +1 -1
  10. package/build/dex/aave-v3-stata/aave-v3-stata.js +0 -1
  11. package/build/dex/aave-v3-stata/aave-v3-stata.js.map +1 -1
  12. package/build/dex/angle-staked-stable/angle-staked-stable.js +1 -4
  13. package/build/dex/angle-staked-stable/angle-staked-stable.js.map +1 -1
  14. package/build/dex/compound/compound.js +1 -2
  15. package/build/dex/compound/compound.js.map +1 -1
  16. package/build/dex/etherfi.js +1 -4
  17. package/build/dex/etherfi.js.map +1 -1
  18. package/build/dex/idle-dao/idle-dao-pool.d.ts +56 -0
  19. package/build/dex/idle-dao/idle-dao-pool.js +176 -0
  20. package/build/dex/idle-dao/idle-dao-pool.js.map +1 -0
  21. package/build/dex/idle-dao/idle-dao-pooling-pool.d.ts +16 -0
  22. package/build/dex/idle-dao/idle-dao-pooling-pool.js +57 -0
  23. package/build/dex/idle-dao/idle-dao-pooling-pool.js.map +1 -0
  24. package/build/dex/idle-dao/idle-dao.js +0 -1
  25. package/build/dex/idle-dao/idle-dao.js.map +1 -1
  26. package/build/dex/idle-dao/scripts.d.ts +9 -0
  27. package/build/dex/idle-dao/scripts.js +552 -0
  28. package/build/dex/idle-dao/scripts.js.map +1 -0
  29. package/build/dex/inception/config.d.ts +5 -0
  30. package/build/dex/inception/config.js +100 -0
  31. package/build/dex/inception/config.js.map +1 -0
  32. package/build/dex/inception/inception-native.d.ts +43 -0
  33. package/build/dex/inception/inception-native.js +131 -0
  34. package/build/dex/inception/inception-native.js.map +1 -0
  35. package/build/dex/inception/inception-pool.d.ts +18 -0
  36. package/build/dex/inception/inception-pool.js +32 -0
  37. package/build/dex/inception/inception-pool.js.map +1 -0
  38. package/build/dex/inception/inception.d.ts +42 -0
  39. package/build/dex/inception/inception.js +128 -0
  40. package/build/dex/inception/inception.js.map +1 -0
  41. package/build/dex/inception/types.d.ts +11 -0
  42. package/build/dex/inception/types.js +3 -0
  43. package/build/dex/inception/types.js.map +1 -0
  44. package/build/dex/inception/utils.d.ts +4 -0
  45. package/build/dex/inception/utils.js +22 -0
  46. package/build/dex/inception/utils.js.map +1 -0
  47. package/build/dex/index.js +2 -0
  48. package/build/dex/index.js.map +1 -1
  49. package/build/dex/mStable.js +1 -1
  50. package/build/dex/mStable.js.map +1 -1
  51. package/build/dex/oswap/config.d.ts +5 -0
  52. package/build/dex/oswap/config.js +31 -0
  53. package/build/dex/oswap/config.js.map +1 -0
  54. package/build/dex/oswap/oswap-pool.d.ts +51 -0
  55. package/build/dex/oswap/oswap-pool.js +150 -0
  56. package/build/dex/oswap/oswap-pool.js.map +1 -0
  57. package/build/dex/oswap/oswap.d.ts +46 -0
  58. package/build/dex/oswap/oswap.js +263 -0
  59. package/build/dex/oswap/oswap.js.map +1 -0
  60. package/build/dex/oswap/types.d.ts +20 -0
  61. package/build/dex/oswap/types.js +3 -0
  62. package/build/dex/oswap/types.js.map +1 -0
  63. package/build/dex/platypus/platypus.d.ts +2 -1
  64. package/build/dex/platypus/platypus.js +31 -0
  65. package/build/dex/platypus/platypus.js.map +1 -1
  66. package/build/dex/simple-exchange.d.ts +1 -1
  67. package/build/dex/simple-exchange.js +2 -4
  68. package/build/dex/simple-exchange.js.map +1 -1
  69. package/build/dex/spark/spark.js +1 -1
  70. package/build/dex/spark/spark.js.map +1 -1
  71. package/build/dex/swaap-v1/swaap-v1.d.ts +2 -1
  72. package/build/dex/swaap-v1/swaap-v1.js +10 -0
  73. package/build/dex/swaap-v1/swaap-v1.js.map +1 -1
  74. package/build/executor/Executor01BytecodeBuilder.js +0 -1
  75. package/build/executor/Executor01BytecodeBuilder.js.map +1 -1
  76. package/build/executor/Executor02BytecodeBuilder.js +0 -1
  77. package/build/executor/Executor02BytecodeBuilder.js.map +1 -1
  78. package/build/executor/Executor03BytecodeBuilder.js +0 -1
  79. package/build/executor/Executor03BytecodeBuilder.js.map +1 -1
  80. package/build/generic-swap-transaction-builder.js +2 -2
  81. package/build/generic-swap-transaction-builder.js.map +1 -1
  82. package/build/types.d.ts +0 -1
  83. package/build/utils.d.ts +1 -1
  84. package/package.json +1 -1
  85. package/src/abi/oswap/oswap.abi.json +452 -0
  86. package/src/dex/aave-v3/aave-v3-e2e.test.ts +9 -4
  87. package/src/dex/aave-v3/aave-v3.ts +0 -5
  88. package/src/dex/aave-v3-stata/aave-v3-stata.ts +0 -1
  89. package/src/dex/angle-staked-stable/angle-staked-stable.ts +0 -8
  90. package/src/dex/compound/compound.ts +0 -5
  91. package/src/dex/etherfi.ts +0 -5
  92. package/src/dex/idle-dao/idle-dao.ts +0 -1
  93. package/src/dex/index.ts +2 -0
  94. package/src/dex/mStable.ts +0 -4
  95. package/src/dex/oswap/config.ts +32 -0
  96. package/src/dex/oswap/oswap-e2e.test.ts +91 -0
  97. package/src/dex/oswap/oswap-events.test.ts +88 -0
  98. package/src/dex/oswap/oswap-integration.test.ts +287 -0
  99. package/src/dex/oswap/oswap-pool.ts +190 -0
  100. package/src/dex/oswap/oswap.ts +359 -0
  101. package/src/dex/oswap/types.ts +29 -0
  102. package/src/dex/simple-exchange.ts +5 -5
  103. package/src/dex/spark/spark-e2e.test.ts +1 -9
  104. package/src/dex/spark/spark.ts +0 -4
  105. package/src/executor/Executor01BytecodeBuilder.ts +0 -1
  106. package/src/executor/Executor02BytecodeBuilder.ts +0 -1
  107. package/src/executor/Executor03BytecodeBuilder.ts +0 -1
  108. package/src/executor/executor01-bytecode-builder-e2e.test.ts +0 -25
  109. package/src/executor/executor02-bytecode-builder-e2e.test.ts +0 -29
  110. package/src/generic-swap-transaction-builder.ts +1 -2
  111. package/src/types.ts +0 -1
  112. package/tests/constants-e2e.ts +13 -13
  113. package/tests/utils-e2e.ts +1 -1
  114. package/build/abi/Uncompressor.json +0 -250
  115. package/build/dex/bProtocol.d.ts +0 -18
  116. package/build/dex/bProtocol.js +0 -39
  117. package/build/dex/bProtocol.js.map +0 -1
  118. package/build/dex/bancor.d.ts +0 -26
  119. package/build/dex/bancor.js +0 -58
  120. package/build/dex/bancor.js.map +0 -1
  121. package/build/dex/compound.d.ts +0 -18
  122. package/build/dex/compound.js +0 -46
  123. package/build/dex/compound.js.map +0 -1
  124. package/build/dex/curve-v2.d.ts +0 -58
  125. package/build/dex/curve-v2.js +0 -180
  126. package/build/dex/curve-v2.js.map +0 -1
  127. package/build/dex/dodo-v1.d.ts +0 -33
  128. package/build/dex/dodo-v1.js +0 -63
  129. package/build/dex/dodo-v1.js.map +0 -1
  130. package/build/dex/etherfi/etherfi.d.ts +0 -26
  131. package/build/dex/etherfi/etherfi.js +0 -96
  132. package/build/dex/etherfi/etherfi.js.map +0 -1
  133. package/build/dex/lido.d.ts +0 -19
  134. package/build/dex/lido.js +0 -42
  135. package/build/dex/lido.js.map +0 -1
  136. package/build/dex/onebit.d.ts +0 -25
  137. package/build/dex/onebit.js +0 -42
  138. package/build/dex/onebit.js.map +0 -1
  139. package/build/dex/sdai/config.d.ts +0 -11
  140. package/build/dex/sdai/config.js +0 -21
  141. package/build/dex/sdai/config.js.map +0 -1
  142. package/build/dex/sdai/constants.d.ts +0 -2
  143. package/build/dex/sdai/constants.js +0 -6
  144. package/build/dex/sdai/constants.js.map +0 -1
  145. package/build/dex/sdai/scripts/validate-state.d.ts +0 -1
  146. package/build/dex/sdai/scripts/validate-state.js +0 -102
  147. package/build/dex/sdai/scripts/validate-state.js.map +0 -1
  148. package/build/dex/sdai/sdai-pool.d.ts +0 -16
  149. package/build/dex/sdai/sdai-pool.js +0 -85
  150. package/build/dex/sdai/sdai-pool.js.map +0 -1
  151. package/build/dex/sdai/sdai.d.ts +0 -51
  152. package/build/dex/sdai/sdai.js +0 -172
  153. package/build/dex/sdai/sdai.js.map +0 -1
  154. package/build/dex/sdai/types.d.ts +0 -21
  155. package/build/dex/sdai/types.js +0 -11
  156. package/build/dex/sdai/types.js.map +0 -1
  157. package/build/dex/sdai/utils.d.ts +0 -4
  158. package/build/dex/sdai/utils.js +0 -39
  159. package/build/dex/sdai/utils.js.map +0 -1
  160. package/build/dex/smoothy.d.ts +0 -26
  161. package/build/dex/smoothy.js +0 -48
  162. package/build/dex/smoothy.js.map +0 -1
  163. package/build/dex/stable-pool.d.ts +0 -28
  164. package/build/dex/stable-pool.js +0 -62
  165. package/build/dex/stable-pool.js.map +0 -1
  166. package/build/dex/trader-joe-v2.1.d.ts +0 -43
  167. package/build/dex/trader-joe-v2.1.js +0 -79
  168. package/build/dex/trader-joe-v2.1.js.map +0 -1
  169. package/build/executor/compressor/Compressor.d.ts +0 -23
  170. package/build/executor/compressor/Compressor.js +0 -144
  171. package/build/executor/compressor/Compressor.js.map +0 -1
  172. package/build/executor/compressor/compress.d.ts +0 -17
  173. package/build/executor/compressor/compress.js +0 -187
  174. package/build/executor/compressor/compress.js.map +0 -1
  175. package/build/executor/compressor/compress_functions/addressSubstitution.d.ts +0 -6
  176. package/build/executor/compressor/compress_functions/addressSubstitution.js +0 -29
  177. package/build/executor/compressor/compress_functions/addressSubstitution.js.map +0 -1
  178. package/build/executor/compressor/compress_functions/addressSubstitutionFromObject.d.ts +0 -10
  179. package/build/executor/compressor/compress_functions/addressSubstitutionFromObject.js +0 -40
  180. package/build/executor/compressor/compress_functions/addressSubstitutionFromObject.js.map +0 -1
  181. package/build/executor/compressor/compress_functions/byteSubstitution.d.ts +0 -11
  182. package/build/executor/compressor/compress_functions/byteSubstitution.js +0 -64
  183. package/build/executor/compressor/compress_functions/byteSubstitution.js.map +0 -1
  184. package/build/executor/compressor/compress_functions/ffSubstitution.d.ts +0 -7
  185. package/build/executor/compressor/compress_functions/ffSubstitution.js +0 -54
  186. package/build/executor/compressor/compress_functions/ffSubstitution.js.map +0 -1
  187. package/build/executor/compressor/compress_functions/findLongestAndSubstitute.d.ts +0 -8
  188. package/build/executor/compressor/compress_functions/findLongestAndSubstitute.js +0 -67
  189. package/build/executor/compressor/compress_functions/findLongestAndSubstitute.js.map +0 -1
  190. package/build/executor/compressor/compress_functions/findLongestAndSubstitute_old.d.ts +0 -8
  191. package/build/executor/compressor/compress_functions/findLongestAndSubstitute_old.js +0 -61
  192. package/build/executor/compressor/compress_functions/findLongestAndSubstitute_old.js.map +0 -1
  193. package/build/executor/compressor/compress_functions/reverseAddressSubstitution.d.ts +0 -6
  194. package/build/executor/compressor/compress_functions/reverseAddressSubstitution.js +0 -37
  195. package/build/executor/compressor/compress_functions/reverseAddressSubstitution.js.map +0 -1
  196. package/build/executor/compressor/compress_functions/searchUnusedBytes.d.ts +0 -9
  197. package/build/executor/compressor/compress_functions/searchUnusedBytes.js +0 -33
  198. package/build/executor/compressor/compress_functions/searchUnusedBytes.js.map +0 -1
  199. package/build/executor/compressor/fetchSaved.d.ts +0 -0
  200. package/build/executor/compressor/fetchSaved.js +0 -17
  201. package/build/executor/compressor/fetchSaved.js.map +0 -1
  202. package/build/executor/compressor/utils/computeCostL2.d.ts +0 -2
  203. package/build/executor/compressor/utils/computeCostL2.js +0 -14
  204. package/build/executor/compressor/utils/computeCostL2.js.map +0 -1
  205. package/build/executor/compressor/utils/findLongestDuplicatedString.d.ts +0 -2
  206. package/build/executor/compressor/utils/findLongestDuplicatedString.js +0 -30
  207. package/build/executor/compressor/utils/findLongestDuplicatedString.js.map +0 -1
  208. package/build/executor/compressor/utils/getAllIndexes.d.ts +0 -2
  209. package/build/executor/compressor/utils/getAllIndexes.js +0 -12
  210. package/build/executor/compressor/utils/getAllIndexes.js.map +0 -1
  211. package/build/executor/compressor/utils/getByteForAddress.d.ts +0 -2
  212. package/build/executor/compressor/utils/getByteForAddress.js +0 -14
  213. package/build/executor/compressor/utils/getByteForAddress.js.map +0 -1
  214. package/build/executor/compressor/utils/intTo2Bytes.d.ts +0 -2
  215. package/build/executor/compressor/utils/intTo2Bytes.js +0 -14
  216. package/build/executor/compressor/utils/intTo2Bytes.js.map +0 -1
  217. package/build/executor/compressor/utils/intTo3Bytes.d.ts +0 -2
  218. package/build/executor/compressor/utils/intTo3Bytes.js +0 -18
  219. package/build/executor/compressor/utils/intTo3Bytes.js.map +0 -1
  220. package/build/executor/compressor/utils/intToByte.d.ts +0 -2
  221. package/build/executor/compressor/utils/intToByte.js +0 -10
  222. package/build/executor/compressor/utils/intToByte.js.map +0 -1
@@ -127,7 +127,6 @@ export class EtherFi
127
127
 
128
128
  // if src token is WETH, we need to withdraw from weth and pass eth value on call. For other cases, we need to approve and perform call
129
129
  const isSrcTokenWeth = this.isWETH(srcToken);
130
- const skipApproval = this.is_weETH(srcToken) && this.is_eETH(destToken);
131
130
 
132
131
  return this.buildSimpleParamWithoutWETHConversion(
133
132
  isSrcTokenWeth ? ETHER_ADDRESS : srcToken,
@@ -149,7 +148,6 @@ export class EtherFi
149
148
  values: ['0'],
150
149
  }
151
150
  : undefined,
152
- skipApproval,
153
151
  );
154
152
  }
155
153
 
@@ -208,8 +206,6 @@ export class EtherFi
208
206
  swapFunctionParams,
209
207
  );
210
208
 
211
- const skipApproval = this.is_weETH(srcToken) && this.is_eETH(destToken);
212
-
213
209
  return {
214
210
  needWrapNative: this.needWrapNative,
215
211
  dexFuncHasRecipient: false,
@@ -223,7 +219,6 @@ export class EtherFi
223
219
  ])
224
220
  : undefined,
225
221
  returnAmountPos: extractReturnAmountPosition(Interface, swapFunction),
226
- skipApproval,
227
222
  };
228
223
  }
229
224
 
@@ -350,7 +350,6 @@ export class IdleDao extends SimpleExchange implements IDex<IdleDaoData> {
350
350
  exchangeData,
351
351
  targetExchange: swapCallee,
352
352
  returnAmountPos: side === SwapSide.SELL ? returnAmountPos : undefined,
353
- skipApproval: data.fromIdleToken,
354
353
  };
355
354
  }
356
355
 
package/src/dex/index.ts CHANGED
@@ -88,6 +88,7 @@ import { EtherFi } from './etherfi';
88
88
  import { Spark } from './spark/spark';
89
89
  import { VelodromeSlipstream } from './uniswap-v3/forks/velodrome-slipstream/velodrome-slipstream';
90
90
  import { AaveV3Stata } from './aave-v3-stata/aave-v3-stata';
91
+ import { OSwap } from './oswap/oswap';
91
92
 
92
93
  const LegacyDexes = [
93
94
  CurveV2,
@@ -172,6 +173,7 @@ const Dexes = [
172
173
  PharaohV1,
173
174
  Spark,
174
175
  AaveV3Stata,
176
+ OSwap,
175
177
  ];
176
178
 
177
179
  export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder<
@@ -142,10 +142,6 @@ export class MStable
142
142
  destAmount,
143
143
  swapData,
144
144
  data.exchange,
145
- undefined,
146
- undefined,
147
- undefined,
148
- opType === MStableFunctions.redeem,
149
145
  );
150
146
  }
151
147
  }
@@ -0,0 +1,32 @@
1
+ import { DexParams } from './types';
2
+ import { DexConfigMap, AdapterMappings } from '../../types';
3
+ import { Network, SwapSide } from '../../constants';
4
+
5
+ export const OSWAP_GAS_COST = 80_000;
6
+
7
+ // Important:
8
+ // - All addresses should be lower case.
9
+ // - Only tokens with 18 decimals are supported.
10
+ export const OSwapConfig: DexConfigMap<DexParams> = {
11
+ OSwap: {
12
+ [Network.MAINNET]: {
13
+ pools: [
14
+ {
15
+ id: 'OSwap_0x85b78aca6deae198fbf201c82daf6ca21942acc6', // Pool identifier: `{dex_key}_{pool_address}`
16
+ address: '0x85b78aca6deae198fbf201c82daf6ca21942acc6', // Address of the pool
17
+ token0: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH
18
+ token1: '0xae7ab96520de3a18e5e111b5eaab095312d7fe84', // STETH
19
+ },
20
+ ],
21
+ },
22
+ },
23
+ };
24
+
25
+ export const Adapters: Record<number, AdapterMappings> = {
26
+ [Network.MAINNET]: {
27
+ // Note: We re-use the SmarDex adapters since it implements
28
+ // an Uniswap V2 router compatible interface, which OSwap supports.
29
+ [SwapSide.SELL]: [{ name: 'Adapter04', index: 6 }],
30
+ [SwapSide.BUY]: [{ name: 'BuyAdapter02', index: 2 }],
31
+ },
32
+ };
@@ -0,0 +1,91 @@
1
+ /* eslint-disable no-console */
2
+ import dotenv from 'dotenv';
3
+ dotenv.config();
4
+
5
+ import { testE2E } from '../../../tests/utils-e2e';
6
+ import { Tokens, Holders } from '../../../tests/constants-e2e';
7
+ import { Network, ContractMethod, SwapSide } from '../../constants';
8
+ import { StaticJsonRpcProvider } from '@ethersproject/providers';
9
+ import { generateConfig } from '../../config';
10
+
11
+ function testForNetwork(
12
+ network: Network,
13
+ dexKey: string,
14
+ tokenASymbol: string,
15
+ tokenBSymbol: string,
16
+ tokenAAmount: string,
17
+ tokenBAmount: string,
18
+ ) {
19
+ const provider = new StaticJsonRpcProvider(
20
+ generateConfig(network).privateHttpProvider,
21
+ network,
22
+ );
23
+ const tokens = Tokens[network];
24
+ const holders = Holders[network];
25
+
26
+ const sideToContractMethods = new Map([
27
+ [SwapSide.SELL, [ContractMethod.swapExactAmountIn]],
28
+ [SwapSide.BUY, [ContractMethod.swapExactAmountOut]],
29
+ ]);
30
+
31
+ describe(`${network}`, () => {
32
+ sideToContractMethods.forEach((contractMethods, side) =>
33
+ describe(`${side}`, () => {
34
+ contractMethods.forEach((contractMethod: ContractMethod) => {
35
+ describe(`${contractMethod}`, () => {
36
+ it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => {
37
+ await testE2E(
38
+ tokens[tokenASymbol],
39
+ tokens[tokenBSymbol],
40
+ holders[tokenASymbol],
41
+ side === SwapSide.SELL ? tokenAAmount : tokenBAmount,
42
+ side,
43
+ dexKey,
44
+ contractMethod,
45
+ network,
46
+ provider,
47
+ );
48
+ });
49
+
50
+ it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => {
51
+ await testE2E(
52
+ tokens[tokenBSymbol],
53
+ tokens[tokenASymbol],
54
+ holders[tokenBSymbol],
55
+ side === SwapSide.SELL ? tokenBAmount : tokenAAmount,
56
+ side,
57
+ dexKey,
58
+ contractMethod,
59
+ network,
60
+ provider,
61
+ );
62
+ });
63
+ });
64
+ });
65
+ }),
66
+ );
67
+ });
68
+ }
69
+
70
+ describe('Oswap E2E', () => {
71
+ const dexKey = 'OSwap';
72
+
73
+ describe('Mainnet', () => {
74
+ const network = Network.MAINNET;
75
+
76
+ const tokenASymbol: string = 'WETH';
77
+ const tokenBSymbol: string = 'STETH';
78
+
79
+ const tokenAAmount: string = '10000000000000';
80
+ const tokenBAmount: string = '10000000000000';
81
+
82
+ testForNetwork(
83
+ network,
84
+ dexKey,
85
+ tokenASymbol,
86
+ tokenBSymbol,
87
+ tokenAAmount,
88
+ tokenBAmount,
89
+ );
90
+ });
91
+ });
@@ -0,0 +1,88 @@
1
+ /* eslint-disable no-console */
2
+ import dotenv from 'dotenv';
3
+ dotenv.config();
4
+
5
+ import { OSwapConfig } from './config';
6
+ import { OSwapEventPool } from './oswap-pool';
7
+ import { Network } from '../../constants';
8
+ import { Address } from '../../types';
9
+ import { DummyDexHelper } from '../../dex-helper/index';
10
+ import { testEventSubscriber } from '../../../tests/utils-events';
11
+ import { OSwapPool, OSwapPoolState } from './types';
12
+
13
+ jest.setTimeout(50 * 1000);
14
+
15
+ // eventName -> blockNumbers
16
+ type EventMappings = Record<string, number[]>;
17
+
18
+ // Helper function. Returns the absolute value of the difference between 2 bigints.
19
+ function absdelta(a: bigint, b: bigint) {
20
+ const delta = a - b;
21
+ return delta < 0 ? -delta : delta;
22
+ }
23
+
24
+ function stateCompare(state1: OSwapPoolState, state2: OSwapPoolState) {
25
+ const ROUNDING_ERROR = 2;
26
+
27
+ expect(state1.traderate0).toEqual(state2.traderate0);
28
+ expect(state1.traderate1).toEqual(state2.traderate1);
29
+ // Some ERC20 tokens have rounding error which can lead to the balance computed from Transfer event valuee
30
+ // to deviate by a couple gwei vs the on-chain balance.
31
+ // For example stETH: https://docs.lido.fi/guides/lido-tokens-integration-guide/#1-2-wei-corner-case
32
+ expect(absdelta(state1.balance0, state2.balance0)).toBeLessThanOrEqual(
33
+ ROUNDING_ERROR,
34
+ );
35
+ expect(absdelta(state1.balance1, state2.balance1)).toBeLessThanOrEqual(
36
+ ROUNDING_ERROR,
37
+ );
38
+ }
39
+
40
+ describe('Oswap EventPool Mainnet', function () {
41
+ const dexKey = 'OSwap';
42
+ const network = Network.MAINNET;
43
+ const dexHelper = new DummyDexHelper(network);
44
+ const logger = dexHelper.getLogger(dexKey);
45
+ const pool: OSwapPool = OSwapConfig[dexKey][network].pools[0];
46
+
47
+ let eventPool: OSwapEventPool;
48
+
49
+ // poolAddress -> EventMappings
50
+ const eventsToTest: Record<Address, EventMappings> = {
51
+ [pool.address]: {
52
+ TraderateChanged: [18917344],
53
+ Transfer: [18922097, 18924756],
54
+ },
55
+ };
56
+
57
+ beforeEach(async () => {
58
+ eventPool = new OSwapEventPool(dexKey, pool, network, dexHelper, logger);
59
+ });
60
+
61
+ Object.entries(eventsToTest).forEach(
62
+ ([poolAddress, events]: [string, EventMappings]) => {
63
+ describe(`Events for ${poolAddress}`, () => {
64
+ Object.entries(events).forEach(
65
+ ([eventName, blockNumbers]: [string, number[]]) => {
66
+ describe(`${eventName}`, () => {
67
+ blockNumbers.forEach((blockNumber: number) => {
68
+ it(`State after ${blockNumber}`, async function () {
69
+ await testEventSubscriber(
70
+ eventPool,
71
+ eventPool.addressesSubscribed,
72
+ (_blockNumber: number) =>
73
+ eventPool.generateState(_blockNumber),
74
+ blockNumber,
75
+ `${dexKey}_${poolAddress}`,
76
+ dexHelper.provider,
77
+ (state1: OSwapPoolState, state2: OSwapPoolState) =>
78
+ stateCompare(state1, state2),
79
+ );
80
+ });
81
+ });
82
+ });
83
+ },
84
+ );
85
+ });
86
+ },
87
+ );
88
+ });
@@ -0,0 +1,287 @@
1
+ /* eslint-disable no-console */
2
+ import dotenv from 'dotenv';
3
+ dotenv.config();
4
+
5
+ import { DummyDexHelper } from '../../dex-helper/index';
6
+ import { Network, SwapSide } from '../../constants';
7
+ import { BI_POWS } from '../../bigint-constants';
8
+ import { MultiCallParams } from '../../lib/multi-wrapper';
9
+ import { uint256ToBigInt } from '../../lib/decoders';
10
+ import { getBigIntPow } from '../../utils';
11
+ import {
12
+ checkPoolPrices,
13
+ checkPoolsLiquidity,
14
+ checkConstantPoolPrices,
15
+ } from '../../../tests/utils';
16
+ import { Tokens } from '../../../tests/constants-e2e';
17
+ import { Address } from '../../types';
18
+ import { OSwap } from './oswap';
19
+ import { OSwapPool } from './types';
20
+
21
+ async function getOnchainTraderates(
22
+ oswap: OSwap,
23
+ pool: OSwapPool,
24
+ blockNumber: number,
25
+ ): Promise<{ traderate0: bigint; traderate1: bigint }> {
26
+ const callData: MultiCallParams<bigint>[] = [
27
+ {
28
+ target: pool.address,
29
+ callData: oswap.iOSwap.encodeFunctionData('traderate0', []),
30
+ decodeFunction: uint256ToBigInt,
31
+ },
32
+ {
33
+ target: pool.address,
34
+ callData: oswap.iOSwap.encodeFunctionData('traderate1', []),
35
+ decodeFunction: uint256ToBigInt,
36
+ },
37
+ ];
38
+
39
+ const results = await oswap.dexHelper.multiWrapper.aggregate<bigint>(
40
+ callData,
41
+ blockNumber,
42
+ oswap.dexHelper.multiWrapper.defaultBatchSize,
43
+ );
44
+
45
+ return { traderate0: results[0], traderate1: results[1] };
46
+ }
47
+
48
+ // Check prices passed as arguments against prices calculated from on-chain data.
49
+ async function checkOnChainPricing(
50
+ oswap: OSwap,
51
+ pool: OSwapPool,
52
+ blockNumber: number,
53
+ prices: bigint[],
54
+ side: SwapSide,
55
+ srcAddress: Address,
56
+ destAddress: Address,
57
+ amounts: bigint[],
58
+ ) {
59
+ // Get the onchain trade rates from the pool and calculate the prices.
60
+ const data = await getOnchainTraderates(oswap, pool, blockNumber);
61
+ let expectedPrices: bigint[] = [];
62
+ for (const amount of amounts) {
63
+ const rate =
64
+ srcAddress.toLowerCase() === pool.token0
65
+ ? data.traderate0
66
+ : data.traderate1;
67
+ if (side === SwapSide.SELL) {
68
+ expectedPrices.push((amount * rate) / getBigIntPow(36));
69
+ } else {
70
+ // SwapSide.BUY
71
+ expectedPrices.push((amount * getBigIntPow(36)) / rate);
72
+ }
73
+ }
74
+ expect(prices).toEqual(expectedPrices);
75
+ }
76
+
77
+ async function testPricingOnNetwork(
78
+ oswap: OSwap,
79
+ network: Network,
80
+ dexKey: string,
81
+ blockNumber: number,
82
+ srcTokenSymbol: string,
83
+ destTokenSymbol: string,
84
+ side: SwapSide,
85
+ amounts: bigint[],
86
+ ) {
87
+ const networkTokens = Tokens[network];
88
+ const srcToken = networkTokens[srcTokenSymbol];
89
+ const destToken = networkTokens[destTokenSymbol];
90
+
91
+ const poolIds = await oswap.getPoolIdentifiers(
92
+ srcToken,
93
+ destToken,
94
+ side,
95
+ blockNumber,
96
+ );
97
+ console.log(
98
+ `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: ${poolIds}`,
99
+ );
100
+
101
+ expect(poolIds.length).toBeGreaterThan(0);
102
+
103
+ // Get calculated prices based on the stored state.
104
+ const poolPrices = await oswap.getPricesVolume(
105
+ srcToken,
106
+ destToken,
107
+ amounts,
108
+ side,
109
+ blockNumber,
110
+ poolIds,
111
+ );
112
+ console.log(
113
+ `${side} ${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `,
114
+ poolPrices,
115
+ );
116
+
117
+ expect(poolPrices).not.toBeNull();
118
+ if (oswap.hasConstantPriceLargeAmounts) {
119
+ checkConstantPoolPrices(poolPrices!, amounts, dexKey);
120
+ } else {
121
+ checkPoolPrices(poolPrices!, amounts, side, dexKey);
122
+ }
123
+
124
+ // Check that the prices calculated from onchain data match with the ones calculated from the stored state.
125
+ const pool = oswap.getPoolById(poolIds[0]);
126
+ expect(pool).not.toBeNull();
127
+ await checkOnChainPricing(
128
+ oswap,
129
+ pool as OSwapPool,
130
+ blockNumber,
131
+ poolPrices![0].prices,
132
+ side,
133
+ srcToken.address,
134
+ destToken.address,
135
+ amounts,
136
+ );
137
+ }
138
+
139
+ describe('OSwap', function () {
140
+ const dexKey = 'OSwap';
141
+ let blockNumber: number;
142
+ let oswap: OSwap;
143
+
144
+ describe('Mainnet', () => {
145
+ const network = Network.MAINNET;
146
+ const dexHelper = new DummyDexHelper(network);
147
+
148
+ const tokens = Tokens[network];
149
+
150
+ const srcTokenSymbol = 'WETH';
151
+ const destTokenSymbol = 'STETH';
152
+
153
+ const amountsForSell = [
154
+ 0n,
155
+ 1n * BI_POWS[tokens[srcTokenSymbol].decimals],
156
+ 2n * BI_POWS[tokens[srcTokenSymbol].decimals],
157
+ 3n * BI_POWS[tokens[srcTokenSymbol].decimals],
158
+ 4n * BI_POWS[tokens[srcTokenSymbol].decimals],
159
+ 5n * BI_POWS[tokens[srcTokenSymbol].decimals],
160
+ 6n * BI_POWS[tokens[srcTokenSymbol].decimals],
161
+ 7n * BI_POWS[tokens[srcTokenSymbol].decimals],
162
+ 8n * BI_POWS[tokens[srcTokenSymbol].decimals],
163
+ 9n * BI_POWS[tokens[srcTokenSymbol].decimals],
164
+ 10n * BI_POWS[tokens[srcTokenSymbol].decimals],
165
+ ];
166
+
167
+ const amountsForBuy = [
168
+ 0n,
169
+ 1n * BI_POWS[tokens[destTokenSymbol].decimals],
170
+ 2n * BI_POWS[tokens[destTokenSymbol].decimals],
171
+ 3n * BI_POWS[tokens[destTokenSymbol].decimals],
172
+ 4n * BI_POWS[tokens[destTokenSymbol].decimals],
173
+ 5n * BI_POWS[tokens[destTokenSymbol].decimals],
174
+ 6n * BI_POWS[tokens[destTokenSymbol].decimals],
175
+ 7n * BI_POWS[tokens[destTokenSymbol].decimals],
176
+ 8n * BI_POWS[tokens[destTokenSymbol].decimals],
177
+ 9n * BI_POWS[tokens[destTokenSymbol].decimals],
178
+ 10n * BI_POWS[tokens[destTokenSymbol].decimals],
179
+ ];
180
+
181
+ // Return a blockNumber to use for the tests.
182
+ // Check that the pool has enough liquidity to run the tests at the current blockNumber.
183
+ // If not, fallback to a known blockNumber in the past with
184
+ // high enough liquidity - the on-chain queries will just be a bit slower to execute.
185
+ async function getBlockNumberForTesting(oswap: OSwap): Promise<number> {
186
+ const DEFAULT_BLOCK_NUMBER = 18888241;
187
+
188
+ blockNumber = await dexHelper.web3Provider.eth.getBlockNumber();
189
+ const srcToken = Tokens[network][srcTokenSymbol];
190
+ const destToken = Tokens[network][destTokenSymbol];
191
+
192
+ // Get the pool and its state for the given test pair.
193
+ const pool = oswap.getPoolByTokenPair(srcToken, destToken);
194
+ if (!pool)
195
+ throw new Error(
196
+ `No pool found for pair ${srcTokenSymbol}-${destTokenSymbol}`,
197
+ );
198
+
199
+ const eventPool = oswap.eventPools[pool.id];
200
+ const state = await eventPool.getStateOrGenerate(blockNumber, true);
201
+
202
+ // Sum up all the amounts from the test scenarios.
203
+ const sellTotalAmount = amountsForSell.reduce(
204
+ (a: bigint, b: bigint) => a + b,
205
+ BigInt(0),
206
+ );
207
+ const buyTotalAmount = amountsForBuy.reduce(
208
+ (a: bigint, b: bigint) => a + b,
209
+ BigInt(0),
210
+ );
211
+
212
+ if (
213
+ !oswap.checkLiquidity(
214
+ pool,
215
+ state,
216
+ srcToken,
217
+ sellTotalAmount,
218
+ SwapSide.SELL,
219
+ ) ||
220
+ !oswap.checkLiquidity(
221
+ pool,
222
+ state,
223
+ destToken,
224
+ buyTotalAmount,
225
+ SwapSide.BUY,
226
+ )
227
+ ) {
228
+ return DEFAULT_BLOCK_NUMBER;
229
+ }
230
+ return blockNumber;
231
+ }
232
+
233
+ beforeAll(async () => {
234
+ oswap = new OSwap(network, dexKey, dexHelper);
235
+
236
+ blockNumber = await getBlockNumberForTesting(oswap);
237
+ });
238
+
239
+ it('getPoolIdentifiers and getPricesVolume SELL', async function () {
240
+ await testPricingOnNetwork(
241
+ oswap,
242
+ network,
243
+ dexKey,
244
+ blockNumber,
245
+ srcTokenSymbol,
246
+ destTokenSymbol,
247
+ SwapSide.SELL,
248
+ amountsForSell,
249
+ );
250
+ });
251
+
252
+ it('getPoolIdentifiers and getPricesVolume BUY', async function () {
253
+ await testPricingOnNetwork(
254
+ oswap,
255
+ network,
256
+ dexKey,
257
+ blockNumber,
258
+ srcTokenSymbol,
259
+ destTokenSymbol,
260
+ SwapSide.BUY,
261
+ amountsForBuy,
262
+ );
263
+ });
264
+
265
+ it('getTopPoolsForToken', async function () {
266
+ // We have to check without calling initializePricing, because
267
+ // pool-tracker is not calling that function
268
+ const newOSwap = new OSwap(network, dexKey, dexHelper);
269
+ if (newOSwap.updatePoolState) {
270
+ await newOSwap.updatePoolState();
271
+ }
272
+
273
+ const poolLiquidity = await newOSwap.getTopPoolsForToken(
274
+ tokens[srcTokenSymbol].address,
275
+ 10,
276
+ );
277
+
278
+ if (!newOSwap.hasConstantPriceLargeAmounts) {
279
+ checkPoolsLiquidity(
280
+ poolLiquidity,
281
+ Tokens[network][srcTokenSymbol].address,
282
+ dexKey,
283
+ );
284
+ }
285
+ });
286
+ });
287
+ });