@paraswap/dex-lib 2.16.4 → 2.16.5-direct-swaps.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/abi/DirectSwap.json +970 -0
- package/build/abi/woo-fi/WooFeeManager.abi.json +318 -0
- package/build/abi/woo-fi/WooPP.abi.json +548 -0
- package/build/abi/woo-fi/Wooracle.abi.json +260 -0
- package/build/config.js +6 -6
- package/build/dex/aave-v3/tokens/arbitrum.json +50 -0
- package/build/dex/aave-v3/tokens/avalanche.json +74 -0
- package/build/dex/aave-v3/tokens/fantom.json +62 -0
- package/build/dex/aave-v3/tokens/optimism.json +50 -0
- package/build/dex/aave-v3/tokens/polygon.json +116 -0
- package/build/dex/balancer-v2/balancer-v2.d.ts +9 -3
- package/build/dex/balancer-v2/balancer-v2.js +81 -0
- package/build/dex/balancer-v2/balancer-v2.js.map +1 -1
- package/build/dex/balancer-v2/constants.d.ts +4 -0
- package/build/dex/balancer-v2/constants.js +6 -1
- package/build/dex/balancer-v2/constants.js.map +1 -1
- package/build/dex/balancer-v2/types.d.ts +18 -1
- package/build/dex/balancer-v2/types.js.map +1 -1
- package/build/dex/curve-v1/constants.d.ts +1 -0
- package/build/dex/curve-v1/constants.js +2 -1
- package/build/dex/curve-v1/constants.js.map +1 -1
- package/build/dex/curve-v1/curve-v1.d.ts +9 -3
- package/build/dex/curve-v1/curve-v1.js +90 -4
- package/build/dex/curve-v1/curve-v1.js.map +1 -1
- package/build/dex/curve-v1/types.d.ts +23 -0
- package/build/dex/curve-v1/types.js +6 -1
- package/build/dex/curve-v1/types.js.map +1 -1
- package/build/dex/curve-v1-factory/constants.d.ts +1 -0
- package/build/dex/curve-v1-factory/constants.js +2 -1
- package/build/dex/curve-v1-factory/constants.js.map +1 -1
- package/build/dex/curve-v1-factory/curve-v1-factory.d.ts +11 -4
- package/build/dex/curve-v1-factory/curve-v1-factory.js +85 -0
- package/build/dex/curve-v1-factory/curve-v1-factory.js.map +1 -1
- package/build/dex/curve-v1-factory/types.d.ts +23 -0
- package/build/dex/curve-v1-factory/types.js +6 -1
- package/build/dex/curve-v1-factory/types.js.map +1 -1
- package/build/dex/curve-v2.d.ts +28 -7
- package/build/dex/curve-v2.js +89 -1
- package/build/dex/curve-v2.js.map +1 -1
- package/build/dex/idex.d.ts +1 -1
- package/build/dex/quickswap-v3.d.ts +21 -0
- package/build/dex/quickswap-v3.js +40 -0
- package/build/dex/quickswap-v3.js.map +1 -0
- package/build/dex/simple-exchange.d.ts +2 -0
- package/build/dex/simple-exchange.js +1 -0
- package/build/dex/simple-exchange.js.map +1 -1
- package/build/dex/test-dex/config.d.ts +4 -0
- package/build/dex/test-dex/config.js +15 -0
- package/build/dex/test-dex/config.js.map +1 -0
- package/build/dex/test-dex/test-dex-pool.d.ts +39 -0
- package/build/dex/test-dex/test-dex-pool.js +63 -0
- package/build/dex/test-dex/test-dex-pool.js.map +1 -0
- package/build/dex/test-dex/test-dex.d.ts +37 -0
- package/build/dex/test-dex/test-dex.js +126 -0
- package/build/dex/test-dex/test-dex.js.map +1 -0
- package/build/dex/test-dex/types.d.ts +6 -0
- package/build/dex/test-dex/types.js +3 -0
- package/build/dex/test-dex/types.js.map +1 -0
- package/build/dex/uniswap-v2/uniswap-v2.d.ts +1 -1
- package/build/dex/uniswap-v2/uniswap-v2.js +1 -1
- package/build/dex/uniswap-v2/uniswap-v2.js.map +1 -1
- package/build/dex/uniswap-v3/constants.d.ts +4 -0
- package/build/dex/uniswap-v3/constants.js +6 -1
- package/build/dex/uniswap-v3/constants.js.map +1 -1
- package/build/dex/uniswap-v3/types.d.ts +20 -3
- package/build/dex/uniswap-v3/types.js.map +1 -1
- package/build/dex/uniswap-v3/uniswap-v3.d.ts +7 -1
- package/build/dex/uniswap-v3/uniswap-v3.js +85 -1
- package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
- package/build/dex/woo-fi/config.d.ts +4 -0
- package/build/dex/woo-fi/config.js +141 -0
- package/build/dex/woo-fi/config.js.map +1 -0
- package/build/dex/woo-fi/constants.d.ts +5 -0
- package/build/dex/woo-fi/constants.js +20 -0
- package/build/dex/woo-fi/constants.js.map +1 -0
- package/build/dex/woo-fi/types.d.ts +48 -0
- package/build/dex/woo-fi/types.js +3 -0
- package/build/dex/woo-fi/types.js.map +1 -0
- package/build/dex/woo-fi/woo-fi-decimal-math.d.ts +14 -0
- package/build/dex/woo-fi/woo-fi-decimal-math.js +42 -0
- package/build/dex/woo-fi/woo-fi-decimal-math.js.map +1 -0
- package/build/dex/woo-fi/woo-fi-math.d.ts +31 -0
- package/build/dex/woo-fi/woo-fi-math.js +300 -0
- package/build/dex/woo-fi/woo-fi-math.js.map +1 -0
- package/build/dex/woo-fi/woo-fi.d.ts +65 -0
- package/build/dex/woo-fi/woo-fi.js +480 -0
- package/build/dex/woo-fi/woo-fi.js.map +1 -0
- package/build/dex/woo-fi-v2/woo-fi-math.d.ts +16 -0
- package/build/dex/woo-fi-v2/woo-fi-math.js +137 -0
- package/build/dex/woo-fi-v2/woo-fi-math.js.map +1 -0
- package/build/dex/zerox/index.d.ts +1 -1
- package/build/dex/zerox/index.js +1 -1
- package/build/dex/zerox/index.js.map +1 -1
- package/build/implementations/local-paraswap-sdk.js +5 -1
- package/build/implementations/local-paraswap-sdk.js.map +1 -1
- package/build/router/directswap.js +3 -1
- package/build/router/directswap.js.map +1 -1
- package/build/router/index.js.map +1 -1
- package/build/types.d.ts +1 -0
- package/package.json +5 -3
- package/src/abi/DirectSwap.json +970 -0
- package/src/config.ts +6 -6
- package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +71 -0
- package/src/dex/balancer-v2/balancer-v2.ts +150 -3
- package/src/dex/balancer-v2/constants.ts +5 -0
- package/src/dex/balancer-v2/types.ts +19 -1
- package/src/dex/curve-v1/constants.ts +2 -0
- package/src/dex/curve-v1/curve-v1-e2e.test.ts +57 -0
- package/src/dex/curve-v1/curve-v1.ts +142 -5
- package/src/dex/curve-v1/types.ts +25 -0
- package/src/dex/curve-v1-factory/constants.ts +2 -0
- package/src/dex/curve-v1-factory/curve-v1-factory-e2e.test.ts +1 -0
- package/src/dex/curve-v1-factory/curve-v1-factory.ts +138 -4
- package/src/dex/curve-v1-factory/types.ts +25 -0
- package/src/dex/curve-v2.ts +166 -8
- package/src/dex/generic-rfq/generic-rfq-e2e.test.ts +2 -2
- package/src/dex/idex.ts +6 -0
- package/src/dex/simple-exchange.ts +6 -0
- package/src/dex/uniswap-v2/uniswap-v2.ts +6 -0
- package/src/dex/uniswap-v3/constants.ts +5 -0
- package/src/dex/uniswap-v3/types.ts +23 -3
- package/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +100 -2
- package/src/dex/uniswap-v3/uniswap-v3.ts +138 -3
- package/src/dex/zerox/index.ts +7 -0
- package/src/implementations/local-paraswap-sdk.ts +8 -1
- package/src/router/directswap.ts +9 -0
- package/src/router/index.ts +0 -2
- package/src/types.ts +1 -0
- package/tests/constants-e2e.ts +3 -3
- package/tests/utils-e2e.ts +135 -20
- package/tests/utils.ts +52 -0
package/src/config.ts
CHANGED
|
@@ -158,8 +158,8 @@ const baseConfigs: { [network: number]: BaseConfig } = {
|
|
|
158
158
|
process.env[`HASHFLOW_DISABLED_MMS_56`]?.split(',') || [],
|
|
159
159
|
adapterAddresses: {
|
|
160
160
|
BscAdapter01: '0xA31d9C571DF00e0F428B0bD24c34D103E8112222',
|
|
161
|
-
BscAdapter02: '
|
|
162
|
-
BscBuyAdapter: '
|
|
161
|
+
BscAdapter02: '0x1d2Fd92a1942A92a51198168eFCd626ed441CEC0',
|
|
162
|
+
BscBuyAdapter: '0x64C856fafE4C83a818514cBDfD661a3563a71B98',
|
|
163
163
|
},
|
|
164
164
|
rpcPollingMaxAllowedStateDelayInBlocks: 1,
|
|
165
165
|
rpcPollingBlocksBackToTriggerUpdate: 1,
|
|
@@ -213,8 +213,8 @@ const baseConfigs: { [network: number]: BaseConfig } = {
|
|
|
213
213
|
process.env[`HASHFLOW_DISABLED_MMS_43114`]?.split(',') || [],
|
|
214
214
|
adapterAddresses: {
|
|
215
215
|
AvalancheAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9',
|
|
216
|
-
AvalancheAdapter02: '
|
|
217
|
-
AvalancheBuyAdapter: '
|
|
216
|
+
AvalancheAdapter02: '0xa003dFBA51C9e1e56C67ae445b852bdEd7aC5EEd',
|
|
217
|
+
AvalancheBuyAdapter: '0xfa072107a2CCfE5664794282EF36400735ABB70F',
|
|
218
218
|
},
|
|
219
219
|
uniswapV2ExchangeRouterAddress:
|
|
220
220
|
'0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b',
|
|
@@ -267,8 +267,8 @@ const baseConfigs: { [network: number]: BaseConfig } = {
|
|
|
267
267
|
process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [],
|
|
268
268
|
adapterAddresses: {
|
|
269
269
|
ArbitrumAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9',
|
|
270
|
-
ArbitrumAdapter02: '
|
|
271
|
-
ArbitrumBuyAdapter: '
|
|
270
|
+
ArbitrumAdapter02: '0x3ad7f275E27AC579cA88e0b4765828242A9E8C49',
|
|
271
|
+
ArbitrumBuyAdapter: '0x6c33C7f6CBB4a428fe9ee31ca500a787c9f1525b',
|
|
272
272
|
},
|
|
273
273
|
uniswapV2ExchangeRouterAddress:
|
|
274
274
|
'0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC',
|
|
@@ -405,6 +405,77 @@ describe('BalancerV2 E2E', () => {
|
|
|
405
405
|
//});
|
|
406
406
|
});
|
|
407
407
|
|
|
408
|
+
describe('BalancerV2 Polygon', () => {
|
|
409
|
+
const dexKey = 'BalancerV2';
|
|
410
|
+
const network = Network.POLYGON;
|
|
411
|
+
const tokens = Tokens[Network.POLYGON];
|
|
412
|
+
const holders = Holders[Network.POLYGON];
|
|
413
|
+
const provider = new StaticJsonRpcProvider(
|
|
414
|
+
generateConfig(network).privateHttpProvider,
|
|
415
|
+
network,
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
const sideToContractMethods = new Map([
|
|
419
|
+
[
|
|
420
|
+
SwapSide.SELL,
|
|
421
|
+
[
|
|
422
|
+
ContractMethod.simpleSwap,
|
|
423
|
+
ContractMethod.multiSwap,
|
|
424
|
+
ContractMethod.megaSwap,
|
|
425
|
+
ContractMethod.directBalancerV2GivenInSwap,
|
|
426
|
+
],
|
|
427
|
+
],
|
|
428
|
+
]);
|
|
429
|
+
|
|
430
|
+
const pairs: { name: string; sellAmount: string }[][] = [
|
|
431
|
+
[
|
|
432
|
+
{ name: 'WMATIC', sellAmount: '1000000000000000000' },
|
|
433
|
+
{ name: 'stMATIC', sellAmount: '1000000000000000000' },
|
|
434
|
+
],
|
|
435
|
+
[
|
|
436
|
+
{ name: 'MATIC', sellAmount: '1000000000000000000' },
|
|
437
|
+
{ name: 'stMATIC', sellAmount: '1000000000000000000' },
|
|
438
|
+
],
|
|
439
|
+
];
|
|
440
|
+
|
|
441
|
+
sideToContractMethods.forEach((contractMethods, side) =>
|
|
442
|
+
describe(`${side}`, () => {
|
|
443
|
+
contractMethods.forEach((contractMethod: ContractMethod) => {
|
|
444
|
+
pairs.forEach(pair => {
|
|
445
|
+
describe(`${contractMethod}`, () => {
|
|
446
|
+
it(`${pair[0].name} -> ${pair[1].name}`, async () => {
|
|
447
|
+
await testE2E(
|
|
448
|
+
tokens[pair[0].name],
|
|
449
|
+
tokens[pair[1].name],
|
|
450
|
+
holders[pair[0].name],
|
|
451
|
+
pair[0].sellAmount,
|
|
452
|
+
side,
|
|
453
|
+
dexKey,
|
|
454
|
+
contractMethod,
|
|
455
|
+
network,
|
|
456
|
+
provider,
|
|
457
|
+
);
|
|
458
|
+
});
|
|
459
|
+
it(`${pair[1].name} -> ${pair[0].name}`, async () => {
|
|
460
|
+
await testE2E(
|
|
461
|
+
tokens[pair[1].name],
|
|
462
|
+
tokens[pair[0].name],
|
|
463
|
+
holders[pair[1].name],
|
|
464
|
+
pair[1].sellAmount,
|
|
465
|
+
side,
|
|
466
|
+
dexKey,
|
|
467
|
+
contractMethod,
|
|
468
|
+
network,
|
|
469
|
+
provider,
|
|
470
|
+
);
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
}),
|
|
476
|
+
);
|
|
477
|
+
});
|
|
478
|
+
|
|
408
479
|
describe('BalancerV2 ARBITRUM', () => {
|
|
409
480
|
const dexKey = 'BalancerV2';
|
|
410
481
|
const network = Network.ARBITRUM;
|
|
@@ -11,6 +11,9 @@ import {
|
|
|
11
11
|
SimpleExchangeParam,
|
|
12
12
|
PoolLiquidity,
|
|
13
13
|
Logger,
|
|
14
|
+
TxInfo,
|
|
15
|
+
PreprocessTransactionOptions,
|
|
16
|
+
ExchangeTxInfo,
|
|
14
17
|
} from '../../types';
|
|
15
18
|
import {
|
|
16
19
|
SwapSide,
|
|
@@ -26,8 +29,13 @@ import { StablePool, WeightedPool } from './balancer-v2-pool';
|
|
|
26
29
|
import { PhantomStablePool } from './PhantomStablePool';
|
|
27
30
|
import { LinearPool } from './LinearPool';
|
|
28
31
|
import VaultABI from '../../abi/balancer-v2/vault.json';
|
|
32
|
+
import DirectSwapABI from '../../abi/DirectSwap.json';
|
|
29
33
|
import { StatefulEventSubscriber } from '../../stateful-event-subscriber';
|
|
30
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
getDexKeysWithNetwork,
|
|
36
|
+
getBigIntPow,
|
|
37
|
+
uuidToBytes16,
|
|
38
|
+
} from '../../utils';
|
|
31
39
|
import { IDex } from '../../dex/idex';
|
|
32
40
|
import { IDexHelper } from '../../dex-helper';
|
|
33
41
|
import {
|
|
@@ -42,8 +50,12 @@ import {
|
|
|
42
50
|
PoolStateCache,
|
|
43
51
|
BalancerPoolTypes,
|
|
44
52
|
SubgraphPoolAddressDictionary,
|
|
53
|
+
BalancerV2DirectParam,
|
|
45
54
|
} from './types';
|
|
46
|
-
import {
|
|
55
|
+
import {
|
|
56
|
+
getLocalDeadlineAsFriendlyPlaceholder,
|
|
57
|
+
SimpleExchange,
|
|
58
|
+
} from '../simple-exchange';
|
|
47
59
|
import { BalancerConfig, Adapters } from './config';
|
|
48
60
|
import {
|
|
49
61
|
getAllPoolsUsedInPaths,
|
|
@@ -52,10 +64,12 @@ import {
|
|
|
52
64
|
poolGetPathForTokenInOut,
|
|
53
65
|
} from './utils';
|
|
54
66
|
import {
|
|
67
|
+
DirectMethods,
|
|
55
68
|
MIN_USD_LIQUIDITY_TO_FETCH,
|
|
56
69
|
STABLE_GAS_COST,
|
|
57
70
|
VARIABLE_GAS_COST_PER_CYCLE,
|
|
58
71
|
} from './constants';
|
|
72
|
+
import { NumberAsString, OptimalSwapExchange } from '@paraswap/core';
|
|
59
73
|
|
|
60
74
|
const fetchAllPools = `query ($count: Int) {
|
|
61
75
|
pools: pools(
|
|
@@ -474,13 +488,16 @@ export class BalancerV2EventPool extends StatefulEventSubscriber<PoolStateMap> {
|
|
|
474
488
|
|
|
475
489
|
export class BalancerV2
|
|
476
490
|
extends SimpleExchange
|
|
477
|
-
implements
|
|
491
|
+
implements
|
|
492
|
+
IDex<BalancerV2Data, BalancerV2DirectParam, OptimizedBalancerV2Data>
|
|
478
493
|
{
|
|
479
494
|
protected eventPools: BalancerV2EventPool;
|
|
480
495
|
|
|
481
496
|
readonly hasConstantPriceLargeAmounts = false;
|
|
482
497
|
readonly isFeeOnTransferSupported = false;
|
|
483
498
|
|
|
499
|
+
readonly directSwapIface = new Interface(DirectSwapABI);
|
|
500
|
+
|
|
484
501
|
public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
|
|
485
502
|
getDexKeysWithNetwork(BalancerConfig);
|
|
486
503
|
|
|
@@ -993,6 +1010,136 @@ export class BalancerV2
|
|
|
993
1010
|
return params;
|
|
994
1011
|
}
|
|
995
1012
|
|
|
1013
|
+
static getDirectFunctionName(): string[] {
|
|
1014
|
+
return [DirectMethods.directSell, DirectMethods.directBuy];
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
getTokenFromAddress(address: Address): Token {
|
|
1018
|
+
// In this Dex decimals are not used
|
|
1019
|
+
return { address, decimals: 0 };
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
async preProcessTransaction(
|
|
1023
|
+
optimalSwapExchange: OptimalSwapExchange<OptimizedBalancerV2Data>,
|
|
1024
|
+
srcToken: Token,
|
|
1025
|
+
_0: Token,
|
|
1026
|
+
_1: SwapSide,
|
|
1027
|
+
options: PreprocessTransactionOptions,
|
|
1028
|
+
): Promise<[OptimalSwapExchange<OptimizedBalancerV2Data>, ExchangeTxInfo]> {
|
|
1029
|
+
if (!options.isDirectMethod) {
|
|
1030
|
+
return [
|
|
1031
|
+
optimalSwapExchange,
|
|
1032
|
+
{
|
|
1033
|
+
deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()),
|
|
1034
|
+
},
|
|
1035
|
+
];
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
assert(
|
|
1039
|
+
optimalSwapExchange.data !== undefined,
|
|
1040
|
+
`preProcessTransaction: data field is missing`,
|
|
1041
|
+
);
|
|
1042
|
+
|
|
1043
|
+
let isApproved: boolean | undefined;
|
|
1044
|
+
|
|
1045
|
+
try {
|
|
1046
|
+
this.erc20Contract.options.address =
|
|
1047
|
+
this.dexHelper.config.wrapETH(srcToken).address;
|
|
1048
|
+
const allowance = await this.erc20Contract.methods
|
|
1049
|
+
.allowance(this.augustusAddress, this.vaultAddress)
|
|
1050
|
+
.call(undefined, 'latest');
|
|
1051
|
+
isApproved =
|
|
1052
|
+
BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount);
|
|
1053
|
+
} catch (e) {
|
|
1054
|
+
this.logger.error(
|
|
1055
|
+
`preProcessTransaction failed to retrieve allowance info: `,
|
|
1056
|
+
e,
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
return [
|
|
1061
|
+
{
|
|
1062
|
+
...optimalSwapExchange,
|
|
1063
|
+
data: {
|
|
1064
|
+
...optimalSwapExchange.data,
|
|
1065
|
+
isApproved,
|
|
1066
|
+
},
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()),
|
|
1070
|
+
},
|
|
1071
|
+
];
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
getDirectParam(
|
|
1075
|
+
srcToken: Address,
|
|
1076
|
+
destToken: Address,
|
|
1077
|
+
srcAmount: NumberAsString,
|
|
1078
|
+
destAmount: NumberAsString,
|
|
1079
|
+
expectedAmount: NumberAsString,
|
|
1080
|
+
data: OptimizedBalancerV2Data,
|
|
1081
|
+
side: SwapSide,
|
|
1082
|
+
permit: string,
|
|
1083
|
+
uuid: string,
|
|
1084
|
+
feePercent: NumberAsString,
|
|
1085
|
+
deadline: NumberAsString,
|
|
1086
|
+
partner: string,
|
|
1087
|
+
beneficiary: string,
|
|
1088
|
+
contractMethod?: string,
|
|
1089
|
+
): TxInfo<BalancerV2DirectParam> {
|
|
1090
|
+
if (
|
|
1091
|
+
contractMethod !== DirectMethods.directSell &&
|
|
1092
|
+
contractMethod !== DirectMethods.directBuy
|
|
1093
|
+
) {
|
|
1094
|
+
throw new Error(`Invalid contract method ${contractMethod}`);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
let isApproved: boolean = !!data.isApproved;
|
|
1098
|
+
if (data.isApproved === undefined) {
|
|
1099
|
+
this.logger.warn(`isApproved is undefined, defaulting to false`);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
const [, swaps, assets, funds, limits, _deadline] = this.getBalancerParam(
|
|
1103
|
+
srcToken,
|
|
1104
|
+
destToken,
|
|
1105
|
+
srcAmount,
|
|
1106
|
+
destAmount,
|
|
1107
|
+
data,
|
|
1108
|
+
side,
|
|
1109
|
+
);
|
|
1110
|
+
|
|
1111
|
+
const swapParams: BalancerV2DirectParam = [
|
|
1112
|
+
swaps,
|
|
1113
|
+
assets,
|
|
1114
|
+
funds,
|
|
1115
|
+
limits,
|
|
1116
|
+
expectedAmount,
|
|
1117
|
+
_deadline,
|
|
1118
|
+
feePercent,
|
|
1119
|
+
this.vaultAddress,
|
|
1120
|
+
partner,
|
|
1121
|
+
isApproved,
|
|
1122
|
+
beneficiary,
|
|
1123
|
+
permit,
|
|
1124
|
+
uuidToBytes16(uuid),
|
|
1125
|
+
];
|
|
1126
|
+
|
|
1127
|
+
const encoder = (...params: BalancerV2DirectParam) => {
|
|
1128
|
+
return this.directSwapIface.encodeFunctionData(
|
|
1129
|
+
side === SwapSide.SELL
|
|
1130
|
+
? DirectMethods.directSell
|
|
1131
|
+
: DirectMethods.directBuy,
|
|
1132
|
+
[params],
|
|
1133
|
+
);
|
|
1134
|
+
};
|
|
1135
|
+
|
|
1136
|
+
return {
|
|
1137
|
+
params: swapParams,
|
|
1138
|
+
encoder,
|
|
1139
|
+
networkFee: '0',
|
|
1140
|
+
};
|
|
1141
|
+
}
|
|
1142
|
+
|
|
996
1143
|
async getSimpleParam(
|
|
997
1144
|
srcToken: string,
|
|
998
1145
|
destToken: string,
|
|
@@ -8,3 +8,8 @@ export const STABLE_GAS_COST = 84_000;
|
|
|
8
8
|
|
|
9
9
|
// I see three pools used in trade: (57856 + 79098 + 51041) / 3 = 62665 ~ 63k
|
|
10
10
|
export const VARIABLE_GAS_COST_PER_CYCLE = 63_000;
|
|
11
|
+
|
|
12
|
+
export enum DirectMethods {
|
|
13
|
+
directSell = 'directBalancerV2GivenInSwap',
|
|
14
|
+
directBuy = 'directBalancerV2GivenOutSwap',
|
|
15
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NumberAsString } from '@paraswap/core';
|
|
1
2
|
import { Address } from '../../types';
|
|
2
3
|
|
|
3
4
|
// These should match the Balancer Pool types available on Subgraph
|
|
@@ -84,12 +85,13 @@ export type BalancerSwapV2 = {
|
|
|
84
85
|
|
|
85
86
|
export type OptimizedBalancerV2Data = {
|
|
86
87
|
swaps: BalancerSwapV2[];
|
|
88
|
+
isApproved?: boolean;
|
|
87
89
|
};
|
|
88
90
|
|
|
89
91
|
export type BalancerFunds = {
|
|
90
92
|
sender: string;
|
|
91
|
-
recipient: string;
|
|
92
93
|
fromInternalBalance: boolean;
|
|
94
|
+
recipient: string;
|
|
93
95
|
toInternalBalance: boolean;
|
|
94
96
|
};
|
|
95
97
|
|
|
@@ -116,6 +118,22 @@ export type BalancerParam = [
|
|
|
116
118
|
deadline: string,
|
|
117
119
|
];
|
|
118
120
|
|
|
121
|
+
export type BalancerV2DirectParam = [
|
|
122
|
+
swaps: BalancerSwap[],
|
|
123
|
+
assets: Address[],
|
|
124
|
+
funds: BalancerFunds,
|
|
125
|
+
limits: NumberAsString[],
|
|
126
|
+
expectedAmount: NumberAsString,
|
|
127
|
+
deadline: NumberAsString,
|
|
128
|
+
feePercent: NumberAsString,
|
|
129
|
+
vault: Address,
|
|
130
|
+
partner: Address,
|
|
131
|
+
isApproved: boolean,
|
|
132
|
+
beneficiary: Address,
|
|
133
|
+
permit: string,
|
|
134
|
+
uuid: string,
|
|
135
|
+
];
|
|
136
|
+
|
|
119
137
|
export type BalancerV2Data = {
|
|
120
138
|
poolId: string;
|
|
121
139
|
};
|
|
@@ -2,6 +2,8 @@ import { CurveV1Config } from './config';
|
|
|
2
2
|
import { SwerveConfig } from './forks/swerve/config';
|
|
3
3
|
import { CurveForksConfig } from './forks/curve-forks/config';
|
|
4
4
|
|
|
5
|
+
export const DIRECT_METHOD_NAME = 'directCurveV1Swap';
|
|
6
|
+
|
|
5
7
|
export const AllCurveForks = [
|
|
6
8
|
...Object.keys(CurveV1Config),
|
|
7
9
|
...Object.keys(CurveForksConfig),
|
|
@@ -133,6 +133,63 @@ describe('CurveV1 E2E', () => {
|
|
|
133
133
|
});
|
|
134
134
|
});
|
|
135
135
|
|
|
136
|
+
describe('CurveV1 POLYGON', () => {
|
|
137
|
+
const network = Network.POLYGON;
|
|
138
|
+
const tokens = Tokens[network];
|
|
139
|
+
const holders = Holders[network];
|
|
140
|
+
const provider = new StaticJsonRpcProvider(
|
|
141
|
+
generateConfig(network).privateHttpProvider,
|
|
142
|
+
network,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
const tokensToTest = [
|
|
146
|
+
[
|
|
147
|
+
{
|
|
148
|
+
symbol: 'USDT',
|
|
149
|
+
amount: (10 ** 8).toString(),
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
symbol: 'DAI',
|
|
153
|
+
amount: (10 ** 8).toString(),
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
const sideToContractMethods = new Map([
|
|
159
|
+
[
|
|
160
|
+
SwapSide.SELL,
|
|
161
|
+
[
|
|
162
|
+
ContractMethod.simpleSwap,
|
|
163
|
+
ContractMethod.multiSwap,
|
|
164
|
+
ContractMethod.megaSwap,
|
|
165
|
+
ContractMethod.directCurveV1Swap,
|
|
166
|
+
],
|
|
167
|
+
],
|
|
168
|
+
]);
|
|
169
|
+
|
|
170
|
+
sideToContractMethods.forEach((contractMethods, side) =>
|
|
171
|
+
contractMethods.forEach((contractMethod: ContractMethod) => {
|
|
172
|
+
tokensToTest.forEach(pair => {
|
|
173
|
+
describe(`${contractMethod}`, () => {
|
|
174
|
+
it(`${pair[0].symbol} -> ${pair[1].symbol}`, async () => {
|
|
175
|
+
await testE2E(
|
|
176
|
+
tokens[pair[0].symbol],
|
|
177
|
+
tokens[pair[1].symbol],
|
|
178
|
+
holders[pair[0].symbol],
|
|
179
|
+
side === SwapSide.SELL ? pair[0].amount : pair[1].amount,
|
|
180
|
+
side,
|
|
181
|
+
dexKey,
|
|
182
|
+
contractMethod,
|
|
183
|
+
network,
|
|
184
|
+
provider,
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}),
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
|
|
136
193
|
describe('FANTOM', () => {
|
|
137
194
|
const network = Network.FANTOM;
|
|
138
195
|
const tokens = Tokens[network];
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import { Interface, AbiCoder, JsonFragment } from '@ethersproject/abi';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { NumberAsString, OptimalSwapExchange } from '@paraswap/core';
|
|
4
|
+
import { assert } from 'ts-essentials';
|
|
2
5
|
import BigNumber from 'bignumber.js';
|
|
3
6
|
import CurveABI from '../../abi/Curve.json';
|
|
7
|
+
import DirectSwapABI from '../../abi/DirectSwap.json';
|
|
4
8
|
import { Adapters, CurveV1Config } from './config';
|
|
5
9
|
|
|
6
10
|
import {
|
|
7
11
|
AdapterExchangeParam,
|
|
8
12
|
Address,
|
|
9
13
|
ExchangePrices,
|
|
14
|
+
ExchangeTxInfo,
|
|
10
15
|
PoolLiquidity,
|
|
11
16
|
PoolPrices,
|
|
17
|
+
PreprocessTransactionOptions,
|
|
12
18
|
SimpleExchangeParam,
|
|
13
19
|
Token,
|
|
14
20
|
TransferFeeParams,
|
|
21
|
+
TxInfo,
|
|
15
22
|
} from '../../types';
|
|
16
23
|
import {
|
|
17
24
|
Network,
|
|
@@ -48,8 +55,6 @@ import { TBTCPool, address as TBTCPoolAddress } from './pools/tBTCpool';
|
|
|
48
55
|
import { USDKPool, address as USDKPoolAddress } from './pools/usdkpool';
|
|
49
56
|
import { USTPool, address as USTPoolAddress } from './pools/ustpool';
|
|
50
57
|
import { SLINKPool, address as SLINKPoolAddress } from './pools/sLinkpool';
|
|
51
|
-
|
|
52
|
-
import * as _ from 'lodash';
|
|
53
58
|
import {
|
|
54
59
|
getBigIntPow,
|
|
55
60
|
getDexKeysWithNetwork,
|
|
@@ -57,9 +62,13 @@ import {
|
|
|
57
62
|
isDestTokenTransferFeeToBeExchanged,
|
|
58
63
|
isSrcTokenTransferFeeToBeExchanged,
|
|
59
64
|
Utils,
|
|
65
|
+
uuidToBytes16,
|
|
60
66
|
} from '../../utils';
|
|
61
67
|
import { BN_0 } from '../../bignumber-constants';
|
|
62
|
-
import {
|
|
68
|
+
import {
|
|
69
|
+
getLocalDeadlineAsFriendlyPlaceholder,
|
|
70
|
+
SimpleExchange,
|
|
71
|
+
} from '../simple-exchange';
|
|
63
72
|
import { IDex } from '../idex';
|
|
64
73
|
import { IDexHelper } from '../../dex-helper';
|
|
65
74
|
import { Logger } from 'log4js';
|
|
@@ -71,9 +80,12 @@ import {
|
|
|
71
80
|
CurveV1Data,
|
|
72
81
|
TokenWithReasonableVolume,
|
|
73
82
|
CurveSwapFunctions,
|
|
83
|
+
CurveV1SwapType,
|
|
84
|
+
DirectCurveV1Param,
|
|
74
85
|
} from './types';
|
|
75
86
|
import { erc20Iface } from '../../lib/utils-interfaces';
|
|
76
87
|
import { applyTransferFee } from '../../lib/token-transfer-fee';
|
|
88
|
+
import { DIRECT_METHOD_NAME } from './constants';
|
|
77
89
|
|
|
78
90
|
const CURVE_DEFAULT_CHUNKS = 10;
|
|
79
91
|
|
|
@@ -82,7 +94,10 @@ const CURVE_POOL_GAS = 200 * 1000;
|
|
|
82
94
|
|
|
83
95
|
const coder = new AbiCoder();
|
|
84
96
|
|
|
85
|
-
export class CurveV1
|
|
97
|
+
export class CurveV1
|
|
98
|
+
extends SimpleExchange
|
|
99
|
+
implements IDex<CurveV1Data, DirectCurveV1Param>
|
|
100
|
+
{
|
|
86
101
|
exchangeRouterInterface: Interface;
|
|
87
102
|
minConversionRate = '1';
|
|
88
103
|
|
|
@@ -102,6 +117,8 @@ export class CurveV1 extends SimpleExchange implements IDex<CurveV1Data> {
|
|
|
102
117
|
|
|
103
118
|
protected disableFeeOnTransferTokenAddresses: Set<string>;
|
|
104
119
|
|
|
120
|
+
readonly directSwapIface = new Interface(DirectSwapABI);
|
|
121
|
+
|
|
105
122
|
readonly SRC_TOKEN_DEX_TRANSFERS = 1;
|
|
106
123
|
readonly DEST_TOKEN_DEX_TRANSFERS = 1;
|
|
107
124
|
|
|
@@ -840,6 +857,126 @@ export class CurveV1 extends SimpleExchange implements IDex<CurveV1Data> {
|
|
|
840
857
|
return this.adapters[side];
|
|
841
858
|
}
|
|
842
859
|
|
|
860
|
+
static getDirectFunctionName(): string[] {
|
|
861
|
+
return [DIRECT_METHOD_NAME];
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
getTokenFromAddress(address: Address): Token {
|
|
865
|
+
// In this Dex decimals are not used
|
|
866
|
+
return { address, decimals: 0 };
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
async preProcessTransaction(
|
|
870
|
+
optimalSwapExchange: OptimalSwapExchange<CurveV1Data>,
|
|
871
|
+
srcToken: Token,
|
|
872
|
+
_0: Token,
|
|
873
|
+
_1: SwapSide,
|
|
874
|
+
options: PreprocessTransactionOptions,
|
|
875
|
+
): Promise<[OptimalSwapExchange<CurveV1Data>, ExchangeTxInfo]> {
|
|
876
|
+
if (!options.isDirectMethod) {
|
|
877
|
+
return [
|
|
878
|
+
optimalSwapExchange,
|
|
879
|
+
{
|
|
880
|
+
deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()),
|
|
881
|
+
},
|
|
882
|
+
];
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
assert(
|
|
886
|
+
optimalSwapExchange.data !== undefined,
|
|
887
|
+
`preProcessTransaction: data field is missing`,
|
|
888
|
+
);
|
|
889
|
+
|
|
890
|
+
let isApproved: boolean | undefined;
|
|
891
|
+
|
|
892
|
+
try {
|
|
893
|
+
this.erc20Contract.options.address =
|
|
894
|
+
this.dexHelper.config.wrapETH(srcToken).address;
|
|
895
|
+
const allowance = await this.erc20Contract.methods
|
|
896
|
+
.allowance(this.augustusAddress, optimalSwapExchange.data.exchange)
|
|
897
|
+
.call(undefined, 'latest');
|
|
898
|
+
isApproved =
|
|
899
|
+
BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount);
|
|
900
|
+
} catch (e) {
|
|
901
|
+
this.logger.error(
|
|
902
|
+
`preProcessTransaction failed to retrieve allowance info: `,
|
|
903
|
+
e,
|
|
904
|
+
);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
return [
|
|
908
|
+
{
|
|
909
|
+
...optimalSwapExchange,
|
|
910
|
+
data: {
|
|
911
|
+
...optimalSwapExchange.data,
|
|
912
|
+
isApproved,
|
|
913
|
+
},
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()),
|
|
917
|
+
},
|
|
918
|
+
];
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
getDirectParam(
|
|
922
|
+
srcToken: Address,
|
|
923
|
+
destToken: Address,
|
|
924
|
+
srcAmount: NumberAsString,
|
|
925
|
+
destAmount: NumberAsString,
|
|
926
|
+
expectedAmount: NumberAsString,
|
|
927
|
+
data: CurveV1Data,
|
|
928
|
+
side: SwapSide,
|
|
929
|
+
permit: string,
|
|
930
|
+
uuid: string,
|
|
931
|
+
feePercent: NumberAsString,
|
|
932
|
+
deadline: NumberAsString,
|
|
933
|
+
partner: string,
|
|
934
|
+
beneficiary: string,
|
|
935
|
+
contractMethod?: string,
|
|
936
|
+
): TxInfo<DirectCurveV1Param> {
|
|
937
|
+
if (contractMethod !== DIRECT_METHOD_NAME) {
|
|
938
|
+
throw new Error(`Invalid contract method ${contractMethod}`);
|
|
939
|
+
}
|
|
940
|
+
assert(side === SwapSide.SELL, 'Buy not supported');
|
|
941
|
+
|
|
942
|
+
let isApproved: boolean = !!data.isApproved;
|
|
943
|
+
if (data.isApproved === undefined) {
|
|
944
|
+
this.logger.warn(`isApproved is undefined, defaulting to false`);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
const swapParams: DirectCurveV1Param = [
|
|
948
|
+
srcToken,
|
|
949
|
+
destToken,
|
|
950
|
+
data.exchange,
|
|
951
|
+
srcAmount,
|
|
952
|
+
destAmount,
|
|
953
|
+
expectedAmount,
|
|
954
|
+
feePercent,
|
|
955
|
+
data.i.toString(),
|
|
956
|
+
data.j.toString(),
|
|
957
|
+
partner,
|
|
958
|
+
isApproved,
|
|
959
|
+
data.underlyingSwap
|
|
960
|
+
? CurveV1SwapType.EXCHANGE_UNDERLYING
|
|
961
|
+
: CurveV1SwapType.EXCHANGE,
|
|
962
|
+
beneficiary,
|
|
963
|
+
permit,
|
|
964
|
+
uuidToBytes16(uuid),
|
|
965
|
+
];
|
|
966
|
+
|
|
967
|
+
const encoder = (...params: DirectCurveV1Param) => {
|
|
968
|
+
return this.directSwapIface.encodeFunctionData(DIRECT_METHOD_NAME, [
|
|
969
|
+
params,
|
|
970
|
+
]);
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
return {
|
|
974
|
+
params: swapParams,
|
|
975
|
+
encoder,
|
|
976
|
+
networkFee: '0',
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
|
|
843
980
|
async getSimpleParam(
|
|
844
981
|
srcToken: string,
|
|
845
982
|
destToken: string,
|
|
@@ -943,7 +1080,7 @@ export class CurveV1 extends SimpleExchange implements IDex<CurveV1Data> {
|
|
|
943
1080
|
// the balances array in the pool as it was a mess to have each curve abi
|
|
944
1081
|
// Some have balances[uint128] some have balances[uint256]
|
|
945
1082
|
// One of the consequence for such a hack is below for ETH Pools
|
|
946
|
-
// TODO: below can be highly
|
|
1083
|
+
// TODO: below can be highly optimized
|
|
947
1084
|
// * we don't need to query token decimals every iteration
|
|
948
1085
|
// * we can use the decimals from the tokens list using the api
|
|
949
1086
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NumberAsString } from '@paraswap/core';
|
|
1
2
|
import { Address, Token } from '../../types';
|
|
2
3
|
|
|
3
4
|
export type CurveV1Data = {
|
|
@@ -6,6 +7,7 @@ export type CurveV1Data = {
|
|
|
6
7
|
j: number;
|
|
7
8
|
underlyingSwap: boolean;
|
|
8
9
|
deadline: number;
|
|
10
|
+
isApproved?: boolean;
|
|
9
11
|
};
|
|
10
12
|
|
|
11
13
|
export type PoolConfig = {
|
|
@@ -42,3 +44,26 @@ export enum CurveSwapFunctions {
|
|
|
42
44
|
exchange = 'exchange',
|
|
43
45
|
exchange_underlying = 'exchange_underlying',
|
|
44
46
|
}
|
|
47
|
+
|
|
48
|
+
export enum CurveV1SwapType {
|
|
49
|
+
EXCHANGE,
|
|
50
|
+
EXCHANGE_UNDERLYING,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type DirectCurveV1Param = [
|
|
54
|
+
fromToken: Address,
|
|
55
|
+
toToken: Address,
|
|
56
|
+
exchange: Address,
|
|
57
|
+
fromAmount: NumberAsString,
|
|
58
|
+
toAmount: NumberAsString,
|
|
59
|
+
expectedAmount: NumberAsString,
|
|
60
|
+
feePercent: NumberAsString,
|
|
61
|
+
i: NumberAsString,
|
|
62
|
+
j: NumberAsString,
|
|
63
|
+
partner: Address,
|
|
64
|
+
isApproved: boolean,
|
|
65
|
+
swapType: CurveV1SwapType,
|
|
66
|
+
beneficiary: Address,
|
|
67
|
+
permit: string,
|
|
68
|
+
uuid: string,
|
|
69
|
+
];
|