@paraswap/dex-lib 3.4.2-balancer-v2-single-swap.0 → 3.4.2
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/README.md +377 -377
- package/build/config.js +9 -5
- package/build/config.js.map +1 -1
- package/build/dex/algebra/algebra.js +25 -25
- package/build/dex/balancer-v1/balancer-v1.js +34 -34
- package/build/dex/balancer-v2/balancer-v2.d.ts +1 -1
- package/build/dex/balancer-v2/balancer-v2.js +65 -78
- package/build/dex/balancer-v2/balancer-v2.js.map +1 -1
- package/build/dex/camelot/camelot.js +27 -27
- package/build/dex/kyberdmm/kyberdmm.js +27 -27
- package/build/dex/pancakeswap-v3/pancakeswap-v3.js +25 -25
- package/build/dex/solidly/solidly.js +27 -27
- package/build/dex/solidly-v3/solidly-v3.js +25 -25
- package/build/dex/swaap-v2/config.js +15 -0
- package/build/dex/swaap-v2/config.js.map +1 -1
- package/build/dex/uniswap-v2/uniswap-v2.js +26 -26
- package/build/dex/uniswap-v3/uniswap-v3.js +25 -25
- package/funding.json +5 -5
- package/package.json +1 -1
- package/src/config.ts +500 -496
- package/src/constants.ts +67 -67
- package/src/dex/aave-v2/aave-v2.ts +409 -409
- package/src/dex/aave-v3/aave-v3.ts +320 -320
- package/src/dex/algebra/algebra.ts +1180 -1180
- package/src/dex/angle-staked-stable/angle-staked-stable.ts +347 -347
- package/src/dex/augustus-rfq.ts +180 -180
- package/src/dex/bProtocol/bProtocol.ts +108 -108
- package/src/dex/balancer-v1/balancer-v1.ts +572 -572
- package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +1699 -1699
- package/src/dex/balancer-v2/balancer-v2.ts +1669 -1701
- package/src/dex/bancor/bancor.ts +128 -128
- package/src/dex/camelot/camelot.ts +873 -873
- package/src/dex/compound/compound.ts +107 -107
- package/src/dex/curve-v1/config.ts +1179 -1179
- package/src/dex/curve-v1/curve-v1-e2e.test.ts +507 -507
- package/src/dex/curve-v1/curve-v1.ts +1315 -1315
- package/src/dex/curve-v1-factory/config.ts +1018 -1018
- package/src/dex/curve-v1-factory/curve-v1-factory.ts +1288 -1288
- package/src/dex/curve-v2/curve-v2.ts +440 -440
- package/src/dex/dexalot/dexalot.ts +1100 -1100
- package/src/dex/dodo-v1/dodo-v1.ts +132 -132
- package/src/dex/dodo-v2.ts +266 -266
- package/src/dex/etherfi.ts +239 -239
- package/src/dex/generic-rfq/generic-rfq.ts +431 -431
- package/src/dex/gmx/gmx.ts +321 -321
- package/src/dex/hashflow/hashflow.ts +1135 -1135
- package/src/dex/idex.ts +254 -254
- package/src/dex/index.ts +357 -357
- package/src/dex/jarvis-v6/jarvis-v6.ts +509 -509
- package/src/dex/jarvis.ts +262 -262
- package/src/dex/kyberdmm/kyberdmm.ts +649 -649
- package/src/dex/lido/lido.ts +110 -110
- package/src/dex/maker-psm/maker-psm.ts +592 -592
- package/src/dex/maverick-v1/maverick-v1.ts +537 -537
- package/src/dex/nerve/config.ts +635 -635
- package/src/dex/nerve/nerve-e2e.test.ts +731 -731
- package/src/dex/nerve/nerve-events.test.ts +911 -911
- package/src/dex/nerve/nerve.ts +467 -467
- package/src/dex/onebit/onebit.ts +113 -113
- package/src/dex/pancakeswap-v3/pancakeswap-v3.ts +1150 -1150
- package/src/dex/paraswap-limit-orders/config.ts +60 -60
- package/src/dex/paraswap-limit-orders/paraswap-limit-orders-e2e.test.ts +137 -137
- package/src/dex/paraswap-limit-orders/paraswap-limit-orders-integration.test.ts +328 -328
- package/src/dex/paraswap-limit-orders/paraswap-limit-orders.ts +631 -631
- package/src/dex/polygon-migrator/polygon-migrator.ts +194 -194
- package/src/dex/quick-perps/quick-perps.ts +337 -337
- package/src/dex/quickswap/config.ts +16 -16
- package/src/dex/quickswap/quickswap-e2e.test.ts +384 -384
- package/src/dex/smoothy/smoothy.ts +110 -110
- package/src/dex/solidly/config.ts +225 -225
- package/src/dex/solidly/solidly-e2e.test.ts +1421 -1421
- package/src/dex/solidly/solidly-integration.test.ts +1753 -1753
- package/src/dex/solidly/solidly.ts +687 -687
- package/src/dex/solidly-v3/solidly-v3.ts +968 -968
- package/src/dex/spark/spark.ts +284 -284
- package/src/dex/stable-pool/stable-pool.ts +129 -129
- package/src/dex/swaap-v2/config.ts +15 -0
- package/src/dex/swaap-v2/swaap-v2-e2e.test.ts +233 -17
- package/src/dex/swaap-v2/swaap-v2-integration.test.ts +1 -1
- package/src/dex/swaap-v2/swaap-v2.ts +1056 -1056
- package/src/dex/swell/swell.ts +312 -312
- package/src/dex/synthetix/synthetix.ts +420 -420
- package/src/dex/trader-joe-v2.1/trader-joe-v2.1.ts +180 -180
- package/src/dex/uniswap-v2/config.ts +637 -637
- package/src/dex/uniswap-v2/constants.ts +58 -58
- package/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts +1257 -1257
- package/src/dex/uniswap-v2/uniswap-v2-e2e-base.test.ts +42 -42
- package/src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts +1295 -1295
- package/src/dex/uniswap-v2/uniswap-v2-e2e-mainnet.test.ts +1834 -1834
- package/src/dex/uniswap-v2/uniswap-v2-e2e-polygon.test.ts +871 -871
- package/src/dex/uniswap-v2/uniswap-v2.ts +1117 -1117
- package/src/dex/uniswap-v3/uniswap-v3.ts +1501 -1501
- package/src/dex/uniswap-v3.ts +242 -242
- package/src/dex/weth/config.ts +73 -73
- package/src/dex/weth/weth.ts +230 -230
- package/src/dex/wombat/wombat.ts +467 -467
- package/src/dex/woo-fi-v2/woo-fi-v2.ts +529 -529
- package/src/dex/wsteth/wsteth.ts +304 -304
- package/src/dex/zerox/index.ts +328 -328
- package/src/executor/Executor01BytecodeBuilder.ts +474 -474
- package/src/executor/Executor02BytecodeBuilder.ts +1392 -1392
- package/src/executor/ExecutorBytecodeBuilder.ts +390 -390
- package/src/executor/ExecutorDetector.ts +131 -131
- package/src/executor/constants.ts +66 -66
- package/src/executor/executor01-bytecode-builder-e2e.test.ts +1478 -1478
- package/src/executor/utils.ts +62 -62
- package/src/router/simpleswap.ts +366 -366
- package/src/types.ts +342 -342
- package/tests/constants-e2e.ts +1632 -1622
- package/tests/generate-new-limit-order.ts +107 -107
|
@@ -1,474 +1,474 @@
|
|
|
1
|
-
import { ethers } from 'ethers';
|
|
2
|
-
import { DexExchangeBuildParam } from '../types';
|
|
3
|
-
import { OptimalRate } from '@paraswap/core';
|
|
4
|
-
import { isETHAddress } from '../utils';
|
|
5
|
-
import { DepositWithdrawReturn } from '../dex/weth/types';
|
|
6
|
-
import { Executors, Flag, SpecialDex } from './types';
|
|
7
|
-
import { BYTES_64_LENGTH, DEFAULT_RETURN_AMOUNT_POS } from './constants';
|
|
8
|
-
import {
|
|
9
|
-
DexCallDataParams,
|
|
10
|
-
ExecutorBytecodeBuilder,
|
|
11
|
-
SingleSwapCallDataParams,
|
|
12
|
-
} from './ExecutorBytecodeBuilder';
|
|
13
|
-
import { assert } from 'ts-essentials';
|
|
14
|
-
|
|
15
|
-
const {
|
|
16
|
-
utils: { hexlify, hexDataLength, hexConcat, hexZeroPad, solidityPack },
|
|
17
|
-
} = ethers;
|
|
18
|
-
|
|
19
|
-
export type Executor01SingleSwapCallDataParams = {};
|
|
20
|
-
export type Executor01DexCallDataParams = {};
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Class to build bytecode for Executor01 - simpleSwap (SINGLE_STEP) with 100% on a path and multiSwap with 100% amounts on each path (HORIZONTAL_SEQUENCE)
|
|
24
|
-
*/
|
|
25
|
-
export class Executor01BytecodeBuilder extends ExecutorBytecodeBuilder<
|
|
26
|
-
Executor01SingleSwapCallDataParams,
|
|
27
|
-
Executor01DexCallDataParams
|
|
28
|
-
> {
|
|
29
|
-
type = Executors.ONE;
|
|
30
|
-
/**
|
|
31
|
-
* Executor01 Flags:
|
|
32
|
-
* switch (flag % 4):
|
|
33
|
-
* case 0: don't instert fromAmount
|
|
34
|
-
* case 1: sendEth equal to fromAmount
|
|
35
|
-
* case 2: sendEth equal to fromAmount + insert fromAmount
|
|
36
|
-
* case 3: insert fromAmount
|
|
37
|
-
|
|
38
|
-
* switch (flag % 3):
|
|
39
|
-
* case 0: don't check balance after swap
|
|
40
|
-
* case 1: check eth balance after swap
|
|
41
|
-
* case 2: check destToken balance after swap
|
|
42
|
-
*/
|
|
43
|
-
protected buildSimpleSwapFlags(
|
|
44
|
-
priceRoute: OptimalRate,
|
|
45
|
-
exchangeParams: DexExchangeBuildParam[],
|
|
46
|
-
routeIndex: number,
|
|
47
|
-
swapIndex: number,
|
|
48
|
-
swapExchangeIndex: number,
|
|
49
|
-
exchangeParamIndex: number,
|
|
50
|
-
maybeWethCallData?: DepositWithdrawReturn,
|
|
51
|
-
): { dexFlag: Flag; approveFlag: Flag } {
|
|
52
|
-
const { srcToken, destToken } =
|
|
53
|
-
priceRoute.bestRoute[routeIndex].swaps[swapIndex];
|
|
54
|
-
const isEthSrc = isETHAddress(srcToken);
|
|
55
|
-
const isEthDest = isETHAddress(destToken);
|
|
56
|
-
|
|
57
|
-
const exchangeParam = exchangeParams[exchangeParamIndex];
|
|
58
|
-
const {
|
|
59
|
-
dexFuncHasRecipient,
|
|
60
|
-
needWrapNative,
|
|
61
|
-
specialDexFlag,
|
|
62
|
-
specialDexSupportsInsertFromAmount,
|
|
63
|
-
swappedAmountNotPresentInExchangeData,
|
|
64
|
-
preSwapUnwrapCalldata,
|
|
65
|
-
} = exchangeParam;
|
|
66
|
-
|
|
67
|
-
const needWrap = needWrapNative && isEthSrc && maybeWethCallData?.deposit;
|
|
68
|
-
const needUnwrap =
|
|
69
|
-
needWrapNative && isEthDest && maybeWethCallData?.withdraw;
|
|
70
|
-
const isSpecialDex =
|
|
71
|
-
specialDexFlag !== undefined && specialDexFlag !== SpecialDex.DEFAULT;
|
|
72
|
-
|
|
73
|
-
const forcePreventInsertFromAmount =
|
|
74
|
-
swappedAmountNotPresentInExchangeData ||
|
|
75
|
-
(isSpecialDex && !specialDexSupportsInsertFromAmount);
|
|
76
|
-
|
|
77
|
-
let dexFlag = forcePreventInsertFromAmount
|
|
78
|
-
? Flag.DONT_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP
|
|
79
|
-
: Flag.INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 0 or 3
|
|
80
|
-
let approveFlag =
|
|
81
|
-
Flag.DONT_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 0
|
|
82
|
-
|
|
83
|
-
if (isEthSrc && !needWrap) {
|
|
84
|
-
dexFlag =
|
|
85
|
-
Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP; // 5
|
|
86
|
-
} else if (isEthDest && !needUnwrap) {
|
|
87
|
-
dexFlag = forcePreventInsertFromAmount
|
|
88
|
-
? Flag.DONT_INSERT_FROM_AMOUNT_CHECK_ETH_BALANCE_AFTER_SWAP
|
|
89
|
-
: Flag.INSERT_FROM_AMOUNT_CHECK_ETH_BALANCE_AFTER_SWAP; // 4 or 7
|
|
90
|
-
} else if (!dexFuncHasRecipient || (isEthDest && needUnwrap)) {
|
|
91
|
-
dexFlag = forcePreventInsertFromAmount
|
|
92
|
-
? Flag.DONT_INSERT_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP
|
|
93
|
-
: Flag.INSERT_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP; // 8 or 11
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Actual srcToken is eth, because we'll unwrap weth before swap.
|
|
97
|
-
// Need to check balance, some dexes don't have 1:1 ETH -> custom_ETH rate
|
|
98
|
-
if (preSwapUnwrapCalldata) {
|
|
99
|
-
dexFlag =
|
|
100
|
-
Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
dexFlag,
|
|
105
|
-
approveFlag,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Executor01 Flags:
|
|
111
|
-
* switch (flag % 4):
|
|
112
|
-
* case 0: don't insert fromAmount
|
|
113
|
-
* case 1: sendEth equal to fromAmount
|
|
114
|
-
* case 2: sendEth equal to fromAmount + insert fromAmount
|
|
115
|
-
* case 3: insert fromAmount
|
|
116
|
-
|
|
117
|
-
* switch (flag % 3):
|
|
118
|
-
* case 0: don't check balance after swap
|
|
119
|
-
* case 1: check eth balance after swap
|
|
120
|
-
* case 2: check destToken balance after swap
|
|
121
|
-
*/
|
|
122
|
-
// Executor01 doesn't support mega swap routes, flags are built for multi swap routes only here
|
|
123
|
-
protected buildMultiMegaSwapFlags(
|
|
124
|
-
priceRoute: OptimalRate,
|
|
125
|
-
exchangeParams: DexExchangeBuildParam[],
|
|
126
|
-
routeIndex: number,
|
|
127
|
-
swapIndex: number,
|
|
128
|
-
swapExchangeIndex: number,
|
|
129
|
-
exchangeParamIndex: number,
|
|
130
|
-
maybeWethCallData?: DepositWithdrawReturn,
|
|
131
|
-
): { dexFlag: Flag; approveFlag: Flag } {
|
|
132
|
-
// same as for Executor02 multi flags, except forceBalanceOfCheck
|
|
133
|
-
const swap = priceRoute.bestRoute[routeIndex].swaps[swapIndex];
|
|
134
|
-
const { srcToken, destToken } = swap;
|
|
135
|
-
const exchangeParam = exchangeParams[exchangeParamIndex];
|
|
136
|
-
const {
|
|
137
|
-
dexFuncHasRecipient,
|
|
138
|
-
needWrapNative,
|
|
139
|
-
specialDexFlag,
|
|
140
|
-
specialDexSupportsInsertFromAmount,
|
|
141
|
-
swappedAmountNotPresentInExchangeData,
|
|
142
|
-
sendEthButSupportsInsertFromAmount,
|
|
143
|
-
preSwapUnwrapCalldata,
|
|
144
|
-
} = exchangeParam;
|
|
145
|
-
|
|
146
|
-
const isLastSwap =
|
|
147
|
-
swapIndex === priceRoute.bestRoute[routeIndex].swaps.length - 1;
|
|
148
|
-
const isEthSrc = isETHAddress(srcToken);
|
|
149
|
-
const isEthDest = isETHAddress(destToken);
|
|
150
|
-
|
|
151
|
-
const isSpecialDex =
|
|
152
|
-
specialDexFlag !== undefined && specialDexFlag !== SpecialDex.DEFAULT;
|
|
153
|
-
|
|
154
|
-
const forcePreventInsertFromAmount =
|
|
155
|
-
swappedAmountNotPresentInExchangeData ||
|
|
156
|
-
(isSpecialDex && !specialDexSupportsInsertFromAmount);
|
|
157
|
-
|
|
158
|
-
const needUnwrap =
|
|
159
|
-
needWrapNative && isEthDest && maybeWethCallData?.withdraw;
|
|
160
|
-
|
|
161
|
-
const forceBalanceOfCheck = isLastSwap
|
|
162
|
-
? !dexFuncHasRecipient || needUnwrap
|
|
163
|
-
: true;
|
|
164
|
-
|
|
165
|
-
const needSendEth = isEthSrc && !needWrapNative;
|
|
166
|
-
const needCheckEthBalance = isEthDest && !needWrapNative;
|
|
167
|
-
|
|
168
|
-
const needCheckSrcTokenBalanceOf = needUnwrap && !isLastSwap;
|
|
169
|
-
|
|
170
|
-
let dexFlag: Flag;
|
|
171
|
-
let approveFlag =
|
|
172
|
-
Flag.DONT_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 0
|
|
173
|
-
|
|
174
|
-
if (needSendEth) {
|
|
175
|
-
const preventInsertForSendEth =
|
|
176
|
-
forcePreventInsertFromAmount || !sendEthButSupportsInsertFromAmount;
|
|
177
|
-
dexFlag = forceBalanceOfCheck
|
|
178
|
-
? preventInsertForSendEth
|
|
179
|
-
? Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP // 5
|
|
180
|
-
: Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_PLUS_INSERT_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP // 14
|
|
181
|
-
: dexFuncHasRecipient
|
|
182
|
-
? preventInsertForSendEth
|
|
183
|
-
? Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP // 9
|
|
184
|
-
: Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_PLUS_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP // 18
|
|
185
|
-
: preventInsertForSendEth
|
|
186
|
-
? Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP // 5
|
|
187
|
-
: Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_PLUS_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 18
|
|
188
|
-
} else if (needCheckEthBalance) {
|
|
189
|
-
dexFlag =
|
|
190
|
-
needCheckSrcTokenBalanceOf || forceBalanceOfCheck
|
|
191
|
-
? forcePreventInsertFromAmount && dexFuncHasRecipient
|
|
192
|
-
? Flag.DONT_INSERT_FROM_AMOUNT_CHECK_ETH_BALANCE_AFTER_SWAP // 4
|
|
193
|
-
: Flag.INSERT_FROM_AMOUNT_CHECK_ETH_BALANCE_AFTER_SWAP // 7
|
|
194
|
-
: forcePreventInsertFromAmount && dexFuncHasRecipient
|
|
195
|
-
? Flag.DONT_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP // 0
|
|
196
|
-
: Flag.INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 3
|
|
197
|
-
} else {
|
|
198
|
-
dexFlag =
|
|
199
|
-
needCheckSrcTokenBalanceOf || forceBalanceOfCheck
|
|
200
|
-
? forcePreventInsertFromAmount
|
|
201
|
-
? Flag.DONT_INSERT_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP // 8
|
|
202
|
-
: Flag.INSERT_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP // 11
|
|
203
|
-
: forcePreventInsertFromAmount
|
|
204
|
-
? Flag.DONT_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP // 0
|
|
205
|
-
: Flag.INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 3
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Actual srcToken is eth, because we'll unwrap weth before swap.
|
|
209
|
-
// Need to check balance, some dexes don't have 1:1 ETH -> custom_ETH rate
|
|
210
|
-
if (preSwapUnwrapCalldata) {
|
|
211
|
-
dexFlag =
|
|
212
|
-
Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return {
|
|
216
|
-
dexFlag,
|
|
217
|
-
approveFlag,
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
protected buildSingleSwapCallData(
|
|
222
|
-
params: SingleSwapCallDataParams<Executor01SingleSwapCallDataParams>,
|
|
223
|
-
): string {
|
|
224
|
-
const { priceRoute, index, exchangeParams, flags, maybeWethCallData } =
|
|
225
|
-
params;
|
|
226
|
-
|
|
227
|
-
let swapCallData = '';
|
|
228
|
-
const swap = priceRoute.bestRoute[0].swaps[index];
|
|
229
|
-
const curExchangeParam = exchangeParams[index];
|
|
230
|
-
|
|
231
|
-
const dexCallData = this.buildDexCallData({
|
|
232
|
-
priceRoute,
|
|
233
|
-
routeIndex: 0,
|
|
234
|
-
swapIndex: index,
|
|
235
|
-
swapExchangeIndex: 0,
|
|
236
|
-
exchangeParams,
|
|
237
|
-
exchangeParamIndex: index,
|
|
238
|
-
isLastSwap: index === priceRoute.bestRoute[0].swaps.length - 1,
|
|
239
|
-
flag: flags.dexes[index],
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
if (curExchangeParam.preSwapUnwrapCalldata) {
|
|
243
|
-
const withdrawCallData = this.buildUnwrapEthCallData(
|
|
244
|
-
this.getWETHAddress(curExchangeParam),
|
|
245
|
-
curExchangeParam.preSwapUnwrapCalldata,
|
|
246
|
-
);
|
|
247
|
-
swapCallData = hexConcat([withdrawCallData, dexCallData]);
|
|
248
|
-
} else {
|
|
249
|
-
swapCallData = hexConcat([dexCallData]);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (curExchangeParam.transferSrcTokenBeforeSwap) {
|
|
253
|
-
const transferCallData = this.buildTransferCallData(
|
|
254
|
-
this.erc20Interface.encodeFunctionData('transfer', [
|
|
255
|
-
curExchangeParam.transferSrcTokenBeforeSwap,
|
|
256
|
-
swap.swapExchanges[0].srcAmount,
|
|
257
|
-
]),
|
|
258
|
-
isETHAddress(swap.srcToken)
|
|
259
|
-
? this.getWETHAddress(curExchangeParam)
|
|
260
|
-
: swap.srcToken.toLowerCase(),
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
swapCallData = hexConcat([transferCallData, swapCallData]);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (
|
|
267
|
-
flags.dexes[index] % 4 !== 1 && // not sendEth
|
|
268
|
-
(!isETHAddress(swap.srcToken) ||
|
|
269
|
-
(isETHAddress(swap.srcToken) && index !== 0)) &&
|
|
270
|
-
!curExchangeParam.transferSrcTokenBeforeSwap &&
|
|
271
|
-
curExchangeParam.approveData
|
|
272
|
-
) {
|
|
273
|
-
const approveCallData = this.buildApproveCallData(
|
|
274
|
-
curExchangeParam.approveData.target,
|
|
275
|
-
curExchangeParam.approveData.token,
|
|
276
|
-
flags.approves[index],
|
|
277
|
-
);
|
|
278
|
-
|
|
279
|
-
swapCallData = hexConcat([approveCallData, swapCallData]);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (curExchangeParam.needWrapNative && maybeWethCallData) {
|
|
283
|
-
if (maybeWethCallData.deposit && isETHAddress(swap.srcToken)) {
|
|
284
|
-
const prevExchangeParam = exchangeParams[index - 1];
|
|
285
|
-
|
|
286
|
-
if (
|
|
287
|
-
!prevExchangeParam ||
|
|
288
|
-
(prevExchangeParam && !prevExchangeParam.needWrapNative)
|
|
289
|
-
) {
|
|
290
|
-
let approveWethCalldata = '0x';
|
|
291
|
-
if (
|
|
292
|
-
curExchangeParam.approveData &&
|
|
293
|
-
!curExchangeParam.transferSrcTokenBeforeSwap
|
|
294
|
-
) {
|
|
295
|
-
approveWethCalldata = this.buildApproveCallData(
|
|
296
|
-
curExchangeParam.approveData.target,
|
|
297
|
-
curExchangeParam.approveData.token,
|
|
298
|
-
flags.approves[index],
|
|
299
|
-
);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
const depositCallData = this.buildWrapEthCallData(
|
|
303
|
-
this.getWETHAddress(curExchangeParam),
|
|
304
|
-
maybeWethCallData.deposit.calldata,
|
|
305
|
-
Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP,
|
|
306
|
-
);
|
|
307
|
-
|
|
308
|
-
swapCallData = hexConcat([
|
|
309
|
-
approveWethCalldata,
|
|
310
|
-
depositCallData,
|
|
311
|
-
swapCallData,
|
|
312
|
-
]);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (maybeWethCallData.withdraw && isETHAddress(swap.destToken)) {
|
|
317
|
-
const nextExchangeParam = exchangeParams[index + 1];
|
|
318
|
-
|
|
319
|
-
if (
|
|
320
|
-
!nextExchangeParam ||
|
|
321
|
-
(nextExchangeParam && !nextExchangeParam.needWrapNative)
|
|
322
|
-
) {
|
|
323
|
-
const withdrawCallData = this.buildUnwrapEthCallData(
|
|
324
|
-
this.getWETHAddress(curExchangeParam),
|
|
325
|
-
maybeWethCallData.withdraw.calldata,
|
|
326
|
-
);
|
|
327
|
-
swapCallData = hexConcat([swapCallData, withdrawCallData]);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
return swapCallData;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
protected buildDexCallData(
|
|
336
|
-
params: DexCallDataParams<Executor01DexCallDataParams>,
|
|
337
|
-
): string {
|
|
338
|
-
const {
|
|
339
|
-
priceRoute,
|
|
340
|
-
exchangeParamIndex,
|
|
341
|
-
exchangeParams,
|
|
342
|
-
routeIndex,
|
|
343
|
-
swapIndex,
|
|
344
|
-
flag,
|
|
345
|
-
} = params;
|
|
346
|
-
|
|
347
|
-
const dontCheckBalanceAfterSwap = flag % 3 === 0;
|
|
348
|
-
const checkDestTokenBalanceAfterSwap = flag % 3 === 2;
|
|
349
|
-
const insertFromAmount = flag % 4 === 3 || flag % 4 === 2;
|
|
350
|
-
const exchangeParam = exchangeParams[exchangeParamIndex];
|
|
351
|
-
const swap = priceRoute.bestRoute[routeIndex].swaps[swapIndex];
|
|
352
|
-
let { exchangeData, specialDexFlag } = exchangeParam;
|
|
353
|
-
|
|
354
|
-
const returnAmountPos =
|
|
355
|
-
exchangeParam.returnAmountPos !== undefined
|
|
356
|
-
? exchangeParam.returnAmountPos
|
|
357
|
-
: DEFAULT_RETURN_AMOUNT_POS;
|
|
358
|
-
|
|
359
|
-
let destTokenPos = 0;
|
|
360
|
-
if (checkDestTokenBalanceAfterSwap && !dontCheckBalanceAfterSwap) {
|
|
361
|
-
const destTokenAddr = isETHAddress(swap.destToken)
|
|
362
|
-
? this.getWETHAddress(exchangeParam)
|
|
363
|
-
: swap.destToken.toLowerCase();
|
|
364
|
-
|
|
365
|
-
exchangeData = this.addTokenAddressToCallData(
|
|
366
|
-
exchangeData,
|
|
367
|
-
destTokenAddr,
|
|
368
|
-
);
|
|
369
|
-
const destTokenAddrIndex = exchangeData
|
|
370
|
-
.replace('0x', '')
|
|
371
|
-
.indexOf(destTokenAddr.replace('0x', ''));
|
|
372
|
-
destTokenPos = (destTokenAddrIndex - 24) / 2;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
let fromAmountPos = 0;
|
|
376
|
-
if (insertFromAmount) {
|
|
377
|
-
const fromAmount = ethers.utils.defaultAbiCoder.encode(
|
|
378
|
-
['uint256'],
|
|
379
|
-
[swap.swapExchanges[0].srcAmount],
|
|
380
|
-
);
|
|
381
|
-
|
|
382
|
-
const fromAmountIndex = exchangeData
|
|
383
|
-
.replace('0x', '')
|
|
384
|
-
.indexOf(fromAmount.replace('0x', ''));
|
|
385
|
-
|
|
386
|
-
assert(
|
|
387
|
-
fromAmountIndex !== -1,
|
|
388
|
-
'Encoding error: could not resolve position of fromAmount in exchangeData',
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
fromAmountPos = fromAmountIndex / 2;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
return this.buildCallData(
|
|
395
|
-
exchangeParam.targetExchange,
|
|
396
|
-
exchangeData,
|
|
397
|
-
fromAmountPos,
|
|
398
|
-
destTokenPos,
|
|
399
|
-
specialDexFlag || SpecialDex.DEFAULT,
|
|
400
|
-
flag,
|
|
401
|
-
undefined,
|
|
402
|
-
returnAmountPos,
|
|
403
|
-
);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
public getAddress(): string {
|
|
407
|
-
return this.dexHelper.config.data.executorsAddresses![Executors.ONE];
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
public buildByteCode(
|
|
411
|
-
priceRoute: OptimalRate,
|
|
412
|
-
exchangeParams: DexExchangeBuildParam[],
|
|
413
|
-
sender: string,
|
|
414
|
-
maybeWethCallData?: DepositWithdrawReturn,
|
|
415
|
-
): string {
|
|
416
|
-
const flags = this.buildFlags(
|
|
417
|
-
priceRoute,
|
|
418
|
-
exchangeParams,
|
|
419
|
-
maybeWethCallData,
|
|
420
|
-
);
|
|
421
|
-
|
|
422
|
-
let swapsCalldata = exchangeParams.reduce<string>(
|
|
423
|
-
(acc, ep, index) =>
|
|
424
|
-
hexConcat([
|
|
425
|
-
acc,
|
|
426
|
-
this.buildSingleSwapCallData({
|
|
427
|
-
priceRoute,
|
|
428
|
-
exchangeParams,
|
|
429
|
-
index,
|
|
430
|
-
flags,
|
|
431
|
-
sender,
|
|
432
|
-
maybeWethCallData,
|
|
433
|
-
}),
|
|
434
|
-
]),
|
|
435
|
-
'0x',
|
|
436
|
-
);
|
|
437
|
-
|
|
438
|
-
if (
|
|
439
|
-
!exchangeParams[exchangeParams.length - 1].dexFuncHasRecipient &&
|
|
440
|
-
!isETHAddress(priceRoute.destToken)
|
|
441
|
-
) {
|
|
442
|
-
const transferCallData = this.buildTransferCallData(
|
|
443
|
-
this.erc20Interface.encodeFunctionData('transfer', [
|
|
444
|
-
this.dexHelper.config.data.augustusV6Address,
|
|
445
|
-
priceRoute.destAmount,
|
|
446
|
-
]),
|
|
447
|
-
priceRoute.destToken,
|
|
448
|
-
);
|
|
449
|
-
|
|
450
|
-
swapsCalldata = hexConcat([swapsCalldata, transferCallData]);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
if (
|
|
454
|
-
(maybeWethCallData?.withdraw && isETHAddress(priceRoute.destToken)) ||
|
|
455
|
-
(!exchangeParams[exchangeParams.length - 1].dexFuncHasRecipient &&
|
|
456
|
-
isETHAddress(priceRoute.destToken))
|
|
457
|
-
) {
|
|
458
|
-
const finalSpecialFlagCalldata = this.buildFinalSpecialFlagCalldata();
|
|
459
|
-
swapsCalldata = hexConcat([swapsCalldata, finalSpecialFlagCalldata]);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
return solidityPack(
|
|
463
|
-
['bytes32', 'bytes', 'bytes'],
|
|
464
|
-
[
|
|
465
|
-
hexZeroPad(hexlify(32), 32), // calldata offset
|
|
466
|
-
hexZeroPad(
|
|
467
|
-
hexlify(hexDataLength(swapsCalldata) + BYTES_64_LENGTH), // calldata length (64 bytes = bytes12(0) + msg.sender)
|
|
468
|
-
32,
|
|
469
|
-
),
|
|
470
|
-
swapsCalldata, // // calldata
|
|
471
|
-
],
|
|
472
|
-
);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { DexExchangeBuildParam } from '../types';
|
|
3
|
+
import { OptimalRate } from '@paraswap/core';
|
|
4
|
+
import { isETHAddress } from '../utils';
|
|
5
|
+
import { DepositWithdrawReturn } from '../dex/weth/types';
|
|
6
|
+
import { Executors, Flag, SpecialDex } from './types';
|
|
7
|
+
import { BYTES_64_LENGTH, DEFAULT_RETURN_AMOUNT_POS } from './constants';
|
|
8
|
+
import {
|
|
9
|
+
DexCallDataParams,
|
|
10
|
+
ExecutorBytecodeBuilder,
|
|
11
|
+
SingleSwapCallDataParams,
|
|
12
|
+
} from './ExecutorBytecodeBuilder';
|
|
13
|
+
import { assert } from 'ts-essentials';
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
utils: { hexlify, hexDataLength, hexConcat, hexZeroPad, solidityPack },
|
|
17
|
+
} = ethers;
|
|
18
|
+
|
|
19
|
+
export type Executor01SingleSwapCallDataParams = {};
|
|
20
|
+
export type Executor01DexCallDataParams = {};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Class to build bytecode for Executor01 - simpleSwap (SINGLE_STEP) with 100% on a path and multiSwap with 100% amounts on each path (HORIZONTAL_SEQUENCE)
|
|
24
|
+
*/
|
|
25
|
+
export class Executor01BytecodeBuilder extends ExecutorBytecodeBuilder<
|
|
26
|
+
Executor01SingleSwapCallDataParams,
|
|
27
|
+
Executor01DexCallDataParams
|
|
28
|
+
> {
|
|
29
|
+
type = Executors.ONE;
|
|
30
|
+
/**
|
|
31
|
+
* Executor01 Flags:
|
|
32
|
+
* switch (flag % 4):
|
|
33
|
+
* case 0: don't instert fromAmount
|
|
34
|
+
* case 1: sendEth equal to fromAmount
|
|
35
|
+
* case 2: sendEth equal to fromAmount + insert fromAmount
|
|
36
|
+
* case 3: insert fromAmount
|
|
37
|
+
|
|
38
|
+
* switch (flag % 3):
|
|
39
|
+
* case 0: don't check balance after swap
|
|
40
|
+
* case 1: check eth balance after swap
|
|
41
|
+
* case 2: check destToken balance after swap
|
|
42
|
+
*/
|
|
43
|
+
protected buildSimpleSwapFlags(
|
|
44
|
+
priceRoute: OptimalRate,
|
|
45
|
+
exchangeParams: DexExchangeBuildParam[],
|
|
46
|
+
routeIndex: number,
|
|
47
|
+
swapIndex: number,
|
|
48
|
+
swapExchangeIndex: number,
|
|
49
|
+
exchangeParamIndex: number,
|
|
50
|
+
maybeWethCallData?: DepositWithdrawReturn,
|
|
51
|
+
): { dexFlag: Flag; approveFlag: Flag } {
|
|
52
|
+
const { srcToken, destToken } =
|
|
53
|
+
priceRoute.bestRoute[routeIndex].swaps[swapIndex];
|
|
54
|
+
const isEthSrc = isETHAddress(srcToken);
|
|
55
|
+
const isEthDest = isETHAddress(destToken);
|
|
56
|
+
|
|
57
|
+
const exchangeParam = exchangeParams[exchangeParamIndex];
|
|
58
|
+
const {
|
|
59
|
+
dexFuncHasRecipient,
|
|
60
|
+
needWrapNative,
|
|
61
|
+
specialDexFlag,
|
|
62
|
+
specialDexSupportsInsertFromAmount,
|
|
63
|
+
swappedAmountNotPresentInExchangeData,
|
|
64
|
+
preSwapUnwrapCalldata,
|
|
65
|
+
} = exchangeParam;
|
|
66
|
+
|
|
67
|
+
const needWrap = needWrapNative && isEthSrc && maybeWethCallData?.deposit;
|
|
68
|
+
const needUnwrap =
|
|
69
|
+
needWrapNative && isEthDest && maybeWethCallData?.withdraw;
|
|
70
|
+
const isSpecialDex =
|
|
71
|
+
specialDexFlag !== undefined && specialDexFlag !== SpecialDex.DEFAULT;
|
|
72
|
+
|
|
73
|
+
const forcePreventInsertFromAmount =
|
|
74
|
+
swappedAmountNotPresentInExchangeData ||
|
|
75
|
+
(isSpecialDex && !specialDexSupportsInsertFromAmount);
|
|
76
|
+
|
|
77
|
+
let dexFlag = forcePreventInsertFromAmount
|
|
78
|
+
? Flag.DONT_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP
|
|
79
|
+
: Flag.INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 0 or 3
|
|
80
|
+
let approveFlag =
|
|
81
|
+
Flag.DONT_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 0
|
|
82
|
+
|
|
83
|
+
if (isEthSrc && !needWrap) {
|
|
84
|
+
dexFlag =
|
|
85
|
+
Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP; // 5
|
|
86
|
+
} else if (isEthDest && !needUnwrap) {
|
|
87
|
+
dexFlag = forcePreventInsertFromAmount
|
|
88
|
+
? Flag.DONT_INSERT_FROM_AMOUNT_CHECK_ETH_BALANCE_AFTER_SWAP
|
|
89
|
+
: Flag.INSERT_FROM_AMOUNT_CHECK_ETH_BALANCE_AFTER_SWAP; // 4 or 7
|
|
90
|
+
} else if (!dexFuncHasRecipient || (isEthDest && needUnwrap)) {
|
|
91
|
+
dexFlag = forcePreventInsertFromAmount
|
|
92
|
+
? Flag.DONT_INSERT_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP
|
|
93
|
+
: Flag.INSERT_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP; // 8 or 11
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Actual srcToken is eth, because we'll unwrap weth before swap.
|
|
97
|
+
// Need to check balance, some dexes don't have 1:1 ETH -> custom_ETH rate
|
|
98
|
+
if (preSwapUnwrapCalldata) {
|
|
99
|
+
dexFlag =
|
|
100
|
+
Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
dexFlag,
|
|
105
|
+
approveFlag,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Executor01 Flags:
|
|
111
|
+
* switch (flag % 4):
|
|
112
|
+
* case 0: don't insert fromAmount
|
|
113
|
+
* case 1: sendEth equal to fromAmount
|
|
114
|
+
* case 2: sendEth equal to fromAmount + insert fromAmount
|
|
115
|
+
* case 3: insert fromAmount
|
|
116
|
+
|
|
117
|
+
* switch (flag % 3):
|
|
118
|
+
* case 0: don't check balance after swap
|
|
119
|
+
* case 1: check eth balance after swap
|
|
120
|
+
* case 2: check destToken balance after swap
|
|
121
|
+
*/
|
|
122
|
+
// Executor01 doesn't support mega swap routes, flags are built for multi swap routes only here
|
|
123
|
+
protected buildMultiMegaSwapFlags(
|
|
124
|
+
priceRoute: OptimalRate,
|
|
125
|
+
exchangeParams: DexExchangeBuildParam[],
|
|
126
|
+
routeIndex: number,
|
|
127
|
+
swapIndex: number,
|
|
128
|
+
swapExchangeIndex: number,
|
|
129
|
+
exchangeParamIndex: number,
|
|
130
|
+
maybeWethCallData?: DepositWithdrawReturn,
|
|
131
|
+
): { dexFlag: Flag; approveFlag: Flag } {
|
|
132
|
+
// same as for Executor02 multi flags, except forceBalanceOfCheck
|
|
133
|
+
const swap = priceRoute.bestRoute[routeIndex].swaps[swapIndex];
|
|
134
|
+
const { srcToken, destToken } = swap;
|
|
135
|
+
const exchangeParam = exchangeParams[exchangeParamIndex];
|
|
136
|
+
const {
|
|
137
|
+
dexFuncHasRecipient,
|
|
138
|
+
needWrapNative,
|
|
139
|
+
specialDexFlag,
|
|
140
|
+
specialDexSupportsInsertFromAmount,
|
|
141
|
+
swappedAmountNotPresentInExchangeData,
|
|
142
|
+
sendEthButSupportsInsertFromAmount,
|
|
143
|
+
preSwapUnwrapCalldata,
|
|
144
|
+
} = exchangeParam;
|
|
145
|
+
|
|
146
|
+
const isLastSwap =
|
|
147
|
+
swapIndex === priceRoute.bestRoute[routeIndex].swaps.length - 1;
|
|
148
|
+
const isEthSrc = isETHAddress(srcToken);
|
|
149
|
+
const isEthDest = isETHAddress(destToken);
|
|
150
|
+
|
|
151
|
+
const isSpecialDex =
|
|
152
|
+
specialDexFlag !== undefined && specialDexFlag !== SpecialDex.DEFAULT;
|
|
153
|
+
|
|
154
|
+
const forcePreventInsertFromAmount =
|
|
155
|
+
swappedAmountNotPresentInExchangeData ||
|
|
156
|
+
(isSpecialDex && !specialDexSupportsInsertFromAmount);
|
|
157
|
+
|
|
158
|
+
const needUnwrap =
|
|
159
|
+
needWrapNative && isEthDest && maybeWethCallData?.withdraw;
|
|
160
|
+
|
|
161
|
+
const forceBalanceOfCheck = isLastSwap
|
|
162
|
+
? !dexFuncHasRecipient || needUnwrap
|
|
163
|
+
: true;
|
|
164
|
+
|
|
165
|
+
const needSendEth = isEthSrc && !needWrapNative;
|
|
166
|
+
const needCheckEthBalance = isEthDest && !needWrapNative;
|
|
167
|
+
|
|
168
|
+
const needCheckSrcTokenBalanceOf = needUnwrap && !isLastSwap;
|
|
169
|
+
|
|
170
|
+
let dexFlag: Flag;
|
|
171
|
+
let approveFlag =
|
|
172
|
+
Flag.DONT_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 0
|
|
173
|
+
|
|
174
|
+
if (needSendEth) {
|
|
175
|
+
const preventInsertForSendEth =
|
|
176
|
+
forcePreventInsertFromAmount || !sendEthButSupportsInsertFromAmount;
|
|
177
|
+
dexFlag = forceBalanceOfCheck
|
|
178
|
+
? preventInsertForSendEth
|
|
179
|
+
? Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP // 5
|
|
180
|
+
: Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_PLUS_INSERT_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP // 14
|
|
181
|
+
: dexFuncHasRecipient
|
|
182
|
+
? preventInsertForSendEth
|
|
183
|
+
? Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP // 9
|
|
184
|
+
: Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_PLUS_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP // 18
|
|
185
|
+
: preventInsertForSendEth
|
|
186
|
+
? Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP // 5
|
|
187
|
+
: Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_PLUS_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 18
|
|
188
|
+
} else if (needCheckEthBalance) {
|
|
189
|
+
dexFlag =
|
|
190
|
+
needCheckSrcTokenBalanceOf || forceBalanceOfCheck
|
|
191
|
+
? forcePreventInsertFromAmount && dexFuncHasRecipient
|
|
192
|
+
? Flag.DONT_INSERT_FROM_AMOUNT_CHECK_ETH_BALANCE_AFTER_SWAP // 4
|
|
193
|
+
: Flag.INSERT_FROM_AMOUNT_CHECK_ETH_BALANCE_AFTER_SWAP // 7
|
|
194
|
+
: forcePreventInsertFromAmount && dexFuncHasRecipient
|
|
195
|
+
? Flag.DONT_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP // 0
|
|
196
|
+
: Flag.INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 3
|
|
197
|
+
} else {
|
|
198
|
+
dexFlag =
|
|
199
|
+
needCheckSrcTokenBalanceOf || forceBalanceOfCheck
|
|
200
|
+
? forcePreventInsertFromAmount
|
|
201
|
+
? Flag.DONT_INSERT_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP // 8
|
|
202
|
+
: Flag.INSERT_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP // 11
|
|
203
|
+
: forcePreventInsertFromAmount
|
|
204
|
+
? Flag.DONT_INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP // 0
|
|
205
|
+
: Flag.INSERT_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP; // 3
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Actual srcToken is eth, because we'll unwrap weth before swap.
|
|
209
|
+
// Need to check balance, some dexes don't have 1:1 ETH -> custom_ETH rate
|
|
210
|
+
if (preSwapUnwrapCalldata) {
|
|
211
|
+
dexFlag =
|
|
212
|
+
Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_CHECK_SRC_TOKEN_BALANCE_AFTER_SWAP;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
dexFlag,
|
|
217
|
+
approveFlag,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
protected buildSingleSwapCallData(
|
|
222
|
+
params: SingleSwapCallDataParams<Executor01SingleSwapCallDataParams>,
|
|
223
|
+
): string {
|
|
224
|
+
const { priceRoute, index, exchangeParams, flags, maybeWethCallData } =
|
|
225
|
+
params;
|
|
226
|
+
|
|
227
|
+
let swapCallData = '';
|
|
228
|
+
const swap = priceRoute.bestRoute[0].swaps[index];
|
|
229
|
+
const curExchangeParam = exchangeParams[index];
|
|
230
|
+
|
|
231
|
+
const dexCallData = this.buildDexCallData({
|
|
232
|
+
priceRoute,
|
|
233
|
+
routeIndex: 0,
|
|
234
|
+
swapIndex: index,
|
|
235
|
+
swapExchangeIndex: 0,
|
|
236
|
+
exchangeParams,
|
|
237
|
+
exchangeParamIndex: index,
|
|
238
|
+
isLastSwap: index === priceRoute.bestRoute[0].swaps.length - 1,
|
|
239
|
+
flag: flags.dexes[index],
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
if (curExchangeParam.preSwapUnwrapCalldata) {
|
|
243
|
+
const withdrawCallData = this.buildUnwrapEthCallData(
|
|
244
|
+
this.getWETHAddress(curExchangeParam),
|
|
245
|
+
curExchangeParam.preSwapUnwrapCalldata,
|
|
246
|
+
);
|
|
247
|
+
swapCallData = hexConcat([withdrawCallData, dexCallData]);
|
|
248
|
+
} else {
|
|
249
|
+
swapCallData = hexConcat([dexCallData]);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (curExchangeParam.transferSrcTokenBeforeSwap) {
|
|
253
|
+
const transferCallData = this.buildTransferCallData(
|
|
254
|
+
this.erc20Interface.encodeFunctionData('transfer', [
|
|
255
|
+
curExchangeParam.transferSrcTokenBeforeSwap,
|
|
256
|
+
swap.swapExchanges[0].srcAmount,
|
|
257
|
+
]),
|
|
258
|
+
isETHAddress(swap.srcToken)
|
|
259
|
+
? this.getWETHAddress(curExchangeParam)
|
|
260
|
+
: swap.srcToken.toLowerCase(),
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
swapCallData = hexConcat([transferCallData, swapCallData]);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (
|
|
267
|
+
flags.dexes[index] % 4 !== 1 && // not sendEth
|
|
268
|
+
(!isETHAddress(swap.srcToken) ||
|
|
269
|
+
(isETHAddress(swap.srcToken) && index !== 0)) &&
|
|
270
|
+
!curExchangeParam.transferSrcTokenBeforeSwap &&
|
|
271
|
+
curExchangeParam.approveData
|
|
272
|
+
) {
|
|
273
|
+
const approveCallData = this.buildApproveCallData(
|
|
274
|
+
curExchangeParam.approveData.target,
|
|
275
|
+
curExchangeParam.approveData.token,
|
|
276
|
+
flags.approves[index],
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
swapCallData = hexConcat([approveCallData, swapCallData]);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (curExchangeParam.needWrapNative && maybeWethCallData) {
|
|
283
|
+
if (maybeWethCallData.deposit && isETHAddress(swap.srcToken)) {
|
|
284
|
+
const prevExchangeParam = exchangeParams[index - 1];
|
|
285
|
+
|
|
286
|
+
if (
|
|
287
|
+
!prevExchangeParam ||
|
|
288
|
+
(prevExchangeParam && !prevExchangeParam.needWrapNative)
|
|
289
|
+
) {
|
|
290
|
+
let approveWethCalldata = '0x';
|
|
291
|
+
if (
|
|
292
|
+
curExchangeParam.approveData &&
|
|
293
|
+
!curExchangeParam.transferSrcTokenBeforeSwap
|
|
294
|
+
) {
|
|
295
|
+
approveWethCalldata = this.buildApproveCallData(
|
|
296
|
+
curExchangeParam.approveData.target,
|
|
297
|
+
curExchangeParam.approveData.token,
|
|
298
|
+
flags.approves[index],
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const depositCallData = this.buildWrapEthCallData(
|
|
303
|
+
this.getWETHAddress(curExchangeParam),
|
|
304
|
+
maybeWethCallData.deposit.calldata,
|
|
305
|
+
Flag.SEND_ETH_EQUAL_TO_FROM_AMOUNT_DONT_CHECK_BALANCE_AFTER_SWAP,
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
swapCallData = hexConcat([
|
|
309
|
+
approveWethCalldata,
|
|
310
|
+
depositCallData,
|
|
311
|
+
swapCallData,
|
|
312
|
+
]);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (maybeWethCallData.withdraw && isETHAddress(swap.destToken)) {
|
|
317
|
+
const nextExchangeParam = exchangeParams[index + 1];
|
|
318
|
+
|
|
319
|
+
if (
|
|
320
|
+
!nextExchangeParam ||
|
|
321
|
+
(nextExchangeParam && !nextExchangeParam.needWrapNative)
|
|
322
|
+
) {
|
|
323
|
+
const withdrawCallData = this.buildUnwrapEthCallData(
|
|
324
|
+
this.getWETHAddress(curExchangeParam),
|
|
325
|
+
maybeWethCallData.withdraw.calldata,
|
|
326
|
+
);
|
|
327
|
+
swapCallData = hexConcat([swapCallData, withdrawCallData]);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return swapCallData;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
protected buildDexCallData(
|
|
336
|
+
params: DexCallDataParams<Executor01DexCallDataParams>,
|
|
337
|
+
): string {
|
|
338
|
+
const {
|
|
339
|
+
priceRoute,
|
|
340
|
+
exchangeParamIndex,
|
|
341
|
+
exchangeParams,
|
|
342
|
+
routeIndex,
|
|
343
|
+
swapIndex,
|
|
344
|
+
flag,
|
|
345
|
+
} = params;
|
|
346
|
+
|
|
347
|
+
const dontCheckBalanceAfterSwap = flag % 3 === 0;
|
|
348
|
+
const checkDestTokenBalanceAfterSwap = flag % 3 === 2;
|
|
349
|
+
const insertFromAmount = flag % 4 === 3 || flag % 4 === 2;
|
|
350
|
+
const exchangeParam = exchangeParams[exchangeParamIndex];
|
|
351
|
+
const swap = priceRoute.bestRoute[routeIndex].swaps[swapIndex];
|
|
352
|
+
let { exchangeData, specialDexFlag } = exchangeParam;
|
|
353
|
+
|
|
354
|
+
const returnAmountPos =
|
|
355
|
+
exchangeParam.returnAmountPos !== undefined
|
|
356
|
+
? exchangeParam.returnAmountPos
|
|
357
|
+
: DEFAULT_RETURN_AMOUNT_POS;
|
|
358
|
+
|
|
359
|
+
let destTokenPos = 0;
|
|
360
|
+
if (checkDestTokenBalanceAfterSwap && !dontCheckBalanceAfterSwap) {
|
|
361
|
+
const destTokenAddr = isETHAddress(swap.destToken)
|
|
362
|
+
? this.getWETHAddress(exchangeParam)
|
|
363
|
+
: swap.destToken.toLowerCase();
|
|
364
|
+
|
|
365
|
+
exchangeData = this.addTokenAddressToCallData(
|
|
366
|
+
exchangeData,
|
|
367
|
+
destTokenAddr,
|
|
368
|
+
);
|
|
369
|
+
const destTokenAddrIndex = exchangeData
|
|
370
|
+
.replace('0x', '')
|
|
371
|
+
.indexOf(destTokenAddr.replace('0x', ''));
|
|
372
|
+
destTokenPos = (destTokenAddrIndex - 24) / 2;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
let fromAmountPos = 0;
|
|
376
|
+
if (insertFromAmount) {
|
|
377
|
+
const fromAmount = ethers.utils.defaultAbiCoder.encode(
|
|
378
|
+
['uint256'],
|
|
379
|
+
[swap.swapExchanges[0].srcAmount],
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
const fromAmountIndex = exchangeData
|
|
383
|
+
.replace('0x', '')
|
|
384
|
+
.indexOf(fromAmount.replace('0x', ''));
|
|
385
|
+
|
|
386
|
+
assert(
|
|
387
|
+
fromAmountIndex !== -1,
|
|
388
|
+
'Encoding error: could not resolve position of fromAmount in exchangeData',
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
fromAmountPos = fromAmountIndex / 2;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return this.buildCallData(
|
|
395
|
+
exchangeParam.targetExchange,
|
|
396
|
+
exchangeData,
|
|
397
|
+
fromAmountPos,
|
|
398
|
+
destTokenPos,
|
|
399
|
+
specialDexFlag || SpecialDex.DEFAULT,
|
|
400
|
+
flag,
|
|
401
|
+
undefined,
|
|
402
|
+
returnAmountPos,
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
public getAddress(): string {
|
|
407
|
+
return this.dexHelper.config.data.executorsAddresses![Executors.ONE];
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
public buildByteCode(
|
|
411
|
+
priceRoute: OptimalRate,
|
|
412
|
+
exchangeParams: DexExchangeBuildParam[],
|
|
413
|
+
sender: string,
|
|
414
|
+
maybeWethCallData?: DepositWithdrawReturn,
|
|
415
|
+
): string {
|
|
416
|
+
const flags = this.buildFlags(
|
|
417
|
+
priceRoute,
|
|
418
|
+
exchangeParams,
|
|
419
|
+
maybeWethCallData,
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
let swapsCalldata = exchangeParams.reduce<string>(
|
|
423
|
+
(acc, ep, index) =>
|
|
424
|
+
hexConcat([
|
|
425
|
+
acc,
|
|
426
|
+
this.buildSingleSwapCallData({
|
|
427
|
+
priceRoute,
|
|
428
|
+
exchangeParams,
|
|
429
|
+
index,
|
|
430
|
+
flags,
|
|
431
|
+
sender,
|
|
432
|
+
maybeWethCallData,
|
|
433
|
+
}),
|
|
434
|
+
]),
|
|
435
|
+
'0x',
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
if (
|
|
439
|
+
!exchangeParams[exchangeParams.length - 1].dexFuncHasRecipient &&
|
|
440
|
+
!isETHAddress(priceRoute.destToken)
|
|
441
|
+
) {
|
|
442
|
+
const transferCallData = this.buildTransferCallData(
|
|
443
|
+
this.erc20Interface.encodeFunctionData('transfer', [
|
|
444
|
+
this.dexHelper.config.data.augustusV6Address,
|
|
445
|
+
priceRoute.destAmount,
|
|
446
|
+
]),
|
|
447
|
+
priceRoute.destToken,
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
swapsCalldata = hexConcat([swapsCalldata, transferCallData]);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (
|
|
454
|
+
(maybeWethCallData?.withdraw && isETHAddress(priceRoute.destToken)) ||
|
|
455
|
+
(!exchangeParams[exchangeParams.length - 1].dexFuncHasRecipient &&
|
|
456
|
+
isETHAddress(priceRoute.destToken))
|
|
457
|
+
) {
|
|
458
|
+
const finalSpecialFlagCalldata = this.buildFinalSpecialFlagCalldata();
|
|
459
|
+
swapsCalldata = hexConcat([swapsCalldata, finalSpecialFlagCalldata]);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return solidityPack(
|
|
463
|
+
['bytes32', 'bytes', 'bytes'],
|
|
464
|
+
[
|
|
465
|
+
hexZeroPad(hexlify(32), 32), // calldata offset
|
|
466
|
+
hexZeroPad(
|
|
467
|
+
hexlify(hexDataLength(swapsCalldata) + BYTES_64_LENGTH), // calldata length (64 bytes = bytes12(0) + msg.sender)
|
|
468
|
+
32,
|
|
469
|
+
),
|
|
470
|
+
swapsCalldata, // // calldata
|
|
471
|
+
],
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
}
|