@paraswap/dex-lib 3.8.35 → 3.8.36-susds

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 (42) hide show
  1. package/build/abi/lite-psm/usdsPsm.json +163 -0
  2. package/build/abi/sdai/SavingsUSDS.abi.json +720 -0
  3. package/build/dex/lite-psm/config.js +5 -1
  4. package/build/dex/lite-psm/config.js.map +1 -1
  5. package/build/dex/lite-psm/lite-psm.d.ts +4 -2
  6. package/build/dex/lite-psm/lite-psm.js +39 -26
  7. package/build/dex/lite-psm/lite-psm.js.map +1 -1
  8. package/build/dex/lite-psm/types.d.ts +2 -2
  9. package/build/dex/spark/config.js +25 -0
  10. package/build/dex/spark/config.js.map +1 -1
  11. package/build/dex/spark/scripts/validate-state.js +1 -1
  12. package/build/dex/spark/scripts/validate-state.js.map +1 -1
  13. package/build/dex/spark/spark-sdai-pool.d.ts +4 -1
  14. package/build/dex/spark/spark-sdai-pool.js +6 -7
  15. package/build/dex/spark/spark-sdai-pool.js.map +1 -1
  16. package/build/dex/spark/spark.d.ts +3 -3
  17. package/build/dex/spark/spark.js +4 -4
  18. package/build/dex/spark/spark.js.map +1 -1
  19. package/build/dex/spark/types.d.ts +6 -0
  20. package/build/dex/spark/types.js.map +1 -1
  21. package/build/dex/spark/utils.d.ts +3 -1
  22. package/build/dex/spark/utils.js +43 -7
  23. package/build/dex/spark/utils.js.map +1 -1
  24. package/build/dex/usual-bond/usual-bond.js +5 -11
  25. package/build/dex/usual-bond/usual-bond.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/abi/lite-psm/usdsPsm.json +163 -0
  28. package/src/abi/sdai/SavingsUSDS.abi.json +720 -0
  29. package/src/dex/lite-psm/config.ts +5 -1
  30. package/src/dex/lite-psm/lite-psm-e2e.test.ts +68 -1
  31. package/src/dex/lite-psm/lite-psm.ts +52 -31
  32. package/src/dex/lite-psm/types.ts +3 -2
  33. package/src/dex/spark/config.ts +24 -0
  34. package/src/dex/spark/scripts/validate-state.ts +1 -0
  35. package/src/dex/spark/spark-e2e.test.ts +28 -9
  36. package/src/dex/spark/spark-events.test.ts +77 -62
  37. package/src/dex/spark/spark-integration.test.ts +141 -7
  38. package/src/dex/spark/spark-sdai-pool.ts +10 -5
  39. package/src/dex/spark/spark.ts +6 -2
  40. package/src/dex/spark/types.ts +6 -0
  41. package/src/dex/spark/utils.ts +83 -19
  42. package/tests/constants-e2e.ts +6 -1
@@ -10,20 +10,20 @@ import { Spark } from './spark';
10
10
 
11
11
  const network = Network.MAINNET;
12
12
 
13
- const SDaiSymbol = 'sDAI';
14
- const SDaiToken = Tokens[network][SDaiSymbol];
15
-
16
- const DaiSymbol = 'DAI';
17
- const DaiToken = Tokens[network][DaiSymbol];
18
-
19
13
  const amounts = [0n, BI_POWS[18], 2000000000000000000n];
20
14
 
21
- const dexKey = 'Spark';
22
15
  const dexHelper = new DummyDexHelper(network);
23
16
  let blocknumber: number;
24
17
  let spark: Spark;
25
18
 
26
19
  describe('Spark', function () {
20
+ const dexKey = 'Spark';
21
+ const SDaiSymbol = 'sDAI';
22
+ const SDaiToken = Tokens[network][SDaiSymbol];
23
+
24
+ const DaiSymbol = 'DAI';
25
+ const DaiToken = Tokens[network][DaiSymbol];
26
+
27
27
  beforeAll(async () => {
28
28
  blocknumber = await dexHelper.web3Provider.eth.getBlockNumber();
29
29
  spark = new Spark(network, dexKey, dexHelper);
@@ -149,3 +149,137 @@ describe('Spark', function () {
149
149
  checkPoolsLiquidity(poolLiquidity, SDaiToken.address, dexKey);
150
150
  });
151
151
  });
152
+
153
+ describe('sUSDS', function () {
154
+ const dexKey = 'sUSDS';
155
+ const SDaiSymbol = 'USDS';
156
+ const SDaiToken = Tokens[network][SDaiSymbol];
157
+
158
+ const DaiSymbol = 'sUSDS';
159
+ const DaiToken = Tokens[network][DaiSymbol];
160
+
161
+ beforeAll(async () => {
162
+ blocknumber = await dexHelper.web3Provider.eth.getBlockNumber();
163
+ spark = new Spark(network, dexKey, dexHelper);
164
+ if (spark.initializePricing) {
165
+ await spark.initializePricing(blocknumber);
166
+ }
167
+ });
168
+
169
+ it('getPoolIdentifiers and getPricesVolume USDS -> sUSDS SELL', async function () {
170
+ const pools = await spark.getPoolIdentifiers(
171
+ DaiToken,
172
+ SDaiToken,
173
+ SwapSide.SELL,
174
+ blocknumber,
175
+ );
176
+ console.log(`${DaiSymbol} <> ${SDaiSymbol} Pool Identifiers: `, pools);
177
+
178
+ expect(pools.length).toBeGreaterThan(0);
179
+
180
+ const poolPrices = await spark.getPricesVolume(
181
+ DaiToken,
182
+ SDaiToken,
183
+ amounts,
184
+ SwapSide.SELL,
185
+ blocknumber,
186
+ pools,
187
+ );
188
+ console.log(`${DaiSymbol} <> ${SDaiSymbol} Pool Prices: `, poolPrices);
189
+
190
+ expect(poolPrices).not.toBeNull();
191
+ checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey);
192
+ });
193
+
194
+ it('getPoolIdentifiers and getPricesVolume sUSDS -> USDS SELL', async function () {
195
+ const pools = await spark.getPoolIdentifiers(
196
+ SDaiToken,
197
+ DaiToken,
198
+ SwapSide.SELL,
199
+ blocknumber,
200
+ );
201
+ console.log(`${SDaiSymbol} <> ${DaiSymbol} Pool Identifiers: `, pools);
202
+
203
+ expect(pools.length).toBeGreaterThan(0);
204
+
205
+ const poolPrices = await spark.getPricesVolume(
206
+ SDaiToken,
207
+ DaiToken,
208
+ amounts,
209
+ SwapSide.SELL,
210
+ blocknumber,
211
+ pools,
212
+ );
213
+ console.log(`${SDaiSymbol} <> ${DaiSymbol} Pool Prices: `, poolPrices);
214
+
215
+ expect(poolPrices).not.toBeNull();
216
+ checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey);
217
+ });
218
+
219
+ it('getPoolIdentifiers and getPricesVolume USDS -> sUSDS BUY', async function () {
220
+ const pools = await spark.getPoolIdentifiers(
221
+ DaiToken,
222
+ SDaiToken,
223
+ SwapSide.BUY,
224
+ blocknumber,
225
+ );
226
+ console.log(`${DaiSymbol} <> ${SDaiSymbol} Pool Identifiers: `, pools);
227
+
228
+ expect(pools.length).toBeGreaterThan(0);
229
+
230
+ const poolPrices = await spark.getPricesVolume(
231
+ DaiToken,
232
+ SDaiToken,
233
+ amounts,
234
+ SwapSide.BUY,
235
+ blocknumber,
236
+ pools,
237
+ );
238
+ console.log(`${DaiSymbol} <> ${SDaiSymbol} Pool Prices: `, poolPrices);
239
+
240
+ expect(poolPrices).not.toBeNull();
241
+ checkPoolPrices(poolPrices!, amounts, SwapSide.BUY, dexKey);
242
+ });
243
+
244
+ it('getPoolIdentifiers and getPricesVolume sUSDS -> USDS BUY', async function () {
245
+ const pools = await spark.getPoolIdentifiers(
246
+ SDaiToken,
247
+ DaiToken,
248
+ SwapSide.BUY,
249
+ blocknumber,
250
+ );
251
+ console.log(`${SDaiSymbol} <> ${DaiSymbol} Pool Identifiers: `, pools);
252
+
253
+ expect(pools.length).toBeGreaterThan(0);
254
+
255
+ const poolPrices = await spark.getPricesVolume(
256
+ SDaiToken,
257
+ DaiToken,
258
+ amounts,
259
+ SwapSide.BUY,
260
+ blocknumber,
261
+ pools,
262
+ );
263
+ console.log(`${SDaiSymbol} <> ${DaiSymbol} Pool Prices: `, poolPrices);
264
+
265
+ expect(poolPrices).not.toBeNull();
266
+ checkPoolPrices(poolPrices!, amounts, SwapSide.BUY, dexKey);
267
+ });
268
+
269
+ it('USDS getTopPoolsForToken', async function () {
270
+ const poolLiquidity = await spark.getTopPoolsForToken(DaiToken.address, 10);
271
+ console.log(`${DaiSymbol} Top Pools:`, poolLiquidity);
272
+
273
+ checkPoolsLiquidity(poolLiquidity, DaiToken.address, dexKey);
274
+ });
275
+
276
+ it('sUSDS getTopPoolsForToken', async function () {
277
+ const poolLiquidity = await spark.getTopPoolsForToken(
278
+ SDaiToken.address,
279
+ 10,
280
+ );
281
+ console.log(`${SDaiSymbol} Top Pools:`, poolLiquidity);
282
+
283
+ checkPoolsLiquidity(poolLiquidity, SDaiToken.address, dexKey);
284
+ });
285
+ });
@@ -7,6 +7,8 @@ import type { AsyncOrSync, DeepReadonly } from 'ts-essentials';
7
7
  import type { Address, BlockHeader, Log, Logger } from '../../types';
8
8
  import type { SparkSDaiPoolState } from './types';
9
9
  import { getOnChainState } from './utils';
10
+ import { SDaiConfig } from './config';
11
+ import { Network } from '../../constants';
10
12
 
11
13
  const RAY = BI_POWS[27];
12
14
  const ZERO = BigInt(0);
@@ -17,10 +19,6 @@ const HALF = RAY / TWO;
17
19
  const FILE_TOPICHASH = `0x29ae811400000000000000000000000000000000000000000000000000000000`;
18
20
  // function drip()
19
21
  const DRIP_TOPICHASH = `0x9f678cca00000000000000000000000000000000000000000000000000000000`;
20
- // function cage()
21
- const CAGE_TOPICHASH = `0x6924500900000000000000000000000000000000000000000000000000000000`;
22
- // bytes32 repr of "dsr" string
23
- const DSR_TOPIC = `0x6473720000000000000000000000000000000000000000000000000000000000`;
24
22
 
25
23
  const rpow = (x: bigint, n: bigint): bigint => {
26
24
  if (!x && !n) return RAY;
@@ -54,11 +52,14 @@ const calcChi = (state: SparkSDaiPoolState, currentTimestamp?: number) => {
54
52
  export class SparkSDaiEventPool extends StatefulEventSubscriber<SparkSDaiPoolState> {
55
53
  constructor(
56
54
  parentName: string,
55
+ network: Network,
57
56
  poolName: string,
58
57
  protected dexHelper: IDexHelper,
59
58
  private potAddress: Address,
60
59
  private potInterface: Interface,
61
60
  logger: Logger,
61
+ private savingsRateTopic: string,
62
+ private savingsRateSymbol: 'ssr' | 'dsr',
62
63
  ) {
63
64
  super(parentName, poolName, dexHelper, logger);
64
65
  this.addressesSubscribed = [potAddress];
@@ -69,7 +70,10 @@ export class SparkSDaiEventPool extends StatefulEventSubscriber<SparkSDaiPoolSta
69
70
  log: Readonly<Log>,
70
71
  blockHeader: Readonly<BlockHeader>,
71
72
  ): AsyncOrSync<DeepReadonly<SparkSDaiPoolState> | null> {
72
- if (log.topics[0] === FILE_TOPICHASH && log.topics[2] === DSR_TOPIC) {
73
+ if (
74
+ log.topics[0] === FILE_TOPICHASH &&
75
+ log.topics[2] === this.savingsRateTopic
76
+ ) {
73
77
  return {
74
78
  ...state,
75
79
  dsr: BigInt(log.topics[3]).toString(),
@@ -94,6 +98,7 @@ export class SparkSDaiEventPool extends StatefulEventSubscriber<SparkSDaiPoolSta
94
98
  this.dexHelper.multiContract,
95
99
  this.potAddress,
96
100
  this.potInterface,
101
+ this.savingsRateSymbol,
97
102
  blockNumber,
98
103
  );
99
104
  }
@@ -47,20 +47,24 @@ export class Spark
47
47
  readonly daiAddress: string = SDaiConfig[dexKey][network].daiAddress,
48
48
  readonly sdaiAddress: string = SDaiConfig[dexKey][network].sdaiAddress,
49
49
  readonly potAddress: string = SDaiConfig[dexKey][network].potAddress,
50
+ readonly abiInterface: Interface = SDaiConfig[dexKey][network]
51
+ .poolInterface,
50
52
 
51
53
  protected adapters = Adapters[network] || {},
52
54
  protected sdaiInterface = new Interface(SavingsDaiAbi),
53
- protected potInterface = new Interface(PotAbi),
54
55
  ) {
55
56
  super(dexHelper, dexKey);
56
57
  this.logger = dexHelper.getLogger(dexKey);
57
58
  this.eventPool = new SparkSDaiEventPool(
58
59
  this.dexKey,
60
+ this.network,
59
61
  `${this.daiAddress}_${this.sdaiAddress}`,
60
62
  dexHelper,
61
63
  this.potAddress,
62
- this.potInterface,
64
+ this.abiInterface,
63
65
  this.logger,
66
+ SDaiConfig[dexKey][network].savingsRate.topic,
67
+ SDaiConfig[dexKey][network].savingsRate.symbol,
64
68
  );
65
69
  }
66
70
 
@@ -1,3 +1,4 @@
1
+ import { Interface } from '@ethersproject/abi';
1
2
  import { Address } from '../../types';
2
3
 
3
4
  export type SparkData = { exchange: Address };
@@ -6,6 +7,11 @@ export type SparkParams = {
6
7
  sdaiAddress: Address;
7
8
  daiAddress: Address;
8
9
  potAddress: Address;
10
+ savingsRate: {
11
+ symbol: 'dsr' | 'ssr';
12
+ topic: string;
13
+ };
14
+ poolInterface: Interface;
9
15
  };
10
16
 
11
17
  export enum SparkSDaiFunctions {
@@ -4,34 +4,60 @@ import { Interface, AbiCoder } from '@ethersproject/abi';
4
4
 
5
5
  const coder = new AbiCoder();
6
6
 
7
- // - `dsr`: the Dai Savings Rate
7
+ // - `dsr` || `ssr`: the Dai Savings Rate or USDS savings rate
8
8
  // - `chi`: the Rate Accumulator
9
9
  // - `rho`: time of last drip
10
10
  export async function getOnChainState(
11
11
  multiContract: Contract,
12
12
  potAddress: string,
13
13
  potInterface: Interface,
14
+ savingsRateSymbol: 'dsr' | 'ssr',
14
15
  blockNumber: number | 'latest',
15
16
  ): Promise<SparkSDaiPoolState> {
17
+ if (savingsRateSymbol === 'dsr') {
18
+ return getOnChainStateSDAI(
19
+ multiContract,
20
+ potAddress,
21
+ potInterface,
22
+ blockNumber,
23
+ );
24
+ }
25
+
26
+ return getOnChainStateUSDS(
27
+ multiContract,
28
+ potAddress,
29
+ potInterface,
30
+ blockNumber,
31
+ );
32
+ }
33
+
34
+ export async function getOnChainStateSDAI(
35
+ multiContract: Contract,
36
+ potAddress: string,
37
+ potInterface: Interface,
38
+ blockNumber: number | 'latest',
39
+ ): Promise<SparkSDaiPoolState> {
40
+ const calls = [
41
+ {
42
+ target: potAddress,
43
+ callData: potInterface.encodeFunctionData('dsr', []),
44
+ },
45
+ {
46
+ target: potAddress,
47
+ callData: potInterface.encodeFunctionData('chi', []),
48
+ },
49
+ {
50
+ target: potAddress,
51
+ callData: potInterface.encodeFunctionData('rho', []),
52
+ },
53
+ {
54
+ target: potAddress,
55
+ callData: potInterface.encodeFunctionData('live', []),
56
+ },
57
+ ];
58
+
16
59
  const data: { returnData: any[] } = await multiContract.methods
17
- .aggregate([
18
- {
19
- target: potAddress,
20
- callData: potInterface.encodeFunctionData('dsr', []),
21
- },
22
- {
23
- target: potAddress,
24
- callData: potInterface.encodeFunctionData('chi', []),
25
- },
26
- {
27
- target: potAddress,
28
- callData: potInterface.encodeFunctionData('rho', []),
29
- },
30
- {
31
- target: potAddress,
32
- callData: potInterface.encodeFunctionData('live', []),
33
- },
34
- ])
60
+ .aggregate(calls)
35
61
  .call({}, blockNumber);
36
62
 
37
63
  const [dsr, chi, rho, live] = data.returnData.map(item =>
@@ -45,3 +71,41 @@ export async function getOnChainState(
45
71
  rho,
46
72
  };
47
73
  }
74
+
75
+ export async function getOnChainStateUSDS(
76
+ multiContract: Contract,
77
+ potAddress: string,
78
+ potInterface: Interface,
79
+ blockNumber: number | 'latest',
80
+ ): Promise<SparkSDaiPoolState> {
81
+ const calls = [
82
+ {
83
+ target: potAddress,
84
+ callData: potInterface.encodeFunctionData('ssr', []),
85
+ },
86
+ {
87
+ target: potAddress,
88
+ callData: potInterface.encodeFunctionData('chi', []),
89
+ },
90
+ {
91
+ target: potAddress,
92
+ callData: potInterface.encodeFunctionData('rho', []),
93
+ },
94
+ ];
95
+
96
+ const data: { returnData: any[] } = await multiContract.methods
97
+ .aggregate(calls)
98
+ .call({}, blockNumber);
99
+
100
+ const [dsr, chi, rho] = data.returnData.map(item =>
101
+ coder.decode(['uint256'], item)[0].toString(),
102
+ );
103
+
104
+ return {
105
+ // 'hack' - sUSDS doesn't have global shutdown and no notion of `live`, so it's always `live`
106
+ live: true,
107
+ dsr,
108
+ chi,
109
+ rho,
110
+ };
111
+ }
@@ -19,6 +19,10 @@ export const Tokens: {
19
19
  [network: number]: { [symbol: string]: SmartTokenParams };
20
20
  } = {
21
21
  [Network.MAINNET]: {
22
+ sUSDS: {
23
+ address: '0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD',
24
+ decimals: 18,
25
+ },
22
26
  USDS: {
23
27
  address: '0xdC035D45d973E3EC169d2276DDab16f1e407384F',
24
28
  decimals: 18,
@@ -1500,7 +1504,8 @@ export const Holders: {
1500
1504
  [network: number]: { [tokenAddress: string]: Address };
1501
1505
  } = {
1502
1506
  [Network.MAINNET]: {
1503
- USDS: '0xE99d0ba6966c74BF78bF394BD29DCA154c6BC217',
1507
+ USDS: '0xB1796E8f1eEcF23027c1E3C00fE303629A189d10',
1508
+ sUSDS: '0xd564B3aE673CAa49D054Bf185bD72a6853763eE7',
1504
1509
  SKY: '0x0ddda327A6614130CCb20bc0097313A282176A01',
1505
1510
  MKR: '0xe9aAA7A9DDc0877626C1779AbC29993aD89A6c1f',
1506
1511
  // Idle tokens