@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
package/src/router/simpleswap.ts
CHANGED
|
@@ -1,366 +1,366 @@
|
|
|
1
|
-
import { IRouter } from './irouter';
|
|
2
|
-
import {
|
|
3
|
-
Address,
|
|
4
|
-
OptimalRate,
|
|
5
|
-
ConstractSimpleData,
|
|
6
|
-
TxInfo,
|
|
7
|
-
SimpleExchangeParam,
|
|
8
|
-
} from '../types';
|
|
9
|
-
import { SwapSide } from '../constants';
|
|
10
|
-
import IParaswapABI from '../abi/IParaswap.json';
|
|
11
|
-
import { Interface } from '@ethersproject/abi';
|
|
12
|
-
import { isETHAddress, uuidToBytes16 } from '../utils';
|
|
13
|
-
import { Weth } from '../dex/weth/weth';
|
|
14
|
-
import { IWethDepositorWithdrawer } from '../dex/weth/types';
|
|
15
|
-
|
|
16
|
-
import { DexAdapterService } from '../dex';
|
|
17
|
-
import {
|
|
18
|
-
encodeFeePercent,
|
|
19
|
-
encodeFeePercentForReferrer,
|
|
20
|
-
encodePartnerAddressForFeeLogic,
|
|
21
|
-
} from './payload-encoder';
|
|
22
|
-
import { ParaSwapVersion } from '@paraswap/core';
|
|
23
|
-
|
|
24
|
-
type SimpleSwapParam = [ConstractSimpleData];
|
|
25
|
-
|
|
26
|
-
export type PartialContractSimpleData = Pick<
|
|
27
|
-
ConstractSimpleData,
|
|
28
|
-
'callees' | 'exchangeData' | 'values' | 'startIndexes'
|
|
29
|
-
>;
|
|
30
|
-
|
|
31
|
-
export abstract class SimpleRouterBase<RouterParam>
|
|
32
|
-
implements IRouter<RouterParam>
|
|
33
|
-
{
|
|
34
|
-
paraswapInterface: Interface;
|
|
35
|
-
|
|
36
|
-
constructor(
|
|
37
|
-
protected dexAdapterService: DexAdapterService,
|
|
38
|
-
protected side: SwapSide,
|
|
39
|
-
protected contractMethodName: string = side === SwapSide.SELL
|
|
40
|
-
? 'simpleSwap'
|
|
41
|
-
: 'simpleBuy',
|
|
42
|
-
|
|
43
|
-
// prepare mapping: network -> wrapped exchange key
|
|
44
|
-
// It assumes that no network has more than one wrapped exchange
|
|
45
|
-
protected wExchangeNetworkToKey = Weth.dexKeysWithNetwork.reduce<
|
|
46
|
-
Record<number, string>
|
|
47
|
-
>((prev, current) => {
|
|
48
|
-
for (const network of current.networks) {
|
|
49
|
-
prev[network] = current.key;
|
|
50
|
-
}
|
|
51
|
-
return prev;
|
|
52
|
-
}, {}),
|
|
53
|
-
) {
|
|
54
|
-
this.paraswapInterface = new Interface(IParaswapABI);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
getContractMethodName(): string {
|
|
58
|
-
return this.contractMethodName;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
private buildPartialContractSimpleData(
|
|
62
|
-
simpleExchangeParam: SimpleExchangeParam,
|
|
63
|
-
): PartialContractSimpleData {
|
|
64
|
-
const calldata = simpleExchangeParam.calldata;
|
|
65
|
-
let exchangeData = '0x';
|
|
66
|
-
let startIndexes = [0];
|
|
67
|
-
|
|
68
|
-
for (let i = 0; i < calldata.length; i++) {
|
|
69
|
-
const tempCalldata = calldata[i].substring(2);
|
|
70
|
-
const index = tempCalldata.length / 2;
|
|
71
|
-
startIndexes.push(startIndexes[i] + index);
|
|
72
|
-
exchangeData = exchangeData.concat(tempCalldata);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
callees: simpleExchangeParam.callees,
|
|
77
|
-
values: simpleExchangeParam.values,
|
|
78
|
-
exchangeData,
|
|
79
|
-
startIndexes,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
protected async buildCalls(
|
|
84
|
-
priceRoute: OptimalRate,
|
|
85
|
-
minMaxAmount: string,
|
|
86
|
-
): Promise<{
|
|
87
|
-
partialContractSimpleData: PartialContractSimpleData;
|
|
88
|
-
networkFee: string;
|
|
89
|
-
}> {
|
|
90
|
-
const wethAddress =
|
|
91
|
-
this.dexAdapterService.dexHelper.config.data.wrappedNativeTokenAddress;
|
|
92
|
-
|
|
93
|
-
const rawSimpleParams = await Promise.all(
|
|
94
|
-
priceRoute.bestRoute[0].swaps.flatMap((swap, swapIndex) =>
|
|
95
|
-
swap.swapExchanges.map(async se => {
|
|
96
|
-
const dex = this.dexAdapterService.getTxBuilderDexByKey(se.exchange);
|
|
97
|
-
let _src = swap.srcToken;
|
|
98
|
-
let wethDeposit = 0n;
|
|
99
|
-
let _dest = swap.destToken;
|
|
100
|
-
let wethWithdraw = 0n;
|
|
101
|
-
|
|
102
|
-
// For case of buy apply slippage is applied to srcAmount in equal proportion as the complete swap
|
|
103
|
-
// This assumes that the sum of all swaps srcAmount would sum to priceRoute.srcAmount
|
|
104
|
-
// Also that it is a direct swap.
|
|
105
|
-
const _srcAmount =
|
|
106
|
-
swapIndex > 0 ||
|
|
107
|
-
this.side === SwapSide.SELL ||
|
|
108
|
-
this.dexAdapterService.getDexKeySpecial(se.exchange) === 'zerox'
|
|
109
|
-
? se.srcAmount
|
|
110
|
-
: (
|
|
111
|
-
(BigInt(se.srcAmount) * BigInt(minMaxAmount)) /
|
|
112
|
-
BigInt(priceRoute.srcAmount)
|
|
113
|
-
).toString();
|
|
114
|
-
|
|
115
|
-
// In case of sell the destAmount is set to minimum (1) as
|
|
116
|
-
// even if the individual dex is rekt by slippage the swap
|
|
117
|
-
// should work if the final slippage check passes.
|
|
118
|
-
const _destAmount = this.side === SwapSide.SELL ? '1' : se.destAmount;
|
|
119
|
-
|
|
120
|
-
if (dex.needWrapNative) {
|
|
121
|
-
if (isETHAddress(swap.srcToken)) {
|
|
122
|
-
if (swapIndex !== 0) {
|
|
123
|
-
throw new Error('Wrap native srcToken not in swapIndex 0');
|
|
124
|
-
}
|
|
125
|
-
_src = wethAddress;
|
|
126
|
-
wethDeposit = BigInt(_srcAmount);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (isETHAddress(swap.destToken)) {
|
|
130
|
-
if (swapIndex !== priceRoute.bestRoute[0].swaps.length - 1) {
|
|
131
|
-
throw new Error('Wrap native destToken not in swapIndex last');
|
|
132
|
-
}
|
|
133
|
-
_dest = wethAddress;
|
|
134
|
-
wethWithdraw = BigInt(_destAmount);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const simpleParams = await dex.getSimpleParam?.(
|
|
139
|
-
_src,
|
|
140
|
-
_dest,
|
|
141
|
-
_srcAmount,
|
|
142
|
-
_destAmount,
|
|
143
|
-
se.data,
|
|
144
|
-
this.side,
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
return {
|
|
148
|
-
simpleParams,
|
|
149
|
-
wethDeposit,
|
|
150
|
-
wethWithdraw,
|
|
151
|
-
};
|
|
152
|
-
}),
|
|
153
|
-
),
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
const {
|
|
157
|
-
simpleExchangeDataList,
|
|
158
|
-
srcAmountWethToDeposit,
|
|
159
|
-
destAmountWethToWithdraw,
|
|
160
|
-
} = rawSimpleParams.reduce<{
|
|
161
|
-
simpleExchangeDataList: SimpleExchangeParam[];
|
|
162
|
-
srcAmountWethToDeposit: bigint;
|
|
163
|
-
destAmountWethToWithdraw: bigint;
|
|
164
|
-
}>(
|
|
165
|
-
(acc, se) => {
|
|
166
|
-
acc.srcAmountWethToDeposit += BigInt(se.wethDeposit);
|
|
167
|
-
acc.destAmountWethToWithdraw += BigInt(se.wethWithdraw);
|
|
168
|
-
// V6 doesn't have simpleParams
|
|
169
|
-
if (se.simpleParams) {
|
|
170
|
-
acc.simpleExchangeDataList.push(se.simpleParams);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return acc;
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
simpleExchangeDataList: [],
|
|
177
|
-
srcAmountWethToDeposit: 0n,
|
|
178
|
-
destAmountWethToWithdraw: 0n,
|
|
179
|
-
},
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
const simpleExchangeDataFlat = simpleExchangeDataList.reduce(
|
|
183
|
-
(acc, se) => ({
|
|
184
|
-
callees: acc.callees.concat(se.callees),
|
|
185
|
-
calldata: acc.calldata.concat(se.calldata),
|
|
186
|
-
values: acc.values.concat(se.values),
|
|
187
|
-
networkFee: (BigInt(acc.networkFee) + BigInt(se.networkFee)).toString(),
|
|
188
|
-
}),
|
|
189
|
-
{ callees: [], values: [], calldata: [], networkFee: '0' },
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
const maybeWethCallData = this.getDepositWithdrawWethCallData(
|
|
193
|
-
srcAmountWethToDeposit,
|
|
194
|
-
destAmountWethToWithdraw,
|
|
195
|
-
);
|
|
196
|
-
|
|
197
|
-
if (maybeWethCallData) {
|
|
198
|
-
if (maybeWethCallData.deposit) {
|
|
199
|
-
simpleExchangeDataFlat.callees.unshift(
|
|
200
|
-
maybeWethCallData.deposit.callee,
|
|
201
|
-
);
|
|
202
|
-
simpleExchangeDataFlat.values.unshift(maybeWethCallData.deposit.value);
|
|
203
|
-
simpleExchangeDataFlat.calldata.unshift(
|
|
204
|
-
maybeWethCallData.deposit.calldata,
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
if (maybeWethCallData.withdraw) {
|
|
208
|
-
simpleExchangeDataFlat.callees.push(maybeWethCallData.withdraw.callee);
|
|
209
|
-
simpleExchangeDataFlat.values.push(maybeWethCallData.withdraw.value);
|
|
210
|
-
simpleExchangeDataFlat.calldata.push(
|
|
211
|
-
maybeWethCallData.withdraw.calldata,
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return {
|
|
217
|
-
partialContractSimpleData: this.buildPartialContractSimpleData(
|
|
218
|
-
simpleExchangeDataFlat,
|
|
219
|
-
),
|
|
220
|
-
networkFee: simpleExchangeDataFlat.networkFee,
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
abstract build(
|
|
225
|
-
priceRoute: OptimalRate,
|
|
226
|
-
minMaxAmount: string,
|
|
227
|
-
userAddress: Address,
|
|
228
|
-
referrerAddress: Address | undefined,
|
|
229
|
-
partnerAddress: Address,
|
|
230
|
-
partnerFeePercent: string,
|
|
231
|
-
takeSurplus: boolean,
|
|
232
|
-
beneficiary: Address,
|
|
233
|
-
permit: string,
|
|
234
|
-
deadline: string,
|
|
235
|
-
uuid: string,
|
|
236
|
-
): Promise<TxInfo<RouterParam>>;
|
|
237
|
-
|
|
238
|
-
protected getDepositWithdrawWethCallData(
|
|
239
|
-
srcAmountWeth: bigint,
|
|
240
|
-
destAmountWeth: bigint,
|
|
241
|
-
) {
|
|
242
|
-
if (srcAmountWeth === 0n && destAmountWeth === 0n) return;
|
|
243
|
-
|
|
244
|
-
return (
|
|
245
|
-
this.dexAdapterService.getTxBuilderDexByKey(
|
|
246
|
-
this.wExchangeNetworkToKey[this.dexAdapterService.network],
|
|
247
|
-
) as unknown as IWethDepositorWithdrawer
|
|
248
|
-
).getDepositWithdrawParam(
|
|
249
|
-
srcAmountWeth.toString(),
|
|
250
|
-
destAmountWeth.toString(),
|
|
251
|
-
this.side,
|
|
252
|
-
ParaSwapVersion.V5,
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
export abstract class SimpleRouter extends SimpleRouterBase<SimpleSwapParam> {
|
|
258
|
-
constructor(
|
|
259
|
-
dexAdapterService: DexAdapterService,
|
|
260
|
-
side: SwapSide,
|
|
261
|
-
contractMethodName: string,
|
|
262
|
-
) {
|
|
263
|
-
super(dexAdapterService, side, contractMethodName);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
protected validateBestRoute(priceRoute: OptimalRate): boolean {
|
|
267
|
-
return (
|
|
268
|
-
priceRoute.bestRoute.length === 1 &&
|
|
269
|
-
priceRoute.bestRoute[0].percent === 100 &&
|
|
270
|
-
priceRoute.bestRoute[0].swaps.length === 1
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
async build(
|
|
275
|
-
priceRoute: OptimalRate,
|
|
276
|
-
minMaxAmount: string,
|
|
277
|
-
userAddress: Address,
|
|
278
|
-
referrerAddress: Address | undefined,
|
|
279
|
-
partnerAddress: Address,
|
|
280
|
-
partnerFeePercent: string,
|
|
281
|
-
takeSurplus: boolean,
|
|
282
|
-
beneficiary: Address,
|
|
283
|
-
permit: string,
|
|
284
|
-
deadline: string,
|
|
285
|
-
uuid: string,
|
|
286
|
-
): Promise<TxInfo<SimpleSwapParam>> {
|
|
287
|
-
if (!this.validateBestRoute(priceRoute))
|
|
288
|
-
throw new Error(`${this.contractMethodName} invalid bestRoute`);
|
|
289
|
-
|
|
290
|
-
const { partialContractSimpleData, networkFee } = await this.buildCalls(
|
|
291
|
-
priceRoute,
|
|
292
|
-
minMaxAmount,
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
const [partner, feePercent] = referrerAddress
|
|
296
|
-
? [referrerAddress, encodeFeePercentForReferrer(this.side)]
|
|
297
|
-
: [
|
|
298
|
-
encodePartnerAddressForFeeLogic({
|
|
299
|
-
partnerAddress,
|
|
300
|
-
partnerFeePercent,
|
|
301
|
-
takeSurplus,
|
|
302
|
-
}),
|
|
303
|
-
encodeFeePercent(partnerFeePercent, takeSurplus, this.side),
|
|
304
|
-
];
|
|
305
|
-
|
|
306
|
-
const sellData: ConstractSimpleData = {
|
|
307
|
-
...partialContractSimpleData,
|
|
308
|
-
fromToken: priceRoute.srcToken,
|
|
309
|
-
toToken: priceRoute.destToken,
|
|
310
|
-
fromAmount:
|
|
311
|
-
this.side === SwapSide.SELL ? priceRoute.srcAmount : minMaxAmount,
|
|
312
|
-
toAmount:
|
|
313
|
-
this.side === SwapSide.SELL ? minMaxAmount : priceRoute.destAmount,
|
|
314
|
-
expectedAmount:
|
|
315
|
-
this.side === SwapSide.SELL
|
|
316
|
-
? priceRoute.destAmount
|
|
317
|
-
: priceRoute.srcAmount,
|
|
318
|
-
beneficiary,
|
|
319
|
-
partner,
|
|
320
|
-
feePercent,
|
|
321
|
-
permit,
|
|
322
|
-
deadline,
|
|
323
|
-
uuid: uuidToBytes16(uuid),
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
const encoder = (...params: any[]) =>
|
|
327
|
-
this.paraswapInterface.encodeFunctionData(
|
|
328
|
-
this.contractMethodName,
|
|
329
|
-
params,
|
|
330
|
-
);
|
|
331
|
-
// TODO: fix network fee
|
|
332
|
-
return {
|
|
333
|
-
encoder,
|
|
334
|
-
params: [sellData],
|
|
335
|
-
networkFee,
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
export class SimpleSwap extends SimpleRouter {
|
|
341
|
-
static isBuy = false;
|
|
342
|
-
constructor(dexAdapterService: DexAdapterService) {
|
|
343
|
-
super(dexAdapterService, SwapSide.SELL, 'simpleSwap');
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
export class SimpleBuy extends SimpleRouter {
|
|
348
|
-
static isBuy = true;
|
|
349
|
-
constructor(dexAdapterService: DexAdapterService) {
|
|
350
|
-
super(dexAdapterService, SwapSide.BUY, 'simpleBuy');
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// Need to handle special case where second swap consists entirely of
|
|
354
|
-
// AugustusRFQOrder executions
|
|
355
|
-
protected validateBestRoute(priceRoute: OptimalRate): boolean {
|
|
356
|
-
return (
|
|
357
|
-
priceRoute.bestRoute.length === 1 &&
|
|
358
|
-
priceRoute.bestRoute[0].percent === 100 &&
|
|
359
|
-
(priceRoute.bestRoute[0].swaps.length === 1 ||
|
|
360
|
-
(priceRoute.bestRoute[0].swaps.length === 2 &&
|
|
361
|
-
!priceRoute.bestRoute[0].swaps[1].swapExchanges.find(
|
|
362
|
-
se => se.exchange.toLowerCase() !== 'augustusrfqorder',
|
|
363
|
-
)))
|
|
364
|
-
);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
1
|
+
import { IRouter } from './irouter';
|
|
2
|
+
import {
|
|
3
|
+
Address,
|
|
4
|
+
OptimalRate,
|
|
5
|
+
ConstractSimpleData,
|
|
6
|
+
TxInfo,
|
|
7
|
+
SimpleExchangeParam,
|
|
8
|
+
} from '../types';
|
|
9
|
+
import { SwapSide } from '../constants';
|
|
10
|
+
import IParaswapABI from '../abi/IParaswap.json';
|
|
11
|
+
import { Interface } from '@ethersproject/abi';
|
|
12
|
+
import { isETHAddress, uuidToBytes16 } from '../utils';
|
|
13
|
+
import { Weth } from '../dex/weth/weth';
|
|
14
|
+
import { IWethDepositorWithdrawer } from '../dex/weth/types';
|
|
15
|
+
|
|
16
|
+
import { DexAdapterService } from '../dex';
|
|
17
|
+
import {
|
|
18
|
+
encodeFeePercent,
|
|
19
|
+
encodeFeePercentForReferrer,
|
|
20
|
+
encodePartnerAddressForFeeLogic,
|
|
21
|
+
} from './payload-encoder';
|
|
22
|
+
import { ParaSwapVersion } from '@paraswap/core';
|
|
23
|
+
|
|
24
|
+
type SimpleSwapParam = [ConstractSimpleData];
|
|
25
|
+
|
|
26
|
+
export type PartialContractSimpleData = Pick<
|
|
27
|
+
ConstractSimpleData,
|
|
28
|
+
'callees' | 'exchangeData' | 'values' | 'startIndexes'
|
|
29
|
+
>;
|
|
30
|
+
|
|
31
|
+
export abstract class SimpleRouterBase<RouterParam>
|
|
32
|
+
implements IRouter<RouterParam>
|
|
33
|
+
{
|
|
34
|
+
paraswapInterface: Interface;
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
protected dexAdapterService: DexAdapterService,
|
|
38
|
+
protected side: SwapSide,
|
|
39
|
+
protected contractMethodName: string = side === SwapSide.SELL
|
|
40
|
+
? 'simpleSwap'
|
|
41
|
+
: 'simpleBuy',
|
|
42
|
+
|
|
43
|
+
// prepare mapping: network -> wrapped exchange key
|
|
44
|
+
// It assumes that no network has more than one wrapped exchange
|
|
45
|
+
protected wExchangeNetworkToKey = Weth.dexKeysWithNetwork.reduce<
|
|
46
|
+
Record<number, string>
|
|
47
|
+
>((prev, current) => {
|
|
48
|
+
for (const network of current.networks) {
|
|
49
|
+
prev[network] = current.key;
|
|
50
|
+
}
|
|
51
|
+
return prev;
|
|
52
|
+
}, {}),
|
|
53
|
+
) {
|
|
54
|
+
this.paraswapInterface = new Interface(IParaswapABI);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getContractMethodName(): string {
|
|
58
|
+
return this.contractMethodName;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private buildPartialContractSimpleData(
|
|
62
|
+
simpleExchangeParam: SimpleExchangeParam,
|
|
63
|
+
): PartialContractSimpleData {
|
|
64
|
+
const calldata = simpleExchangeParam.calldata;
|
|
65
|
+
let exchangeData = '0x';
|
|
66
|
+
let startIndexes = [0];
|
|
67
|
+
|
|
68
|
+
for (let i = 0; i < calldata.length; i++) {
|
|
69
|
+
const tempCalldata = calldata[i].substring(2);
|
|
70
|
+
const index = tempCalldata.length / 2;
|
|
71
|
+
startIndexes.push(startIndexes[i] + index);
|
|
72
|
+
exchangeData = exchangeData.concat(tempCalldata);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
callees: simpleExchangeParam.callees,
|
|
77
|
+
values: simpleExchangeParam.values,
|
|
78
|
+
exchangeData,
|
|
79
|
+
startIndexes,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
protected async buildCalls(
|
|
84
|
+
priceRoute: OptimalRate,
|
|
85
|
+
minMaxAmount: string,
|
|
86
|
+
): Promise<{
|
|
87
|
+
partialContractSimpleData: PartialContractSimpleData;
|
|
88
|
+
networkFee: string;
|
|
89
|
+
}> {
|
|
90
|
+
const wethAddress =
|
|
91
|
+
this.dexAdapterService.dexHelper.config.data.wrappedNativeTokenAddress;
|
|
92
|
+
|
|
93
|
+
const rawSimpleParams = await Promise.all(
|
|
94
|
+
priceRoute.bestRoute[0].swaps.flatMap((swap, swapIndex) =>
|
|
95
|
+
swap.swapExchanges.map(async se => {
|
|
96
|
+
const dex = this.dexAdapterService.getTxBuilderDexByKey(se.exchange);
|
|
97
|
+
let _src = swap.srcToken;
|
|
98
|
+
let wethDeposit = 0n;
|
|
99
|
+
let _dest = swap.destToken;
|
|
100
|
+
let wethWithdraw = 0n;
|
|
101
|
+
|
|
102
|
+
// For case of buy apply slippage is applied to srcAmount in equal proportion as the complete swap
|
|
103
|
+
// This assumes that the sum of all swaps srcAmount would sum to priceRoute.srcAmount
|
|
104
|
+
// Also that it is a direct swap.
|
|
105
|
+
const _srcAmount =
|
|
106
|
+
swapIndex > 0 ||
|
|
107
|
+
this.side === SwapSide.SELL ||
|
|
108
|
+
this.dexAdapterService.getDexKeySpecial(se.exchange) === 'zerox'
|
|
109
|
+
? se.srcAmount
|
|
110
|
+
: (
|
|
111
|
+
(BigInt(se.srcAmount) * BigInt(minMaxAmount)) /
|
|
112
|
+
BigInt(priceRoute.srcAmount)
|
|
113
|
+
).toString();
|
|
114
|
+
|
|
115
|
+
// In case of sell the destAmount is set to minimum (1) as
|
|
116
|
+
// even if the individual dex is rekt by slippage the swap
|
|
117
|
+
// should work if the final slippage check passes.
|
|
118
|
+
const _destAmount = this.side === SwapSide.SELL ? '1' : se.destAmount;
|
|
119
|
+
|
|
120
|
+
if (dex.needWrapNative) {
|
|
121
|
+
if (isETHAddress(swap.srcToken)) {
|
|
122
|
+
if (swapIndex !== 0) {
|
|
123
|
+
throw new Error('Wrap native srcToken not in swapIndex 0');
|
|
124
|
+
}
|
|
125
|
+
_src = wethAddress;
|
|
126
|
+
wethDeposit = BigInt(_srcAmount);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (isETHAddress(swap.destToken)) {
|
|
130
|
+
if (swapIndex !== priceRoute.bestRoute[0].swaps.length - 1) {
|
|
131
|
+
throw new Error('Wrap native destToken not in swapIndex last');
|
|
132
|
+
}
|
|
133
|
+
_dest = wethAddress;
|
|
134
|
+
wethWithdraw = BigInt(_destAmount);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const simpleParams = await dex.getSimpleParam?.(
|
|
139
|
+
_src,
|
|
140
|
+
_dest,
|
|
141
|
+
_srcAmount,
|
|
142
|
+
_destAmount,
|
|
143
|
+
se.data,
|
|
144
|
+
this.side,
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
simpleParams,
|
|
149
|
+
wethDeposit,
|
|
150
|
+
wethWithdraw,
|
|
151
|
+
};
|
|
152
|
+
}),
|
|
153
|
+
),
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const {
|
|
157
|
+
simpleExchangeDataList,
|
|
158
|
+
srcAmountWethToDeposit,
|
|
159
|
+
destAmountWethToWithdraw,
|
|
160
|
+
} = rawSimpleParams.reduce<{
|
|
161
|
+
simpleExchangeDataList: SimpleExchangeParam[];
|
|
162
|
+
srcAmountWethToDeposit: bigint;
|
|
163
|
+
destAmountWethToWithdraw: bigint;
|
|
164
|
+
}>(
|
|
165
|
+
(acc, se) => {
|
|
166
|
+
acc.srcAmountWethToDeposit += BigInt(se.wethDeposit);
|
|
167
|
+
acc.destAmountWethToWithdraw += BigInt(se.wethWithdraw);
|
|
168
|
+
// V6 doesn't have simpleParams
|
|
169
|
+
if (se.simpleParams) {
|
|
170
|
+
acc.simpleExchangeDataList.push(se.simpleParams);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return acc;
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
simpleExchangeDataList: [],
|
|
177
|
+
srcAmountWethToDeposit: 0n,
|
|
178
|
+
destAmountWethToWithdraw: 0n,
|
|
179
|
+
},
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const simpleExchangeDataFlat = simpleExchangeDataList.reduce(
|
|
183
|
+
(acc, se) => ({
|
|
184
|
+
callees: acc.callees.concat(se.callees),
|
|
185
|
+
calldata: acc.calldata.concat(se.calldata),
|
|
186
|
+
values: acc.values.concat(se.values),
|
|
187
|
+
networkFee: (BigInt(acc.networkFee) + BigInt(se.networkFee)).toString(),
|
|
188
|
+
}),
|
|
189
|
+
{ callees: [], values: [], calldata: [], networkFee: '0' },
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
const maybeWethCallData = this.getDepositWithdrawWethCallData(
|
|
193
|
+
srcAmountWethToDeposit,
|
|
194
|
+
destAmountWethToWithdraw,
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
if (maybeWethCallData) {
|
|
198
|
+
if (maybeWethCallData.deposit) {
|
|
199
|
+
simpleExchangeDataFlat.callees.unshift(
|
|
200
|
+
maybeWethCallData.deposit.callee,
|
|
201
|
+
);
|
|
202
|
+
simpleExchangeDataFlat.values.unshift(maybeWethCallData.deposit.value);
|
|
203
|
+
simpleExchangeDataFlat.calldata.unshift(
|
|
204
|
+
maybeWethCallData.deposit.calldata,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (maybeWethCallData.withdraw) {
|
|
208
|
+
simpleExchangeDataFlat.callees.push(maybeWethCallData.withdraw.callee);
|
|
209
|
+
simpleExchangeDataFlat.values.push(maybeWethCallData.withdraw.value);
|
|
210
|
+
simpleExchangeDataFlat.calldata.push(
|
|
211
|
+
maybeWethCallData.withdraw.calldata,
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
partialContractSimpleData: this.buildPartialContractSimpleData(
|
|
218
|
+
simpleExchangeDataFlat,
|
|
219
|
+
),
|
|
220
|
+
networkFee: simpleExchangeDataFlat.networkFee,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
abstract build(
|
|
225
|
+
priceRoute: OptimalRate,
|
|
226
|
+
minMaxAmount: string,
|
|
227
|
+
userAddress: Address,
|
|
228
|
+
referrerAddress: Address | undefined,
|
|
229
|
+
partnerAddress: Address,
|
|
230
|
+
partnerFeePercent: string,
|
|
231
|
+
takeSurplus: boolean,
|
|
232
|
+
beneficiary: Address,
|
|
233
|
+
permit: string,
|
|
234
|
+
deadline: string,
|
|
235
|
+
uuid: string,
|
|
236
|
+
): Promise<TxInfo<RouterParam>>;
|
|
237
|
+
|
|
238
|
+
protected getDepositWithdrawWethCallData(
|
|
239
|
+
srcAmountWeth: bigint,
|
|
240
|
+
destAmountWeth: bigint,
|
|
241
|
+
) {
|
|
242
|
+
if (srcAmountWeth === 0n && destAmountWeth === 0n) return;
|
|
243
|
+
|
|
244
|
+
return (
|
|
245
|
+
this.dexAdapterService.getTxBuilderDexByKey(
|
|
246
|
+
this.wExchangeNetworkToKey[this.dexAdapterService.network],
|
|
247
|
+
) as unknown as IWethDepositorWithdrawer
|
|
248
|
+
).getDepositWithdrawParam(
|
|
249
|
+
srcAmountWeth.toString(),
|
|
250
|
+
destAmountWeth.toString(),
|
|
251
|
+
this.side,
|
|
252
|
+
ParaSwapVersion.V5,
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export abstract class SimpleRouter extends SimpleRouterBase<SimpleSwapParam> {
|
|
258
|
+
constructor(
|
|
259
|
+
dexAdapterService: DexAdapterService,
|
|
260
|
+
side: SwapSide,
|
|
261
|
+
contractMethodName: string,
|
|
262
|
+
) {
|
|
263
|
+
super(dexAdapterService, side, contractMethodName);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
protected validateBestRoute(priceRoute: OptimalRate): boolean {
|
|
267
|
+
return (
|
|
268
|
+
priceRoute.bestRoute.length === 1 &&
|
|
269
|
+
priceRoute.bestRoute[0].percent === 100 &&
|
|
270
|
+
priceRoute.bestRoute[0].swaps.length === 1
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async build(
|
|
275
|
+
priceRoute: OptimalRate,
|
|
276
|
+
minMaxAmount: string,
|
|
277
|
+
userAddress: Address,
|
|
278
|
+
referrerAddress: Address | undefined,
|
|
279
|
+
partnerAddress: Address,
|
|
280
|
+
partnerFeePercent: string,
|
|
281
|
+
takeSurplus: boolean,
|
|
282
|
+
beneficiary: Address,
|
|
283
|
+
permit: string,
|
|
284
|
+
deadline: string,
|
|
285
|
+
uuid: string,
|
|
286
|
+
): Promise<TxInfo<SimpleSwapParam>> {
|
|
287
|
+
if (!this.validateBestRoute(priceRoute))
|
|
288
|
+
throw new Error(`${this.contractMethodName} invalid bestRoute`);
|
|
289
|
+
|
|
290
|
+
const { partialContractSimpleData, networkFee } = await this.buildCalls(
|
|
291
|
+
priceRoute,
|
|
292
|
+
minMaxAmount,
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
const [partner, feePercent] = referrerAddress
|
|
296
|
+
? [referrerAddress, encodeFeePercentForReferrer(this.side)]
|
|
297
|
+
: [
|
|
298
|
+
encodePartnerAddressForFeeLogic({
|
|
299
|
+
partnerAddress,
|
|
300
|
+
partnerFeePercent,
|
|
301
|
+
takeSurplus,
|
|
302
|
+
}),
|
|
303
|
+
encodeFeePercent(partnerFeePercent, takeSurplus, this.side),
|
|
304
|
+
];
|
|
305
|
+
|
|
306
|
+
const sellData: ConstractSimpleData = {
|
|
307
|
+
...partialContractSimpleData,
|
|
308
|
+
fromToken: priceRoute.srcToken,
|
|
309
|
+
toToken: priceRoute.destToken,
|
|
310
|
+
fromAmount:
|
|
311
|
+
this.side === SwapSide.SELL ? priceRoute.srcAmount : minMaxAmount,
|
|
312
|
+
toAmount:
|
|
313
|
+
this.side === SwapSide.SELL ? minMaxAmount : priceRoute.destAmount,
|
|
314
|
+
expectedAmount:
|
|
315
|
+
this.side === SwapSide.SELL
|
|
316
|
+
? priceRoute.destAmount
|
|
317
|
+
: priceRoute.srcAmount,
|
|
318
|
+
beneficiary,
|
|
319
|
+
partner,
|
|
320
|
+
feePercent,
|
|
321
|
+
permit,
|
|
322
|
+
deadline,
|
|
323
|
+
uuid: uuidToBytes16(uuid),
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
const encoder = (...params: any[]) =>
|
|
327
|
+
this.paraswapInterface.encodeFunctionData(
|
|
328
|
+
this.contractMethodName,
|
|
329
|
+
params,
|
|
330
|
+
);
|
|
331
|
+
// TODO: fix network fee
|
|
332
|
+
return {
|
|
333
|
+
encoder,
|
|
334
|
+
params: [sellData],
|
|
335
|
+
networkFee,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export class SimpleSwap extends SimpleRouter {
|
|
341
|
+
static isBuy = false;
|
|
342
|
+
constructor(dexAdapterService: DexAdapterService) {
|
|
343
|
+
super(dexAdapterService, SwapSide.SELL, 'simpleSwap');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export class SimpleBuy extends SimpleRouter {
|
|
348
|
+
static isBuy = true;
|
|
349
|
+
constructor(dexAdapterService: DexAdapterService) {
|
|
350
|
+
super(dexAdapterService, SwapSide.BUY, 'simpleBuy');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Need to handle special case where second swap consists entirely of
|
|
354
|
+
// AugustusRFQOrder executions
|
|
355
|
+
protected validateBestRoute(priceRoute: OptimalRate): boolean {
|
|
356
|
+
return (
|
|
357
|
+
priceRoute.bestRoute.length === 1 &&
|
|
358
|
+
priceRoute.bestRoute[0].percent === 100 &&
|
|
359
|
+
(priceRoute.bestRoute[0].swaps.length === 1 ||
|
|
360
|
+
(priceRoute.bestRoute[0].swaps.length === 2 &&
|
|
361
|
+
!priceRoute.bestRoute[0].swaps[1].swapExchanges.find(
|
|
362
|
+
se => se.exchange.toLowerCase() !== 'augustusrfqorder',
|
|
363
|
+
)))
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
}
|