@dhedge/v2-sdk 2.2.3 → 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/dist/config.d.ts +0 -9
- package/dist/v2-sdk.cjs.development.js +20 -37
- package/dist/v2-sdk.cjs.development.js.map +1 -1
- package/dist/v2-sdk.cjs.production.min.js +1 -1
- package/dist/v2-sdk.cjs.production.min.js.map +1 -1
- package/dist/v2-sdk.esm.js +20 -37
- package/dist/v2-sdk.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/config.ts +4 -14
- package/src/services/odos/index.ts +6 -21
- package/src/test/constants.ts +1 -1
- package/src/test/dytm.test.ts +0 -5
- package/src/test/odos.test.ts +74 -34
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -62,7 +62,7 @@ export const routerAddress: AddressDappNetworkMap = {
|
|
|
62
62
|
[Dapp.ODOS]: "0x0D05a7D3448512B78fa8A9e46c4872C88C4a0D05",
|
|
63
63
|
[Dapp.PENDLE]: "0x888888888889758F76e7103c6CbF23ABbF58F946",
|
|
64
64
|
[Dapp.KYBERSWAP]: "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5",
|
|
65
|
-
[Dapp.DYTM]: "
|
|
65
|
+
[Dapp.DYTM]: ""
|
|
66
66
|
},
|
|
67
67
|
[Network.BASE]: {
|
|
68
68
|
[Dapp.ONEINCH]: "0x111111125421ca6dc452d289314280a0f8842a65",
|
|
@@ -80,7 +80,7 @@ export const routerAddress: AddressDappNetworkMap = {
|
|
|
80
80
|
[Dapp.ONEINCH]: "0x111111125421ca6dc452d289314280a0f8842a65",
|
|
81
81
|
[Dapp.KYBERSWAP]: "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5",
|
|
82
82
|
[Dapp.ONDO]: "0xde41399145F23936b03dD1474eC16c1519c0DC2a",
|
|
83
|
-
[Dapp.DYTM]: "
|
|
83
|
+
[Dapp.DYTM]: "0x0ff1ceB93DbADfB13722058D60c4B8cD122b06ea"
|
|
84
84
|
},
|
|
85
85
|
[Network.PLASMA]: {
|
|
86
86
|
[Dapp.AAVEV3]: "0x925a2A7214Ed92428B5b1B090F80b25700095e12",
|
|
@@ -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,
|
|
@@ -288,9 +278,9 @@ export const dytmContractAddresses: Readonly<Partial<
|
|
|
288
278
|
>
|
|
289
279
|
>> = {
|
|
290
280
|
[Network.ARBITRUM]: {
|
|
291
|
-
Periphery: "
|
|
281
|
+
Periphery: ""
|
|
292
282
|
},
|
|
293
283
|
[Network.ETHEREUM]: {
|
|
294
|
-
Periphery: "
|
|
284
|
+
Periphery: "0xfA03F9Ce907006133a0E77796a31c40AC22151d5"
|
|
295
285
|
}
|
|
296
286
|
};
|
|
@@ -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
|
|
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
|
-
|
|
60
|
-
referralFee:
|
|
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
|
-
|
|
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(
|
|
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),
|
|
120
|
+
fee: correctedFee.toFixed(0),
|
|
136
121
|
feeRecipient: referralInfo.feeRecipient
|
|
137
122
|
}
|
|
138
123
|
]);
|
package/src/test/constants.ts
CHANGED
|
@@ -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]:
|
|
232
|
+
[Network.POLYGON]: 9,
|
|
233
233
|
[Network.BASE]: 9,
|
|
234
234
|
[Network.ETHEREUM]: 9,
|
|
235
235
|
[Network.PLASMA]: 9,
|
package/src/test/dytm.test.ts
CHANGED
|
@@ -230,11 +230,6 @@ const testDytm = ({ network, wallet, provider }: TestingRunParams) => {
|
|
|
230
230
|
});
|
|
231
231
|
};
|
|
232
232
|
|
|
233
|
-
testingHelper({
|
|
234
|
-
network: Network.ARBITRUM,
|
|
235
|
-
testingRun: testDytm
|
|
236
|
-
});
|
|
237
|
-
|
|
238
233
|
testingHelper({
|
|
239
234
|
network: Network.ETHEREUM,
|
|
240
235
|
testingRun: testDytm
|
package/src/test/odos.test.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
87
|
-
|
|
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
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
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
|
-
|
|
128
|
-
|
|
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
|
-
//
|
|
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
|
// });
|