@dhedge/v2-sdk 2.2.4 → 2.2.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhedge/v2-sdk",
3
- "version": "2.2.4",
3
+ "version": "2.2.5",
4
4
  "license": "MIT",
5
5
  "description": "🛠 An SDK for building applications on top of dHEDGE V2",
6
6
  "main": "dist/index.js",
package/src/config.ts CHANGED
@@ -269,16 +269,6 @@ export const limitOrderAddress: AddressNetworkMap = {
269
269
  [Network.HYPERLIQUID]: ""
270
270
  };
271
271
 
272
- export const OdosSwapFeeRecipient = {
273
- [Network.POLYGON]: "0x090e7fbD87A673eE3D0B6ccACf0e1d94fB90DA59",
274
- [Network.OPTIMISM]: "0x813123A13d01d3F07d434673Fdc89cBBA523f14d",
275
- [Network.ARBITRUM]: "0xfbD2B4216f422DC1eEe1Cff4Fb64B726F099dEF5",
276
- [Network.BASE]: "0x5619AD05b0253a7e647Bd2E4C01c7f40CEaB0879",
277
- [Network.ETHEREUM]: "0xfbD2B4216f422DC1eEe1Cff4Fb64B726F099dEF5",
278
- [Network.PLASMA]: "",
279
- [Network.HYPERLIQUID]: ""
280
- };
281
-
282
272
  export const dytmContractAddresses: Readonly<Partial<
283
273
  Record<
284
274
  Network,
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import axios from "axios";
3
3
  import { ApiError, ethers } from "../..";
4
- import { networkChainIdMap, OdosSwapFeeRecipient } from "../../config";
4
+ import { networkChainIdMap } from "../../config";
5
5
  import { Pool } from "../../entities";
6
6
  import OdosRouterV3Abi from "../../abi/odos/OdosRouterV3.json";
7
7
  import BigNumber from "bignumber.js";
@@ -37,8 +37,6 @@ export async function getOdosSwapTxData(
37
37
  }
38
38
  const ODOS_API_KEY = process.env.ODOS_API_KEY;
39
39
 
40
- const referralFeeBips = 2; // 2 basis points = 0.02%
41
-
42
40
  const quoteParams = {
43
41
  chainId: networkChainIdMap[pool.network],
44
42
  inputTokens: [
@@ -56,8 +54,8 @@ export async function getOdosSwapTxData(
56
54
  slippageLimitPercent: slippage,
57
55
  userAddr: pool.address,
58
56
  compact: false,
59
- referralFeeRecipient: OdosSwapFeeRecipient[pool.network],
60
- referralFee: referralFeeBips // 0.02% fee
57
+ // OdosV3ContractGuard requires referral fee == 0
58
+ referralFee: 0
61
59
  };
62
60
  try {
63
61
  const quoteResult = await axios.post(
@@ -98,20 +96,9 @@ export async function getOdosSwapTxData(
98
96
  const executor = decodedData.args[2] as string;
99
97
  const referralInfo = decodedData.args[3] as SwapReferralInfo;
100
98
 
101
- if (
102
- referralInfo.fee.lte(
103
- ethers.BigNumber.from((referralFeeBips * 1e18) / 10000)
104
- )
105
- ) {
106
- // Referral fee is already correct, return original txData
107
- return {
108
- swapTxData: assembleResult.data.transaction.data,
109
- minAmountOut: assembleResult.data.outputTokens[0].amount
110
- };
111
- }
112
-
99
+ // Force referral fee to 0 and scale outputQuote up accordingly.
113
100
  const FEE_DENOM = new BigNumber(1e18);
114
- const correctedFee = new BigNumber((referralFeeBips * 1e18) / 10000);
101
+ const correctedFee = new BigNumber(0);
115
102
  const factor = 1.1;
116
103
  const correctedOutputQuote = new BigNumber(tokenInfo.outputQuote.toString())
117
104
  .times(
@@ -121,8 +108,6 @@ export async function getOdosSwapTxData(
121
108
  )
122
109
  .times(factor);
123
110
 
124
- // example referralInfo.fee could be 0.0005 * 1e18 = 500000000000000, which is 0.05%
125
- // Create corrected referral info
126
111
  const correctedTxData = iface.encodeFunctionData(decodedData.name, [
127
112
  {
128
113
  ...tokenInfo,
@@ -132,7 +117,7 @@ export async function getOdosSwapTxData(
132
117
  executor,
133
118
  {
134
119
  code: referralInfo.code,
135
- fee: correctedFee.toFixed(0), // align with referralFeeBips
120
+ fee: correctedFee.toFixed(0),
136
121
  feeRecipient: referralInfo.feeRecipient
137
122
  }
138
123
  ]);
@@ -229,7 +229,7 @@ export const MAX_AMOUNT = ethers.constants.MaxUint256;
229
229
  export const USDC_BALANCEOF_SLOT = {
230
230
  [Network.OPTIMISM]: 9,
231
231
  [Network.ARBITRUM]: 9,
232
- [Network.POLYGON]: 0,
232
+ [Network.POLYGON]: 9,
233
233
  [Network.BASE]: 9,
234
234
  [Network.ETHEREUM]: 9,
235
235
  [Network.PLASMA]: 9,
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
2
 
3
- import { Dhedge, Pool } from "..";
3
+ import { Dhedge, Pool, ethers } from "..";
4
4
 
5
5
  import { Dapp, Network } from "../types";
6
6
  import { CONTRACT_ADDRESS, MAX_AMOUNT, TEST_POOL } from "./constants";
@@ -8,12 +8,17 @@ import {
8
8
  TestingRunParams,
9
9
  setUSDCAmount,
10
10
  testingHelper,
11
- wait
11
+ wait,
12
+ runWithImpersonateAccount
12
13
  } from "./utils/testingHelper";
13
14
  import { allowanceDelta, balanceDelta } from "./utils/token";
14
15
  import { getTxOptions } from "./txOptions";
15
16
  import BigNumber from "bignumber.js";
16
- import { OdosSwapFeeRecipient, routerAddress } from "../config";
17
+ import { routerAddress } from "../config";
18
+ import { getOdosSwapTxData } from "../services/odos";
19
+ import OdosRouterV3Abi from "../abi/odos/OdosRouterV3.json";
20
+ import PoolLogicAbi from "../abi/PoolLogic.json";
21
+ import PoolManagerLogicAbi from "../abi/PoolManagerLogic.json";
17
22
 
18
23
  const testOdos = ({ wallet, network, provider }: TestingRunParams) => {
19
24
  const USDC = CONTRACT_ADDRESS[network].USDC;
@@ -27,6 +32,36 @@ const testOdos = ({ wallet, network, provider }: TestingRunParams) => {
27
32
  beforeAll(async () => {
28
33
  dhedge = new Dhedge(wallet, network);
29
34
  pool = await dhedge.loadPool(TEST_POOL[network]);
35
+ // fork-only: authorize the test wallet by impersonating the pool manager
36
+ // and setting the wallet as trader (avoids dh24 unauthorized executor)
37
+ const poolLogic = new ethers.Contract(
38
+ pool.address,
39
+ PoolLogicAbi.abi,
40
+ provider
41
+ );
42
+ const pmlAddress: string = await poolLogic.poolManagerLogic();
43
+ const poolManagerLogic = new ethers.Contract(
44
+ pmlAddress,
45
+ PoolManagerLogicAbi.abi,
46
+ provider
47
+ );
48
+ const manager: string = await poolManagerLogic.manager();
49
+ const wethSupported: boolean = await poolManagerLogic.isSupportedAsset(
50
+ WETH
51
+ );
52
+ await runWithImpersonateAccount(
53
+ { account: manager, provider },
54
+ async ({ signer }) => {
55
+ await poolManagerLogic.connect(signer).setTrader(wallet.address);
56
+ // fork-only: ensure WETH is a supported (destination) asset so the
57
+ // Odos guard's isSupportedAsset check passes
58
+ if (!wethSupported) {
59
+ await poolManagerLogic
60
+ .connect(signer)
61
+ .changeAssets([{ asset: WETH, isDeposit: false }], []);
62
+ }
63
+ }
64
+ );
30
65
  // top up gas
31
66
  await provider.send("hardhat_setBalance", [
32
67
  wallet.address,
@@ -69,6 +104,20 @@ const testOdos = ({ wallet, network, provider }: TestingRunParams) => {
69
104
 
70
105
  it("trades 10 USDC into WETH on Odos", async () => {
71
106
  await wait(1);
107
+ // inspect the swap txData: referral fee must be 0 (OdosV3ContractGuard)
108
+ const { swapTxData } = await getOdosSwapTxData(
109
+ pool,
110
+ USDC,
111
+ WETH,
112
+ "10000000",
113
+ 0.5
114
+ );
115
+ const referralInfo = new ethers.utils.Interface(
116
+ OdosRouterV3Abi.abi
117
+ ).parseTransaction({ data: swapTxData }).args[3];
118
+ expect(referralInfo.fee.isZero()).toBe(true);
119
+ const feeRecipient: string = referralInfo.feeRecipient;
120
+
72
121
  await pool.trade(
73
122
  Dapp.ODOS,
74
123
  USDC,
@@ -83,37 +132,20 @@ const testOdos = ({ wallet, network, provider }: TestingRunParams) => {
83
132
  pool.signer
84
133
  );
85
134
  expect(wethBalanceDelta.gt(0)).toBe(true);
86
- const wethBalanceDeltaForFeeRecipient = await balanceDelta(
87
- OdosSwapFeeRecipient[network],
135
+ // no WETH skimmed to the Odos router
136
+ const wethBalanceDeltaForRouter = await balanceDelta(
137
+ routerAddress[network]["odos"]!,
88
138
  WETH,
89
139
  pool.signer
90
140
  );
91
-
92
- // diffRatio = (1 - fee) / (0.8 * fee)
93
- // 0.8 is the split percentage for fee recipient
94
- // e.g. for 0.02% fee, diffRatio = 0.9998 / 0.00016 = 6248.75
95
- // e.g. for 0.03% fee, diffRatio = 0.9997 / 0.00024 = 4165.42
96
- // e.g. for 0.04% fee, diffRatio = 0.9996 / 0.00032 = 3123.75
97
- // e.g. for 0.05% fee, diffRatio = 0.9995 / 0.00040 = 2498.75
98
- const diffRatio = wethBalanceDelta.div(wethBalanceDeltaForFeeRecipient);
99
- console.log("diff ratio:", diffRatio.toString());
100
- expect(diffRatio.gt(6200)).toBe(true);
101
- expect(diffRatio.lt(6260)).toBe(true);
102
- const wethBalanceDeltaForRouter = await balanceDelta(
103
- routerAddress[network]["odos"]!,
141
+ expect(wethBalanceDeltaForRouter.eq(0)).toBe(true);
142
+ // no WETH skimmed to the referral fee recipient encoded in the txData
143
+ const wethBalanceDeltaForFeeRecipient = await balanceDelta(
144
+ feeRecipient,
104
145
  WETH,
105
146
  pool.signer
106
147
  );
107
- // diffRatio = (1 - fee) / (0.2 * fee)
108
- // 0.2 is the split percentage for router
109
- // e.g. for 0.02% fee, diffRatio = 0.9998 / 0.00004 = 24995
110
- // e.g. for 0.03% fee, diffRatio = 0.9997 / 0.00006 = 16661.67
111
- // e.g. for 0.04% fee, diffRatio = 0.9996 / 0.00008 = 12495
112
- // e.g. for 0.05% fee, diffRatio = 0.9995 / 0.00010 = 9995
113
- const diffRatioRouter = wethBalanceDelta.div(wethBalanceDeltaForRouter);
114
- console.log("diff ratio router:", diffRatioRouter.toString());
115
- expect(diffRatioRouter.gt(24000)).toBe(true);
116
- expect(diffRatioRouter.lt(26000)).toBe(true);
148
+ expect(wethBalanceDeltaForFeeRecipient.eq(0)).toBe(true);
117
149
  });
118
150
  });
119
151
  };
@@ -123,19 +155,27 @@ const testOdos = ({ wallet, network, provider }: TestingRunParams) => {
123
155
  // testingRun: testOdos
124
156
  // });
125
157
 
126
- testingHelper({
127
- network: Network.ARBITRUM,
128
- testingRun: testOdos
129
- });
158
+ // testingHelper({
159
+ // network: Network.ARBITRUM,
160
+ // testingRun: testOdos
161
+ // });
130
162
 
131
163
  // testingHelper({
132
164
  // network: Network.POLYGON,
133
- // onFork: false,
134
165
  // testingRun: testOdos
135
166
  // });
136
167
 
137
168
  // testingHelper({
138
169
  // network: Network.BASE,
139
- // onFork: false,
170
+ // testingRun: testOdos
171
+ // });
172
+
173
+ testingHelper({
174
+ network: Network.ETHEREUM,
175
+ testingRun: testOdos
176
+ });
177
+
178
+ // testingHelper({
179
+ // network: Network.BASE,
140
180
  // testingRun: testOdos
141
181
  // });