@paraswap/dex-lib 2.50.6 → 2.50.7-sdai
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/abi/maker-psm/pot.json +322 -0
- package/build/abi/{wombat/pool.json → sdai/SavingsDai.abi.json} +289 -701
- package/build/config.js +5 -2
- package/build/config.js.map +1 -1
- package/build/dex/dexalot/config.js +7 -0
- package/build/dex/dexalot/config.js.map +1 -1
- package/build/dex/index.js +2 -0
- package/build/dex/index.js.map +1 -1
- package/build/dex/sdai/config.d.ts +11 -0
- package/build/dex/sdai/config.js +24 -0
- package/build/dex/sdai/config.js.map +1 -0
- package/build/dex/sdai/constants.d.ts +2 -0
- package/build/dex/sdai/constants.js +6 -0
- package/build/dex/sdai/constants.js.map +1 -0
- package/build/dex/sdai/scripts/validate-state.js +102 -0
- package/build/dex/sdai/scripts/validate-state.js.map +1 -0
- package/build/dex/sdai/sdai-pool.d.ts +16 -0
- package/build/dex/sdai/sdai-pool.js +85 -0
- package/build/dex/sdai/sdai-pool.js.map +1 -0
- package/build/dex/sdai/sdai.d.ts +51 -0
- package/build/dex/sdai/sdai.js +172 -0
- package/build/dex/sdai/sdai.js.map +1 -0
- package/build/dex/sdai/types.d.ts +21 -0
- package/build/dex/sdai/types.js +11 -0
- package/build/dex/sdai/types.js.map +1 -0
- package/build/dex/sdai/utils.d.ts +4 -0
- package/build/dex/sdai/utils.js +39 -0
- package/build/dex/sdai/utils.js.map +1 -0
- package/package.json +1 -1
- package/src/abi/maker-psm/pot.json +322 -0
- package/src/abi/sdai/SavingsDai.abi.json +877 -0
- package/src/config.ts +5 -2
- package/src/dex/dexalot/config.ts +7 -0
- package/src/dex/dexalot/dexalot-e2e.test.ts +23 -1
- package/src/dex/dexalot/dexalot-integration.test.ts +121 -0
- package/src/dex/index.ts +2 -0
- package/src/dex/sdai/config.ts +28 -0
- package/src/dex/sdai/constants.ts +2 -0
- package/src/dex/sdai/scripts/validate-state.ts +144 -0
- package/src/dex/sdai/sdai-e2e.test.ts +96 -0
- package/src/dex/sdai/sdai-events.test.ts +105 -0
- package/src/dex/sdai/sdai-integration.test.ts +148 -0
- package/src/dex/sdai/sdai-pool.ts +113 -0
- package/src/dex/sdai/sdai.ts +233 -0
- package/src/dex/sdai/types.ts +23 -0
- package/src/dex/sdai/utils.ts +48 -0
- package/tests/constants-e2e.ts +2 -2
- package/.vscode/launch.json +0 -53
- package/.vscode/settings.json +0 -2
- package/.vscode/tasks.json +0 -15
- package/build/abi/uniswap-v3/AlienBaseV3Router.abi.json +0 -52
- package/build/dex/aave-v2/tokens-avalanche.json +0 -44
- package/build/dex/aave-v2/tokens-mainnet.json +0 -188
- package/build/dex/aave-v2/tokens-polygon.json +0 -44
- package/build/dex/solidly-v3/scripts/check-event-pool-event.js +0 -53
- package/build/dex/solidly-v3/scripts/check-event-pool-event.js.map +0 -1
- package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.d.ts +0 -17
- package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js +0 -64
- package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js.map +0 -1
- package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.d.ts +0 -17
- package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js +0 -79
- package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js.map +0 -1
- package/main-config.ts +0 -4484
- /package/build/dex/{solidly-v3/scripts/check-event-pool-event.d.ts → sdai/scripts/validate-state.d.ts} +0 -0
package/src/config.ts
CHANGED
|
@@ -55,8 +55,9 @@ const baseConfigs: { [network: number]: BaseConfig } = {
|
|
|
55
55
|
Adapter03: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366',
|
|
56
56
|
Adapter04: '0x369A2FDb910d432f0a07381a5E3d27572c876713',
|
|
57
57
|
Adapter05: '0x3329dfa55A40B450952FBE0203167Ae6908E656d',
|
|
58
|
+
Adapter06: '0xe9166234DFB6d3ec05C82404109C02Ca82b16c22',
|
|
58
59
|
BuyAdapter: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29',
|
|
59
|
-
BuyAdapter02: '
|
|
60
|
+
BuyAdapter02: '0x40dB7541b0c655a3a70c4713aD6879Ec3861c1FE',
|
|
60
61
|
},
|
|
61
62
|
uniswapV2ExchangeRouterAddress:
|
|
62
63
|
'0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07',
|
|
@@ -288,10 +289,12 @@ const baseConfigs: { [network: number]: BaseConfig } = {
|
|
|
288
289
|
swaapV2AuthToken: process.env.API_KEY_SWAAP_V2_AUTH_TOKEN || '',
|
|
289
290
|
hashFlowDisabledMMs:
|
|
290
291
|
process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [],
|
|
292
|
+
dexalotAuthToken: process.env.API_KEY_DEXALOT_AUTH_TOKEN || '',
|
|
291
293
|
adapterAddresses: {
|
|
292
294
|
ArbitrumAdapter01: '0x369A2FDb910d432f0a07381a5E3d27572c876713',
|
|
293
295
|
ArbitrumAdapter02: '0x58a5f0b73969800FAFf8556cD2187E3FCE71A6cb',
|
|
294
|
-
|
|
296
|
+
ArbitrumAdapter03: '0x97bdD2B98D9802b0e387FefdB2882C1b2dc2c344',
|
|
297
|
+
ArbitrumBuyAdapter: '0x005213c48d4aafFcA0b6D1CbA8710F4D035C18f9',
|
|
295
298
|
},
|
|
296
299
|
uniswapV2ExchangeRouterAddress:
|
|
297
300
|
'0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC',
|
|
@@ -7,6 +7,9 @@ export const DexalotConfig: DexConfigMap<DexParams> = {
|
|
|
7
7
|
[Network.AVALANCHE]: {
|
|
8
8
|
mainnetRFQAddress: '0xEed3c159F3A96aB8d41c8B9cA49EE1e5071A7cdD',
|
|
9
9
|
},
|
|
10
|
+
[Network.ARBITRUM]: {
|
|
11
|
+
mainnetRFQAddress: '0x010224949cCa211Fb5dDfEDD28Dc8Bf9D2990368',
|
|
12
|
+
},
|
|
10
13
|
},
|
|
11
14
|
};
|
|
12
15
|
|
|
@@ -15,4 +18,8 @@ export const Adapters: Record<number, AdapterMappings> = {
|
|
|
15
18
|
[SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 6 }],
|
|
16
19
|
[SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 8 }],
|
|
17
20
|
},
|
|
21
|
+
[Network.ARBITRUM]: {
|
|
22
|
+
[SwapSide.SELL]: [{ name: 'ArbitrumAdapter03', index: 2 }],
|
|
23
|
+
[SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 11 }],
|
|
24
|
+
},
|
|
18
25
|
};
|
|
@@ -196,7 +196,7 @@ describe('Dexalot E2E', () => {
|
|
|
196
196
|
const tokenASymbol: string = 'BTCb';
|
|
197
197
|
const tokenBSymbol: string = 'USDC';
|
|
198
198
|
|
|
199
|
-
const tokenAAmount: string = '
|
|
199
|
+
const tokenAAmount: string = '10000';
|
|
200
200
|
const tokenBAmount: string = '9000000000';
|
|
201
201
|
const nativeTokenAmount = '1000000000000000000';
|
|
202
202
|
|
|
@@ -211,4 +211,26 @@ describe('Dexalot E2E', () => {
|
|
|
211
211
|
true,
|
|
212
212
|
);
|
|
213
213
|
});
|
|
214
|
+
|
|
215
|
+
describe('Arbitrum', () => {
|
|
216
|
+
const network = Network.ARBITRUM;
|
|
217
|
+
|
|
218
|
+
const tokenASymbol: string = 'USDT';
|
|
219
|
+
const tokenBSymbol: string = 'USDC';
|
|
220
|
+
|
|
221
|
+
const tokenAAmount: string = '1000000';
|
|
222
|
+
const tokenBAmount: string = '1000000';
|
|
223
|
+
const nativeTokenAmount = '1000000000000000000';
|
|
224
|
+
|
|
225
|
+
testForNetwork(
|
|
226
|
+
network,
|
|
227
|
+
dexKey,
|
|
228
|
+
tokenASymbol,
|
|
229
|
+
tokenBSymbol,
|
|
230
|
+
tokenAAmount,
|
|
231
|
+
tokenBAmount,
|
|
232
|
+
nativeTokenAmount,
|
|
233
|
+
true,
|
|
234
|
+
);
|
|
235
|
+
});
|
|
214
236
|
});
|
|
@@ -185,4 +185,125 @@ describe('Dexalot', function () {
|
|
|
185
185
|
}
|
|
186
186
|
});
|
|
187
187
|
});
|
|
188
|
+
|
|
189
|
+
describe('Arbitrum', () => {
|
|
190
|
+
const network = Network.ARBITRUM;
|
|
191
|
+
const dexHelper = new DummyDexHelper(network);
|
|
192
|
+
|
|
193
|
+
const tokens = Tokens[network];
|
|
194
|
+
|
|
195
|
+
const tokenASymbol = 'USDT';
|
|
196
|
+
const tokenBSymbol = 'USDC';
|
|
197
|
+
|
|
198
|
+
const amountsForTokenA = [
|
|
199
|
+
0n,
|
|
200
|
+
1n * BI_POWS[tokens[tokenASymbol].decimals],
|
|
201
|
+
2n * BI_POWS[tokens[tokenASymbol].decimals],
|
|
202
|
+
3n * BI_POWS[tokens[tokenASymbol].decimals],
|
|
203
|
+
4n * BI_POWS[tokens[tokenASymbol].decimals],
|
|
204
|
+
5n * BI_POWS[tokens[tokenASymbol].decimals],
|
|
205
|
+
6n * BI_POWS[tokens[tokenASymbol].decimals],
|
|
206
|
+
7n * BI_POWS[tokens[tokenASymbol].decimals],
|
|
207
|
+
8n * BI_POWS[tokens[tokenASymbol].decimals],
|
|
208
|
+
9n * BI_POWS[tokens[tokenASymbol].decimals],
|
|
209
|
+
10n * BI_POWS[tokens[tokenASymbol].decimals],
|
|
210
|
+
];
|
|
211
|
+
|
|
212
|
+
const amountsForTokenB = [
|
|
213
|
+
0n,
|
|
214
|
+
1n * BI_POWS[tokens[tokenBSymbol].decimals],
|
|
215
|
+
2n * BI_POWS[tokens[tokenBSymbol].decimals],
|
|
216
|
+
3n * BI_POWS[tokens[tokenBSymbol].decimals],
|
|
217
|
+
4n * BI_POWS[tokens[tokenBSymbol].decimals],
|
|
218
|
+
5n * BI_POWS[tokens[tokenBSymbol].decimals],
|
|
219
|
+
6n * BI_POWS[tokens[tokenBSymbol].decimals],
|
|
220
|
+
7n * BI_POWS[tokens[tokenBSymbol].decimals],
|
|
221
|
+
8n * BI_POWS[tokens[tokenBSymbol].decimals],
|
|
222
|
+
9n * BI_POWS[tokens[tokenBSymbol].decimals],
|
|
223
|
+
10n * BI_POWS[tokens[tokenBSymbol].decimals],
|
|
224
|
+
];
|
|
225
|
+
|
|
226
|
+
beforeEach(async () => {
|
|
227
|
+
blockNumber = await dexHelper.web3Provider.eth.getBlockNumber();
|
|
228
|
+
dexalot = new Dexalot(network, dexKey, dexHelper);
|
|
229
|
+
await dexalot.initializePricing(blockNumber);
|
|
230
|
+
await sleep(5000);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
afterEach(async () => {
|
|
234
|
+
dexalot.releaseResources();
|
|
235
|
+
await sleep(5000);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it(`getPoolIdentifiers and getPricesVolume SELL ${tokenASymbol} ${tokenBSymbol}`, async function () {
|
|
239
|
+
await testPricingOnNetwork(
|
|
240
|
+
dexalot,
|
|
241
|
+
network,
|
|
242
|
+
dexKey,
|
|
243
|
+
blockNumber,
|
|
244
|
+
tokenASymbol,
|
|
245
|
+
tokenBSymbol,
|
|
246
|
+
SwapSide.SELL,
|
|
247
|
+
amountsForTokenA,
|
|
248
|
+
);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it(`getPoolIdentifiers and getPricesVolume BUY ${tokenASymbol} ${tokenBSymbol}`, async function () {
|
|
252
|
+
await testPricingOnNetwork(
|
|
253
|
+
dexalot,
|
|
254
|
+
network,
|
|
255
|
+
dexKey,
|
|
256
|
+
blockNumber,
|
|
257
|
+
tokenASymbol,
|
|
258
|
+
tokenBSymbol,
|
|
259
|
+
SwapSide.BUY,
|
|
260
|
+
amountsForTokenB,
|
|
261
|
+
);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it(`getPoolIdentifiers and getPricesVolume SELL ${tokenBSymbol} ${tokenASymbol}`, async function () {
|
|
265
|
+
await testPricingOnNetwork(
|
|
266
|
+
dexalot,
|
|
267
|
+
network,
|
|
268
|
+
dexKey,
|
|
269
|
+
blockNumber,
|
|
270
|
+
tokenBSymbol,
|
|
271
|
+
tokenASymbol,
|
|
272
|
+
SwapSide.SELL,
|
|
273
|
+
amountsForTokenB,
|
|
274
|
+
);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it(`getPoolIdentifiers and getPricesVolume BUY ${tokenBSymbol} ${tokenASymbol}`, async function () {
|
|
278
|
+
await testPricingOnNetwork(
|
|
279
|
+
dexalot,
|
|
280
|
+
network,
|
|
281
|
+
dexKey,
|
|
282
|
+
blockNumber,
|
|
283
|
+
tokenBSymbol,
|
|
284
|
+
tokenASymbol,
|
|
285
|
+
SwapSide.BUY,
|
|
286
|
+
amountsForTokenA,
|
|
287
|
+
);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('getTopPoolsForToken', async function () {
|
|
291
|
+
// We have to check without calling initializePricing, because
|
|
292
|
+
// pool-tracker is not calling that function
|
|
293
|
+
const dexalot = new Dexalot(network, dexKey, dexHelper);
|
|
294
|
+
const poolLiquidity = await dexalot.getTopPoolsForToken(
|
|
295
|
+
tokens[tokenASymbol].address,
|
|
296
|
+
10,
|
|
297
|
+
);
|
|
298
|
+
console.log(`${tokenASymbol} Top Pools:`, poolLiquidity);
|
|
299
|
+
|
|
300
|
+
if (!dexalot.hasConstantPriceLargeAmounts) {
|
|
301
|
+
checkPoolsLiquidity(
|
|
302
|
+
poolLiquidity,
|
|
303
|
+
Tokens[network][tokenASymbol].address,
|
|
304
|
+
dexKey,
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
});
|
|
188
309
|
});
|
package/src/dex/index.ts
CHANGED
|
@@ -87,6 +87,7 @@ import { Wombat } from './wombat/wombat';
|
|
|
87
87
|
import { Swell } from './swell/swell';
|
|
88
88
|
import { PharaohV1 } from './solidly/forks-override/pharaohV1';
|
|
89
89
|
import { EtherFi } from './etherfi';
|
|
90
|
+
import { SDai } from './sdai/sdai';
|
|
90
91
|
|
|
91
92
|
const LegacyDexes = [
|
|
92
93
|
CurveV2,
|
|
@@ -170,6 +171,7 @@ const Dexes = [
|
|
|
170
171
|
Wombat,
|
|
171
172
|
Swell,
|
|
172
173
|
PharaohV1,
|
|
174
|
+
SDai,
|
|
173
175
|
];
|
|
174
176
|
|
|
175
177
|
export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder<
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SDaiParams } from './types';
|
|
2
|
+
import { DexConfigMap } from '../../types';
|
|
3
|
+
import { Network } from '../../constants';
|
|
4
|
+
import { SwapSide } from '@paraswap/core';
|
|
5
|
+
|
|
6
|
+
export const SDaiConfig: DexConfigMap<SDaiParams> = {
|
|
7
|
+
SDai: {
|
|
8
|
+
[Network.MAINNET]: {
|
|
9
|
+
sdaiAddress: '0x83F20F44975D03b1b09e64809B757c47f942BEeA',
|
|
10
|
+
daiAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
|
|
11
|
+
potAddress: '0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const Adapters: {
|
|
17
|
+
[chainId: number]: {
|
|
18
|
+
[side: string]: { name: string; index: number }[];
|
|
19
|
+
};
|
|
20
|
+
} = {
|
|
21
|
+
[Network.MAINNET]: {
|
|
22
|
+
// TODO: uncomment this when SDAI integration got deployed
|
|
23
|
+
// [SwapSide.SELL]: [{ name: 'Adapter06', index: 2 }],
|
|
24
|
+
// [SwapSide.BUY]: [{ name: 'BuyAdapter02', index: 5 }],
|
|
25
|
+
[SwapSide.SELL]: [{ name: 'Adapter06', index: 1 }],
|
|
26
|
+
[SwapSide.BUY]: [{ name: 'BuyAdapter02', index: 4 }],
|
|
27
|
+
},
|
|
28
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
dotenv.config();
|
|
4
|
+
|
|
5
|
+
import { Network } from '../../../constants';
|
|
6
|
+
import { DummyDexHelper } from '../../../dex-helper';
|
|
7
|
+
import { SDaiPoolState } from '../types';
|
|
8
|
+
import { BlockHeader } from 'web3-eth';
|
|
9
|
+
import { ethers } from 'ethers';
|
|
10
|
+
import { SDai } from '../sdai';
|
|
11
|
+
import { SDaiConfig } from '../config';
|
|
12
|
+
import { getOnChainState } from '../utils';
|
|
13
|
+
import { Interface } from '@ethersproject/abi';
|
|
14
|
+
import PotAbi from '../../../abi/maker-psm/pot.json';
|
|
15
|
+
|
|
16
|
+
const network = Network.MAINNET;
|
|
17
|
+
const dexKey = 'SDai';
|
|
18
|
+
|
|
19
|
+
const { potAddress } = SDaiConfig[dexKey][network];
|
|
20
|
+
const blockHeaders: Record<number, BlockHeader> = {};
|
|
21
|
+
|
|
22
|
+
const dexHelper = new DummyDexHelper(network);
|
|
23
|
+
const logger = dexHelper.getLogger(dexKey);
|
|
24
|
+
|
|
25
|
+
function preprocessField(value: any): string {
|
|
26
|
+
if (
|
|
27
|
+
typeof value === 'bigint' ||
|
|
28
|
+
typeof value === 'number' ||
|
|
29
|
+
ethers.BigNumber.isBigNumber(value)
|
|
30
|
+
) {
|
|
31
|
+
return value.toString();
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function compareAndLogDifferences<T extends object, Y extends object>(
|
|
37
|
+
obj1: T,
|
|
38
|
+
obj2: Y,
|
|
39
|
+
keyNames: Array<keyof T & keyof Y>,
|
|
40
|
+
checkEachKey = false,
|
|
41
|
+
) {
|
|
42
|
+
let isValid = true;
|
|
43
|
+
let keys = keyNames;
|
|
44
|
+
|
|
45
|
+
if (checkEachKey) {
|
|
46
|
+
// find common keys
|
|
47
|
+
const keys1 = Object.keys(obj1);
|
|
48
|
+
const keys2 = new Set(Object.keys(obj2));
|
|
49
|
+
keys = keys1.filter(key => keys2.has(key)) as Array<keyof T & keyof Y>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (let fieldName of keys) {
|
|
53
|
+
const value1 = preprocessField(obj1[fieldName]);
|
|
54
|
+
const value2 = preprocessField(obj2[fieldName]);
|
|
55
|
+
|
|
56
|
+
if (value1 !== value2) {
|
|
57
|
+
console.log(
|
|
58
|
+
`${fieldName.toString()} mismatch: actual: ${value1} vs pool: ${value2}`,
|
|
59
|
+
);
|
|
60
|
+
isValid = false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return isValid;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function isPoolStateEqualToReal(
|
|
68
|
+
state: SDaiPoolState,
|
|
69
|
+
blockNumber: number,
|
|
70
|
+
) {
|
|
71
|
+
const expected = await getOnChainState(
|
|
72
|
+
dexHelper.multiContract,
|
|
73
|
+
potAddress,
|
|
74
|
+
new Interface(PotAbi),
|
|
75
|
+
blockNumber,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const isValidState = compareAndLogDifferences(state, expected, [
|
|
79
|
+
'rho',
|
|
80
|
+
'dsr',
|
|
81
|
+
'dsr',
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
return isValidState;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function checkPoolStateForBlockRange(
|
|
88
|
+
startBlockNumber: number,
|
|
89
|
+
endBlockNumber: number,
|
|
90
|
+
): Promise<boolean> {
|
|
91
|
+
const network = Network.MAINNET;
|
|
92
|
+
const dexKey = 'SDai';
|
|
93
|
+
const dexHelper = new DummyDexHelper(network);
|
|
94
|
+
|
|
95
|
+
const sdai = new SDai(network, dexKey, dexHelper);
|
|
96
|
+
const pool = await sdai.eventPool;
|
|
97
|
+
|
|
98
|
+
const logsToDispatch = await dexHelper.provider.getLogs({
|
|
99
|
+
fromBlock: startBlockNumber,
|
|
100
|
+
toBlock: endBlockNumber,
|
|
101
|
+
address: potAddress,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
console.log(logsToDispatch.length);
|
|
105
|
+
|
|
106
|
+
// group logs by block number
|
|
107
|
+
const logsByBlockNumber: Record<number, any[]> = {};
|
|
108
|
+
for (let log of logsToDispatch) {
|
|
109
|
+
if (!logsByBlockNumber[log.blockNumber]) {
|
|
110
|
+
logsByBlockNumber[log.blockNumber] = [];
|
|
111
|
+
}
|
|
112
|
+
logsByBlockNumber[log.blockNumber].push(log);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const sortedBlocks = Object.keys(logsByBlockNumber)
|
|
116
|
+
.map(Number)
|
|
117
|
+
.sort((a, b) => Number(a) - Number(b));
|
|
118
|
+
|
|
119
|
+
for (let blockNumber of sortedBlocks) {
|
|
120
|
+
if (!blockHeaders[blockNumber]) {
|
|
121
|
+
blockHeaders[blockNumber] = await dexHelper.web3Provider.eth.getBlock(
|
|
122
|
+
blockNumber,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
await pool?.update(logsByBlockNumber[blockNumber], {
|
|
127
|
+
[blockNumber]: blockHeaders[blockNumber],
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const state = pool?.getState(startBlockNumber) as SDaiPoolState;
|
|
132
|
+
return isPoolStateEqualToReal(state, endBlockNumber);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function main() {
|
|
136
|
+
// use findBreakingBlock to find the block where the state is broken
|
|
137
|
+
// console.log(await findBreakingBlock(startBlockNumber, endBlockNumber));
|
|
138
|
+
// previously broken block 150502863
|
|
139
|
+
console.log(await checkPoolStateForBlockRange(19199247 - 10000, 19199247));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
main()
|
|
143
|
+
.then(() => console.log('Done'))
|
|
144
|
+
.catch(e => console.error(e));
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
dotenv.config();
|
|
3
|
+
|
|
4
|
+
import { testE2E } from '../../../tests/utils-e2e';
|
|
5
|
+
import { Tokens, Holders } from '../../../tests/constants-e2e';
|
|
6
|
+
import { Network, ContractMethod, SwapSide } from '../../constants';
|
|
7
|
+
import { StaticJsonRpcProvider } from '@ethersproject/providers';
|
|
8
|
+
import { generateConfig } from '../../config';
|
|
9
|
+
|
|
10
|
+
function testForNetwork(
|
|
11
|
+
network: Network,
|
|
12
|
+
dexKey: string,
|
|
13
|
+
tokenASymbol: string,
|
|
14
|
+
tokenBSymbol: string,
|
|
15
|
+
tokenAAmount: string,
|
|
16
|
+
tokenBAmount: string,
|
|
17
|
+
) {
|
|
18
|
+
const provider = new StaticJsonRpcProvider(
|
|
19
|
+
generateConfig(network).privateHttpProvider,
|
|
20
|
+
network,
|
|
21
|
+
);
|
|
22
|
+
const tokens = Tokens[network];
|
|
23
|
+
const holders = Holders[network];
|
|
24
|
+
|
|
25
|
+
const sideToContractMethods = new Map([
|
|
26
|
+
[
|
|
27
|
+
SwapSide.SELL,
|
|
28
|
+
[
|
|
29
|
+
ContractMethod.simpleSwap,
|
|
30
|
+
ContractMethod.multiSwap,
|
|
31
|
+
ContractMethod.megaSwap,
|
|
32
|
+
],
|
|
33
|
+
],
|
|
34
|
+
[SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]],
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
describe(`${network}`, () => {
|
|
38
|
+
sideToContractMethods.forEach((contractMethods, side) =>
|
|
39
|
+
describe(`${side}`, () => {
|
|
40
|
+
contractMethods.forEach((contractMethod: ContractMethod) => {
|
|
41
|
+
describe(`${contractMethod}`, () => {
|
|
42
|
+
it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => {
|
|
43
|
+
await testE2E(
|
|
44
|
+
tokens[tokenASymbol],
|
|
45
|
+
tokens[tokenBSymbol],
|
|
46
|
+
holders[tokenASymbol],
|
|
47
|
+
side === SwapSide.SELL ? tokenAAmount : tokenBAmount,
|
|
48
|
+
side,
|
|
49
|
+
dexKey,
|
|
50
|
+
contractMethod,
|
|
51
|
+
network,
|
|
52
|
+
provider,
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => {
|
|
56
|
+
await testE2E(
|
|
57
|
+
tokens[tokenBSymbol],
|
|
58
|
+
tokens[tokenASymbol],
|
|
59
|
+
holders[tokenBSymbol],
|
|
60
|
+
side === SwapSide.SELL ? tokenBAmount : tokenAAmount,
|
|
61
|
+
side,
|
|
62
|
+
dexKey,
|
|
63
|
+
contractMethod,
|
|
64
|
+
network,
|
|
65
|
+
provider,
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
describe('sDAI E2E', () => {
|
|
76
|
+
const dexKey = 'sdai';
|
|
77
|
+
|
|
78
|
+
describe('Mainnet', () => {
|
|
79
|
+
const network = Network.MAINNET;
|
|
80
|
+
|
|
81
|
+
const tokenASymbol: string = 'DAI';
|
|
82
|
+
const tokenBSymbol: string = 'sDAI';
|
|
83
|
+
|
|
84
|
+
const tokenAAmount: string = '1000000000000000000';
|
|
85
|
+
const tokenBAmount: string = '1000000000000000000';
|
|
86
|
+
|
|
87
|
+
testForNetwork(
|
|
88
|
+
network,
|
|
89
|
+
dexKey,
|
|
90
|
+
tokenASymbol,
|
|
91
|
+
tokenBSymbol,
|
|
92
|
+
tokenAAmount,
|
|
93
|
+
tokenBAmount,
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
dotenv.config();
|
|
3
|
+
|
|
4
|
+
import { SDaiEventPool } from './sdai-pool';
|
|
5
|
+
import { SDaiConfig } from './config';
|
|
6
|
+
import { Network } from '../../constants';
|
|
7
|
+
import { DummyDexHelper } from '../../dex-helper/index';
|
|
8
|
+
import { testEventSubscriber } from '../../../tests/utils-events';
|
|
9
|
+
import { SDaiPoolState } from './types';
|
|
10
|
+
|
|
11
|
+
import PotAbi from '../../abi/maker-psm/pot.json';
|
|
12
|
+
import { Interface } from '@ethersproject/abi';
|
|
13
|
+
import _ from 'lodash';
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
README
|
|
17
|
+
======
|
|
18
|
+
|
|
19
|
+
This test script adds unit tests for SDai event based
|
|
20
|
+
system. This is done by fetching the state on-chain before the
|
|
21
|
+
event block, manually pushing the block logs to the event-subscriber,
|
|
22
|
+
comparing the local state with on-chain state.
|
|
23
|
+
|
|
24
|
+
Most of the logic for testing is abstracted by `testEventSubscriber`.
|
|
25
|
+
You need to do two things to make the tests work:
|
|
26
|
+
|
|
27
|
+
1. Fetch the block numbers where certain events were released. You
|
|
28
|
+
can modify the `./scripts/fetch-event-blocknumber.ts` to get the
|
|
29
|
+
block numbers for different events. Make sure to get sufficient
|
|
30
|
+
number of blockNumbers to cover all possible cases for the event
|
|
31
|
+
mutations.
|
|
32
|
+
|
|
33
|
+
2. Complete the implementation for fetchPoolState function. The
|
|
34
|
+
function should fetch the on-chain state of the event subscriber
|
|
35
|
+
using just the blocknumber.
|
|
36
|
+
|
|
37
|
+
The template tests only include the test for a single event
|
|
38
|
+
subscriber. There can be cases where multiple event subscribers
|
|
39
|
+
exist for a single DEX. In such cases additional tests should be
|
|
40
|
+
added.
|
|
41
|
+
|
|
42
|
+
You can run this individual test script by running:
|
|
43
|
+
`npx jest src/dex/<dex-name>/<dex-name>-events.test.ts`
|
|
44
|
+
|
|
45
|
+
(This comment should be removed from the final implementation)
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
jest.setTimeout(50 * 1000);
|
|
49
|
+
const dexKey = 'SDai';
|
|
50
|
+
const network = Network.MAINNET;
|
|
51
|
+
|
|
52
|
+
async function fetchPoolState(
|
|
53
|
+
sdaiPool: SDaiEventPool,
|
|
54
|
+
blockNumber: number,
|
|
55
|
+
): Promise<SDaiPoolState> {
|
|
56
|
+
return sdaiPool.generateState(blockNumber);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
describe('SDai Event', function () {
|
|
60
|
+
const blockNumbers: { [eventName: string]: number[] } = {
|
|
61
|
+
drip: [19827559, 19827524, 19827163, 19827124, 19827000, 19826892],
|
|
62
|
+
// TODO: no matching logs, you have to manually call "file"
|
|
63
|
+
// from "0xbe8e3e3618f7474f8cb1d074a26affef007e98fb" address
|
|
64
|
+
// https://etherscan.io/advanced-filter?fadd=0x197e90f9fad81970ba7976f33cbd77088e5d7cf7&tadd=0x197e90f9fad81970ba7976f33cbd77088e5d7cf7&mtd=0x29ae8114%7eFile
|
|
65
|
+
// file: [19831086]
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const addresses: { [contract: string]: string } = {
|
|
69
|
+
potAddress: SDaiConfig[dexKey][network].potAddress,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
describe('SDaiPool', function () {
|
|
73
|
+
Object.keys(blockNumbers).forEach((event: string) => {
|
|
74
|
+
blockNumbers[event].forEach((blockNumber: number) => {
|
|
75
|
+
it(`Should return the correct state after the ${blockNumber}:${event}`, async function () {
|
|
76
|
+
const dexHelper = new DummyDexHelper(network);
|
|
77
|
+
const logger = dexHelper.getLogger(dexKey);
|
|
78
|
+
|
|
79
|
+
const sdaiPool = new SDaiEventPool(
|
|
80
|
+
dexKey,
|
|
81
|
+
dexHelper,
|
|
82
|
+
addresses.potAddress,
|
|
83
|
+
new Interface(PotAbi),
|
|
84
|
+
logger,
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
await sdaiPool.initialize(blockNumber);
|
|
88
|
+
|
|
89
|
+
await testEventSubscriber(
|
|
90
|
+
sdaiPool,
|
|
91
|
+
sdaiPool.addressesSubscribed,
|
|
92
|
+
(_blockNumber: number) => fetchPoolState(sdaiPool, _blockNumber),
|
|
93
|
+
blockNumber,
|
|
94
|
+
`${dexKey}_${sdaiPool}`,
|
|
95
|
+
dexHelper.provider,
|
|
96
|
+
(state, expected) => {
|
|
97
|
+
// TODO:
|
|
98
|
+
expect(_.omit(state, ['chi'])).toEqual(_.omit(expected, ['chi']));
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|