@dhedge/v2-sdk 2.1.8 → 2.2.0

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 (91) hide show
  1. package/README.md +400 -53
  2. package/dist/config.d.ts +13 -2
  3. package/dist/entities/pool.d.ts +25 -86
  4. package/dist/entities/utils.d.ts +15 -0
  5. package/dist/services/hyperliquid/index.d.ts +22 -0
  6. package/dist/services/kyberSwap/index.d.ts +1 -1
  7. package/dist/services/oneInch/index.d.ts +1 -1
  8. package/dist/services/toros/easySwapper.d.ts +14 -0
  9. package/dist/services/toros/swapData.d.ts +5 -5
  10. package/dist/services/uniswap/V3Liquidity.d.ts +2 -2
  11. package/dist/services/velodrome/liquidity.d.ts +3 -0
  12. package/dist/test/constants.d.ts +48 -3
  13. package/dist/test/utils/testingHelper.d.ts +4 -0
  14. package/dist/types.d.ts +19 -4
  15. package/dist/utils/contract.d.ts +20 -0
  16. package/dist/v2-sdk.cjs.development.js +4996 -6742
  17. package/dist/v2-sdk.cjs.development.js.map +1 -1
  18. package/dist/v2-sdk.cjs.production.min.js +1 -1
  19. package/dist/v2-sdk.cjs.production.min.js.map +1 -1
  20. package/dist/v2-sdk.esm.js +5001 -6742
  21. package/dist/v2-sdk.esm.js.map +1 -1
  22. package/package.json +1 -1
  23. package/src/abi/PoolFactory.json +414 -204
  24. package/src/abi/PoolLogic.json +160 -134
  25. package/src/config.ts +13 -8
  26. package/src/entities/pool.ts +46 -253
  27. package/src/entities/utils.ts +15 -0
  28. package/src/services/hyperliquid/index.ts +22 -0
  29. package/src/services/kyberSwap/index.ts +5 -3
  30. package/src/services/oneInch/index.ts +5 -4
  31. package/src/services/toros/completeWithdrawal.ts +57 -40
  32. package/src/services/toros/easySwapper.ts +15 -1
  33. package/src/services/toros/initWithdrawal.ts +39 -31
  34. package/src/services/toros/swapData.ts +45 -131
  35. package/src/services/uniswap/V3Liquidity.ts +3 -24
  36. package/src/services/velodrome/liquidity.ts +3 -0
  37. package/src/test/aave.test.ts +99 -70
  38. package/src/test/aerodrome.test.ts +53 -24
  39. package/src/test/aerodromeCL.test.ts +64 -30
  40. package/src/test/arrakis.test.ts +23 -35
  41. package/src/test/balancer.test.ts +114 -106
  42. package/src/test/compoundV3.test.ts +45 -29
  43. package/src/test/constants.ts +56 -11
  44. package/src/test/cowswap.test.ts +33 -35
  45. package/src/test/dhedge.test.ts +45 -12
  46. package/src/test/flatmoney.test.ts +25 -39
  47. package/src/test/fluid.test.ts +33 -24
  48. package/src/test/hyperliquid.onchain.test.ts +131 -0
  49. package/src/test/kyberSwap.test.ts +37 -16
  50. package/src/test/lyra.test.ts +159 -150
  51. package/src/test/odos.test.ts +2 -2
  52. package/src/test/oneInch.test.ts +36 -22
  53. package/src/test/pancakeCL.test.ts +72 -31
  54. package/src/test/pendle.test.ts +94 -54
  55. package/src/test/{pendleMint.test.ts → pendleMint.onchain.test.ts} +22 -8
  56. package/src/test/pool.test.ts +152 -95
  57. package/src/test/toros.onchain.test.ts +92 -0
  58. package/src/test/toros.test.ts +74 -20
  59. package/src/test/torosLimitOrder.test.ts +87 -42
  60. package/src/test/uniswap.test.ts +77 -128
  61. package/src/test/utils/testingHelper.ts +120 -0
  62. package/src/test/velodrome.test.ts +126 -92
  63. package/src/test/velodromeCL.test.ts +43 -31
  64. package/src/test/velodromeV2.test.ts +153 -95
  65. package/src/types.ts +20 -5
  66. package/src/utils/contract.ts +20 -0
  67. package/dist/services/futures/constants.d.ts +0 -1
  68. package/dist/services/futures/index.d.ts +0 -2
  69. package/dist/services/futures/margin.d.ts +0 -2
  70. package/dist/services/futures/trade.d.ts +0 -3
  71. package/dist/services/ramses/vesting.d.ts +0 -4
  72. package/dist/services/uniswap/V3Trade.d.ts +0 -3
  73. package/dist/test/utils/futures.d.ts +0 -2
  74. package/src/abi/IRamsesNonfungiblePositionManager.json +0 -486
  75. package/src/abi/ISynthetiXFuturesMarketV2.json +0 -531
  76. package/src/abi/ISynthetix.json +0 -139
  77. package/src/abi/IUniswapV3Quoter.json +0 -195
  78. package/src/abi/IUniswapV3Router.json +0 -221
  79. package/src/abi/IXRam.json +0 -99
  80. package/src/services/futures/constants.ts +0 -1
  81. package/src/services/futures/index.ts +0 -2
  82. package/src/services/futures/margin.ts +0 -10
  83. package/src/services/futures/trade.ts +0 -32
  84. package/src/services/ramses/vesting.ts +0 -24
  85. package/src/services/uniswap/V3Trade.ts +0 -46
  86. package/src/test/futures.test.ts +0 -51
  87. package/src/test/hyperliquid.test.ts +0 -107
  88. package/src/test/ramses.test.ts +0 -190
  89. package/src/test/ramsesCL.test.ts +0 -155
  90. package/src/test/synthetix.test.ts +0 -36
  91. package/src/test/utils/futures.ts +0 -14
@@ -9,6 +9,8 @@ import {
9
9
  } from "../constants";
10
10
  import { Pool } from "../../entities";
11
11
  import AssetHandler from "../../abi/AssetHandler.json";
12
+ import PoolLogicAbi from "../../abi/PoolLogic.json";
13
+ import PoolManagerLogicAbi from "../../abi/PoolManagerLogic.json";
12
14
 
13
15
  export type TestingRunParams = {
14
16
  network: Network;
@@ -146,6 +148,124 @@ export const runWithImpersonateAccount = async (
146
148
  await provider.send("hardhat_stopImpersonatingAccount", [account]);
147
149
  };
148
150
 
151
+ // Fixes oracle staleness reverts on hardhat forks for ChainlinkPythPriceAggregator and PythPriceAggregator.
152
+ // These aggregators have their own maxAge staleness checks separate from the AssetHandler's chainlinkTimeout.
153
+ // This function dynamically finds all such aggregators for a pool's supported assets and overrides
154
+ // their maxAge fields to max uint32 (0xffffffff, ~136 years).
155
+ //
156
+ // Slot layouts below are written in big-endian hex order (high-order bytes first), matching the 64-char
157
+ // string returned by eth_getStorageAt. Within a packed slot, Solidity lays fields out from the low-order
158
+ // end in declaration order — so the first declared field ends up on the right side of the hex string.
159
+ //
160
+ // ChainlinkPythPriceAggregator storage layout:
161
+ // slot 0: asset (address)
162
+ // slot 1: oracleData.onchainOracle = [8 bytes padding][4 bytes maxAge][20 bytes oracleContract]
163
+ // → maxAge at hex offset 16
164
+ // slot 2: oracleData.offchainOracle.priceId (bytes32)
165
+ // slot 3: oracleData.offchainOracle = [24 bytes padding][4 bytes maxAge][4 bytes minConfidenceRatio]
166
+ // → maxAge at hex offset 48
167
+ //
168
+ // PythPriceAggregator storage layout:
169
+ // slot 0: asset (address)
170
+ // slot 1: oracleData.priceId (bytes32)
171
+ // slot 2: oracleData = [24 bytes padding][4 bytes maxAge][4 bytes minConfidenceRatio]
172
+ // → maxAge at hex offset 48
173
+ const MAX_UINT32_HEX = "ffffffff";
174
+
175
+ const overrideMaxAgeInSlot = async (
176
+ provider: ethers.providers.JsonRpcProvider,
177
+ contractAddress: string,
178
+ slotIndex: string,
179
+ maxAgeHexOffset: number // character offset of maxAge within the 64-char hex string
180
+ ): Promise<void> => {
181
+ const slot: string = await provider.send("eth_getStorageAt", [
182
+ contractAddress,
183
+ slotIndex,
184
+ "latest"
185
+ ]);
186
+ const hex = slot.slice(2); // remove 0x
187
+ const newHex =
188
+ hex.slice(0, maxAgeHexOffset) +
189
+ MAX_UINT32_HEX +
190
+ hex.slice(maxAgeHexOffset + 8);
191
+ await provider.send("hardhat_setStorageAt", [
192
+ contractAddress,
193
+ slotIndex,
194
+ "0x" + newHex
195
+ ]);
196
+ };
197
+
198
+ export const fixOracleAggregatorStaleness = async ({
199
+ pool,
200
+ provider
201
+ }: {
202
+ pool: Pool;
203
+ provider: ethers.providers.JsonRpcProvider;
204
+ }): Promise<void> => {
205
+ const assetHandlerAddress = await pool.factory.callStatic.getAssetHandler();
206
+ const assetHandlerContract = new Contract(
207
+ assetHandlerAddress,
208
+ AssetHandler.abi,
209
+ provider
210
+ );
211
+
212
+ // Resolve managerLogic from poolLogic to support both isDhedge=true and isDhedge=false pools
213
+ const poolLogic = new Contract(pool.address, PoolLogicAbi.abi, provider);
214
+ const managerLogicAddress: string = await poolLogic.poolManagerLogic();
215
+ const managerLogic = new Contract(
216
+ managerLogicAddress,
217
+ PoolManagerLogicAbi.abi,
218
+ provider
219
+ );
220
+ const supportedAssets: {
221
+ asset: string;
222
+ }[] = await managerLogic.getSupportedAssets();
223
+
224
+ // ABI fragments to detect aggregator type
225
+ const chainlinkPythAbi = [
226
+ "function oracleData() view returns (address oracleContract, uint32 maxAge)"
227
+ ];
228
+ const pythAbi = [
229
+ "function oracleData() view returns (bytes32 priceId, uint32 maxAge, uint32 minConfidenceRatio)"
230
+ ];
231
+
232
+ for (const { asset } of supportedAssets) {
233
+ try {
234
+ const aggregatorAddress: string = await assetHandlerContract.priceAggregators(
235
+ asset
236
+ );
237
+ if (aggregatorAddress === ethers.constants.AddressZero) continue;
238
+
239
+ // Try ChainlinkPythPriceAggregator first (has onchainOracle + offchainOracle)
240
+ const agg = new Contract(aggregatorAddress, chainlinkPythAbi, provider);
241
+ try {
242
+ await agg.oracleData();
243
+ // ChainlinkPythPriceAggregator detected.
244
+ // Slot 1 layout: [8 bytes padding][4 bytes maxAge][20 bytes oracleContract] → maxAge at offset 16
245
+ await overrideMaxAgeInSlot(provider, aggregatorAddress, "0x1", 16);
246
+ // Slot 3 layout: [24 bytes padding][4 bytes maxAge][4 bytes minConfidenceRatio] → maxAge at offset 48
247
+ await overrideMaxAgeInSlot(provider, aggregatorAddress, "0x3", 48);
248
+ continue;
249
+ } catch {
250
+ // Not a ChainlinkPythPriceAggregator
251
+ }
252
+
253
+ // Try PythPriceAggregator (has only offchainOracle)
254
+ const pythAgg = new Contract(aggregatorAddress, pythAbi, provider);
255
+ try {
256
+ await pythAgg.oracleData();
257
+ // PythPriceAggregator detected.
258
+ // Slot 2 layout: [24 bytes padding][4 bytes maxAge][4 bytes minConfidenceRatio] → maxAge at offset 48
259
+ await overrideMaxAgeInSlot(provider, aggregatorAddress, "0x2", 48);
260
+ } catch {
261
+ // Not a PythPriceAggregator either — skip
262
+ }
263
+ } catch {
264
+ // No aggregator set for this asset — skip
265
+ }
266
+ }
267
+ };
268
+
149
269
  export const setChainlinkTimeout = async (
150
270
  {
151
271
  pool,
@@ -4,111 +4,145 @@ import { Dhedge, Pool } from "..";
4
4
  import { routerAddress } from "../config";
5
5
  import { Dapp, Network } from "../types";
6
6
  import { CONTRACT_ADDRESS, MAX_AMOUNT, TEST_POOL } from "./constants";
7
+ import {
8
+ TestingRunParams,
9
+ fixOracleAggregatorStaleness,
10
+ runWithImpersonateAccount,
11
+ setChainlinkTimeout,
12
+ testingHelper
13
+ } from "./utils/testingHelper";
7
14
  import { allowanceDelta, balanceDelta } from "./utils/token";
8
15
 
9
- import { wallet } from "./wallet";
10
-
11
16
  const USDC_SUSD_Lp = "0xd16232ad60188b68076a235c65d692090caba155";
12
17
  const USDC_SUSD_Gauge = "0xb03f52d2db3e758dd49982defd6aeefea9454e80";
13
- const network = Network.OPTIMISM;
14
- const SUSD = CONTRACT_ADDRESS[network].SUSD;
15
- const USDC = CONTRACT_ADDRESS[network].USDC;
16
18
 
17
- let dhedge: Dhedge;
18
- let pool: Pool;
19
- jest.setTimeout(100000);
19
+ const testVelodrome = ({ wallet, network, provider }: TestingRunParams) => {
20
+ const SUSD = CONTRACT_ADDRESS[network].SUSD;
21
+ const USDC = CONTRACT_ADDRESS[network].USDC;
20
22
 
21
- describe("pool", () => {
22
- beforeAll(async () => {
23
- dhedge = new Dhedge(wallet, network);
24
- pool = await dhedge.loadPool(TEST_POOL[network]);
25
- });
23
+ let dhedge: Dhedge;
24
+ let pool: Pool;
25
+ jest.setTimeout(100000);
26
26
 
27
- it("approves unlimited sUSD and USDC on for Velodrome", async () => {
28
- await pool.approve(Dapp.VELODROME, SUSD, MAX_AMOUNT);
29
- await pool.approve(Dapp.VELODROME, USDC, MAX_AMOUNT);
30
- const UsdcAllowanceDelta = await allowanceDelta(
31
- pool.address,
32
- USDC,
33
- routerAddress[network].velodrome!,
34
- pool.signer
35
- );
36
- await expect(UsdcAllowanceDelta.gt(0));
37
- });
27
+ describe(`pool on ${network}`, () => {
28
+ beforeAll(async () => {
29
+ await provider.send("hardhat_setBalance", [
30
+ wallet.address,
31
+ "0x10000000000000000"
32
+ ]);
33
+ dhedge = new Dhedge(wallet, network);
34
+ pool = await dhedge.loadPool(TEST_POOL[network]);
38
35
 
39
- it("adds USDC and SUSD to a Velodrome stable pool", async () => {
40
- await pool.addLiquidityVelodrome(
41
- USDC,
42
- SUSD,
43
- (5 * 1e6).toString(),
44
- (5 * 1e18).toString(),
45
- true
46
- );
36
+ await setChainlinkTimeout({ pool, provider }, 86400 * 365);
37
+ await fixOracleAggregatorStaleness({ pool, provider });
47
38
 
48
- const lpTokenDelta = await balanceDelta(
49
- pool.address,
50
- USDC_SUSD_Lp,
51
- pool.signer
52
- );
53
- expect(lpTokenDelta.gt(0));
54
- });
39
+ await runWithImpersonateAccount(
40
+ { provider, account: await pool.managerLogic.manager() },
41
+ async ({ signer }) => {
42
+ await pool.managerLogic.connect(signer).setTrader(wallet.address);
43
+ await pool.managerLogic.connect(signer).changeAssets(
44
+ [
45
+ [USDC, true],
46
+ [SUSD, true],
47
+ [USDC_SUSD_Lp, false]
48
+ ],
49
+ []
50
+ );
51
+ }
52
+ );
53
+ });
55
54
 
56
- it("should stake USDC-sUSD LP in a gauge", async () => {
57
- const balance = await dhedge.utils.getBalance(USDC_SUSD_Lp, pool.address);
58
- await pool.approveSpender(USDC_SUSD_Gauge, USDC_SUSD_Lp, MAX_AMOUNT);
59
- await pool.stakeInGauge(Dapp.VELODROME, USDC_SUSD_Gauge, balance);
60
- const gaugeBalance = await balanceDelta(
61
- pool.address,
62
- USDC_SUSD_Lp,
63
- pool.signer
64
- );
65
- expect(gaugeBalance.gt(0));
66
- });
55
+ it("approves unlimited sUSD and USDC on for Velodrome", async () => {
56
+ await pool.approve(Dapp.VELODROME, SUSD, MAX_AMOUNT);
57
+ await pool.approve(Dapp.VELODROME, USDC, MAX_AMOUNT);
58
+ const UsdcAllowanceDelta = await allowanceDelta(
59
+ pool.address,
60
+ USDC,
61
+ routerAddress[network].velodrome!,
62
+ pool.signer
63
+ );
64
+ expect(UsdcAllowanceDelta.gt(0)).toBe(true);
65
+ });
67
66
 
68
- it("should claim rewards from Gauge", async () => {
69
- const tx = await pool.claimFees(Dapp.VELODROME, USDC_SUSD_Gauge);
70
- expect(tx).not.toBe(null);
71
- });
67
+ it("adds USDC and SUSD to a Velodrome stable pool", async () => {
68
+ await pool.addLiquidityVelodrome(
69
+ USDC,
70
+ SUSD,
71
+ (5 * 1e6).toString(),
72
+ (5 * 1e18).toString(),
73
+ true
74
+ );
72
75
 
73
- it("should unStake USDC-sUSD LP from a gauge", async () => {
74
- const gaugeBalance = await dhedge.utils.getBalance(
75
- USDC_SUSD_Gauge,
76
- pool.address
77
- );
78
- await pool.unstakeFromGauge(USDC_SUSD_Gauge, gaugeBalance);
79
- const lpTokenDelta = await balanceDelta(
80
- pool.address,
81
- USDC_SUSD_Lp,
82
- pool.signer
83
- );
84
- expect(lpTokenDelta.gt(0));
85
- });
76
+ const lpTokenDelta = await balanceDelta(
77
+ pool.address,
78
+ USDC_SUSD_Lp,
79
+ pool.signer
80
+ );
81
+ expect(lpTokenDelta.gt(0)).toBe(true);
82
+ });
86
83
 
87
- it("approves unlimited wETH/stwETH LP for Velodrome", async () => {
88
- await pool.approve(Dapp.VELODROME, USDC_SUSD_Lp, MAX_AMOUNT);
89
- const lpAllowanceDelta = await allowanceDelta(
90
- pool.address,
91
- USDC_SUSD_Lp,
92
- routerAddress[network].velodrome!,
93
- pool.signer
94
- );
95
- expect(lpAllowanceDelta.gt(0));
96
- });
84
+ it("should stake USDC-sUSD LP in a gauge", async () => {
85
+ const balance = await dhedge.utils.getBalance(USDC_SUSD_Lp, pool.address);
86
+ await pool.approveSpender(USDC_SUSD_Gauge, USDC_SUSD_Lp, MAX_AMOUNT);
87
+ await pool.stakeInGauge(Dapp.VELODROME, USDC_SUSD_Gauge, balance);
88
+ const gaugeBalance = await balanceDelta(
89
+ pool.address,
90
+ USDC_SUSD_Lp,
91
+ pool.signer
92
+ );
93
+ expect(gaugeBalance.gt(0)).toBe(true);
94
+ });
95
+
96
+ it("should claim rewards from Gauge", async () => {
97
+ const tx = await pool.claimFees(Dapp.VELODROME, USDC_SUSD_Gauge);
98
+ expect(tx).not.toBe(null);
99
+ });
97
100
 
98
- it("should remove all liquidity from an existing pool ", async () => {
99
- const balance = await dhedge.utils.getBalance(USDC_SUSD_Lp, pool.address);
100
- await pool.removeLiquidityVelodrome(USDC, SUSD, balance, true);
101
- const usdcBalanceDelta = await balanceDelta(
102
- pool.address,
103
- USDC,
104
- pool.signer
105
- );
106
- const susdBalanceDelta = await balanceDelta(
107
- pool.address,
108
- SUSD,
109
- pool.signer
110
- );
111
- expect(usdcBalanceDelta.gt(0));
112
- expect(susdBalanceDelta.gt(0));
101
+ it("should unStake USDC-sUSD LP from a gauge", async () => {
102
+ const gaugeBalance = await dhedge.utils.getBalance(
103
+ USDC_SUSD_Gauge,
104
+ pool.address
105
+ );
106
+ await pool.unstakeFromGauge(USDC_SUSD_Gauge, gaugeBalance);
107
+ const lpTokenDelta = await balanceDelta(
108
+ pool.address,
109
+ USDC_SUSD_Lp,
110
+ pool.signer
111
+ );
112
+ expect(lpTokenDelta.gt(0)).toBe(true);
113
+ });
114
+
115
+ it("approves unlimited USDC-sUSD LP for Velodrome", async () => {
116
+ await pool.approve(Dapp.VELODROME, USDC_SUSD_Lp, MAX_AMOUNT);
117
+ const lpAllowanceDelta = await allowanceDelta(
118
+ pool.address,
119
+ USDC_SUSD_Lp,
120
+ routerAddress[network].velodrome!,
121
+ pool.signer
122
+ );
123
+ expect(lpAllowanceDelta.gt(0)).toBe(true);
124
+ });
125
+
126
+ it("should remove all liquidity from an existing pool ", async () => {
127
+ const balance = await dhedge.utils.getBalance(USDC_SUSD_Lp, pool.address);
128
+ await pool.removeLiquidityVelodrome(USDC, SUSD, balance, true);
129
+ const usdcBalanceDelta = await balanceDelta(
130
+ pool.address,
131
+ USDC,
132
+ pool.signer
133
+ );
134
+ const susdBalanceDelta = await balanceDelta(
135
+ pool.address,
136
+ SUSD,
137
+ pool.signer
138
+ );
139
+ expect(usdcBalanceDelta.gt(0)).toBe(true);
140
+ expect(susdBalanceDelta.gt(0)).toBe(true);
141
+ });
113
142
  });
143
+ };
144
+
145
+ testingHelper({
146
+ network: Network.OPTIMISM,
147
+ testingRun: testVelodrome
114
148
  });
@@ -1,22 +1,24 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
1
2
  import BigNumber from "bignumber.js";
2
3
  import { Dhedge, Pool, ethers } from "..";
3
4
 
4
5
  import { nonfungiblePositionManagerAddress } from "../config";
5
- import { AssetEnabled, Dapp, Network } from "../types";
6
+ import { Dapp, Network } from "../types";
6
7
  import { CONTRACT_ADDRESS, MAX_AMOUNT, TEST_POOL } from "./constants";
7
8
  import {
8
9
  TestingRunParams,
9
10
  beforeAfterReset,
11
+ fixOracleAggregatorStaleness,
12
+ runWithImpersonateAccount,
10
13
  setChainlinkTimeout,
11
14
  setUSDCAmount,
12
15
  setWETHAmount,
13
16
  testingHelper
14
17
  } from "./utils/testingHelper";
15
- import { allowanceDelta, balanceDelta } from "./utils/token";
18
+ import { balanceDelta } from "./utils/token";
16
19
  import INonfungiblePositionManager from "../abi/INonfungiblePositionManager.json";
17
20
 
18
21
  const testVelodromeCL = ({ wallet, network, provider }: TestingRunParams) => {
19
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20
22
  const VELODROME_POSITION_MANGER = nonfungiblePositionManagerAddress[network][
21
23
  Dapp.VELODROMECL
22
24
  ]!;
@@ -33,18 +35,33 @@ const testVelodromeCL = ({ wallet, network, provider }: TestingRunParams) => {
33
35
  let tokenId: string;
34
36
  jest.setTimeout(100000);
35
37
 
36
- describe(`[${network}] veldorome CL tests`, () => {
38
+ describe(`[${network}] velodrome CL tests`, () => {
37
39
  beforeAll(async () => {
38
- // top up ETH (gas)
39
40
  await provider.send("hardhat_setBalance", [
40
41
  wallet.address,
41
- "0x100000000000000"
42
+ "0x10000000000000000"
42
43
  ]);
43
44
  dhedge = new Dhedge(wallet, network);
44
45
  pool = await dhedge.loadPool(TEST_POOL[network]);
45
46
 
46
- // setChainlinkTimeout
47
47
  await setChainlinkTimeout({ pool, provider }, 86400 * 365);
48
+ await fixOracleAggregatorStaleness({ pool, provider });
49
+
50
+ await runWithImpersonateAccount(
51
+ { provider, account: await pool.managerLogic.manager() },
52
+ async ({ signer }) => {
53
+ await pool.managerLogic.connect(signer).setTrader(wallet.address);
54
+ await pool.managerLogic.connect(signer).changeAssets(
55
+ [
56
+ [USDC, true],
57
+ [WETH, true],
58
+ [VELODROME_POSITION_MANGER, false],
59
+ [VELO, false]
60
+ ],
61
+ []
62
+ );
63
+ }
64
+ );
48
65
 
49
66
  await setUSDCAmount({
50
67
  amount: new BigNumber(10000).times(1e6).toFixed(0),
@@ -59,20 +76,6 @@ const testVelodromeCL = ({ wallet, network, provider }: TestingRunParams) => {
59
76
  provider
60
77
  });
61
78
 
62
- const newAssets: AssetEnabled[] = [
63
- { asset: USDC, isDeposit: true },
64
- { asset: WETH, isDeposit: true },
65
- {
66
- asset: VELODROME_POSITION_MANGER,
67
- isDeposit: false
68
- },
69
- {
70
- asset: VELO,
71
- isDeposit: false
72
- }
73
- ];
74
- await pool.changeAssets(newAssets);
75
-
76
79
  velodromePositionManager = new ethers.Contract(
77
80
  VELODROME_POSITION_MANGER,
78
81
  INonfungiblePositionManager.abi,
@@ -86,13 +89,16 @@ const testVelodromeCL = ({ wallet, network, provider }: TestingRunParams) => {
86
89
  it("approves unlimited USDC and WETH on for Velodrome CL", async () => {
87
90
  await pool.approveSpender(VELODROME_POSITION_MANGER, USDC, MAX_AMOUNT);
88
91
  await pool.approveSpender(VELODROME_POSITION_MANGER, WETH, MAX_AMOUNT);
89
- const UsdcAllowanceDelta = await allowanceDelta(
90
- pool.address,
92
+ const iERC20 = new ethers.Contract(
91
93
  USDC,
92
- VELODROME_POSITION_MANGER,
94
+ ["function allowance(address,address) view returns (uint256)"],
93
95
  pool.signer
94
96
  );
95
- await expect(UsdcAllowanceDelta.gt(0));
97
+ const usdcAllowance = await iERC20.allowance(
98
+ pool.address,
99
+ VELODROME_POSITION_MANGER
100
+ );
101
+ expect(usdcAllowance.gt(0)).toBe(true);
96
102
  });
97
103
 
98
104
  it("adds USDC and WETH to a Velodrome CL (mint position)", async () => {
@@ -114,7 +120,7 @@ const testVelodromeCL = ({ wallet, network, provider }: TestingRunParams) => {
114
120
  tokenId = (
115
121
  await velodromePositionManager.tokenOfOwnerByIndex(pool.address, 0)
116
122
  ).toString();
117
- expect(tokenId).not.toBe(null);
123
+ expect(tokenId).toBeDefined();
118
124
  });
119
125
 
120
126
  it("increases liquidity in a CL position", async () => {
@@ -130,7 +136,7 @@ const testVelodromeCL = ({ wallet, network, provider }: TestingRunParams) => {
130
136
  wethBalance.div(2)
131
137
  );
132
138
  const positionAfter = await velodromePositionManager.positions(tokenId);
133
- expect(positionAfter.liquidity.gt(positionBefore.liquidity));
139
+ expect(positionAfter.liquidity.gt(positionBefore.liquidity)).toBe(true);
134
140
  });
135
141
 
136
142
  it("decreases liquidity from a CL position", async () => {
@@ -139,14 +145,17 @@ const testVelodromeCL = ({ wallet, network, provider }: TestingRunParams) => {
139
145
  );
140
146
  await pool.decreaseLiquidity(Dapp.VELODROMECL, tokenId, 50);
141
147
  const positionAfter = await velodromePositionManager.positions(tokenId);
142
- expect(positionAfter.liquidity.lt(positionBefore.liquidity));
148
+ expect(positionAfter.liquidity.lt(positionBefore.liquidity)).toBe(true);
143
149
  });
144
150
 
145
151
  it("collects fess of a CL position", async () => {
146
- await provider.send("evm_increaseTime", [24 * 3600 * 3]); // 1 day
152
+ await provider.send("evm_increaseTime", [24 * 3600 * 3]); // 3 days
147
153
  await provider.send("evm_mine", []);
148
154
  await pool.claimFees(Dapp.VELODROMECL, tokenId);
149
- expect((await balanceDelta(pool.address, USDC, pool.signer)).gt(0));
155
+ // Fork has no trading activity during evm_increaseTime so no fees accrue — assert gte(0) to verify the call succeeds
156
+ expect(
157
+ (await balanceDelta(pool.address, USDC, pool.signer)).gte(0)
158
+ ).toBe(true);
150
159
  });
151
160
  });
152
161
  describe("Liquidity staking", () => {
@@ -186,7 +195,10 @@ const testVelodromeCL = ({ wallet, network, provider }: TestingRunParams) => {
186
195
  await provider.send("evm_increaseTime", [24 * 3600]); // 1 day
187
196
  await provider.send("evm_mine", []);
188
197
  await pool.claimFees(Dapp.VELODROMECL, tokenId);
189
- expect((await balanceDelta(pool.address, VELO, pool.signer)).gt(0));
198
+ // Fork has no gauge emissions during evm_increaseTime so no VELO rewards — assert gte(0) to verify the call succeeds
199
+ expect(
200
+ (await balanceDelta(pool.address, VELO, pool.signer)).gte(0)
201
+ ).toBe(true);
190
202
  });
191
203
 
192
204
  it("unstakes a CL position from a gauge", async () => {