@paraswap/dex-lib 2.16.3 → 2.16.4-balancer-v2-buy.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.
Files changed (86) hide show
  1. package/.idea/aws.xml +17 -0
  2. package/.idea/codeStyles/Project.xml +19 -0
  3. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  4. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  5. package/.idea/misc.xml +6 -0
  6. package/.idea/modules.xml +8 -0
  7. package/.idea/paraswap-dex-lib.iml +9 -0
  8. package/.idea/vcs.xml +6 -0
  9. package/build/abi/TraderJoeV21Router.json +1489 -0
  10. package/build/config.js +10 -10
  11. package/build/dex/balancer-v2/balancer-v2.d.ts +9 -14
  12. package/build/dex/balancer-v2/balancer-v2.js +19 -16
  13. package/build/dex/balancer-v2/balancer-v2.js.map +1 -1
  14. package/build/dex/balancer-v2/config.d.ts +2 -7
  15. package/build/dex/balancer-v2/config.js +20 -30
  16. package/build/dex/balancer-v2/config.js.map +1 -1
  17. package/build/dex/balancer-v2/pools/balancer-v2-pool.d.ts +25 -0
  18. package/build/dex/balancer-v2/pools/balancer-v2-pool.js +107 -0
  19. package/build/dex/balancer-v2/pools/balancer-v2-pool.js.map +1 -0
  20. package/build/dex/balancer-v2/pools/linear/LinearMath.d.ts +20 -0
  21. package/build/dex/balancer-v2/pools/linear/LinearMath.js +186 -0
  22. package/build/dex/balancer-v2/pools/linear/LinearMath.js.map +1 -0
  23. package/build/dex/balancer-v2/pools/linear/LinearPool.d.ts +51 -0
  24. package/build/dex/balancer-v2/pools/linear/LinearPool.js +477 -0
  25. package/build/dex/balancer-v2/pools/linear/LinearPool.js.map +1 -0
  26. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStableMath.d.ts +10 -0
  27. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStableMath.js +314 -0
  28. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStableMath.js.map +1 -0
  29. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStablePool.d.ts +50 -0
  30. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStablePool.js +367 -0
  31. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStablePool.js.map +1 -0
  32. package/build/dex/balancer-v2/pools/stable/StableMath.d.ts +7 -0
  33. package/build/dex/balancer-v2/pools/stable/StableMath.js +111 -0
  34. package/build/dex/balancer-v2/pools/stable/StableMath.js.map +1 -0
  35. package/build/dex/balancer-v2/pools/stable/StablePool.d.ts +30 -0
  36. package/build/dex/balancer-v2/pools/stable/StablePool.js +129 -0
  37. package/build/dex/balancer-v2/pools/stable/StablePool.js.map +1 -0
  38. package/build/dex/balancer-v2/pools/weighted/WeightedMath.d.ts +6 -0
  39. package/build/dex/balancer-v2/pools/weighted/WeightedMath.js +61 -0
  40. package/build/dex/balancer-v2/pools/weighted/WeightedMath.js.map +1 -0
  41. package/build/dex/balancer-v2/pools/weighted/WeightedPool.d.ts +30 -0
  42. package/build/dex/balancer-v2/pools/weighted/WeightedPool.js +112 -0
  43. package/build/dex/balancer-v2/pools/weighted/WeightedPool.js.map +1 -0
  44. package/build/dex/balancer-v2/types.d.ts +1 -0
  45. package/build/dex/balancer-v2/types.js.map +1 -1
  46. package/build/dex/index.js +2 -0
  47. package/build/dex/index.js.map +1 -1
  48. package/build/dex/trader-joe-v2.1.d.ts +43 -0
  49. package/build/dex/trader-joe-v2.1.js +78 -0
  50. package/build/dex/trader-joe-v2.1.js.map +1 -0
  51. package/package.json +1 -1
  52. package/src/abi/TraderJoeV21Router.json +1489 -0
  53. package/src/config.ts +10 -10
  54. package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +207 -224
  55. package/src/dex/balancer-v2/balancer-v2.ts +41 -29
  56. package/src/dex/balancer-v2/config.ts +23 -35
  57. package/src/dex/balancer-v2/pools/balancer-v2-pool.ts +274 -0
  58. package/src/dex/balancer-v2/{LinearMath.ts → pools/linear/LinearMath.ts} +81 -23
  59. package/src/dex/balancer-v2/{LinearPool.ts → pools/linear/LinearPool.ts} +241 -5
  60. package/src/dex/balancer-v2/{StableMath.ts → pools/phantom-stable/PhantomStableMath.ts} +101 -21
  61. package/src/dex/balancer-v2/{PhantomStablePool.ts → pools/phantom-stable/PhantomStablePool.ts} +165 -11
  62. package/src/dex/balancer-v2/pools/stable/StableMath.ts +204 -0
  63. package/src/dex/balancer-v2/pools/stable/StablePool.ts +221 -0
  64. package/src/dex/balancer-v2/pools/weighted/WeightedMath.ts +84 -0
  65. package/src/dex/balancer-v2/pools/weighted/WeightedPool.ts +189 -0
  66. package/src/dex/balancer-v2/types.ts +1 -0
  67. package/src/dex/index.ts +2 -0
  68. package/src/dex/trader-joe-v2.1.ts +155 -0
  69. package/tests/constants-e2e.ts +9 -4
  70. package/build/abi/DirectSwap.json +0 -970
  71. package/build/dex/test-dex/config.d.ts +0 -4
  72. package/build/dex/test-dex/config.js +0 -15
  73. package/build/dex/test-dex/config.js.map +0 -1
  74. package/build/dex/test-dex/test-dex-pool.d.ts +0 -39
  75. package/build/dex/test-dex/test-dex-pool.js +0 -63
  76. package/build/dex/test-dex/test-dex-pool.js.map +0 -1
  77. package/build/dex/test-dex/test-dex.d.ts +0 -37
  78. package/build/dex/test-dex/test-dex.js +0 -126
  79. package/build/dex/test-dex/test-dex.js.map +0 -1
  80. package/build/dex/test-dex/types.d.ts +0 -6
  81. package/build/dex/test-dex/types.js +0 -3
  82. package/build/dex/test-dex/types.js.map +0 -1
  83. package/build/dex/woo-fi-v2/woo-fi-math.d.ts +0 -16
  84. package/build/dex/woo-fi-v2/woo-fi-math.js +0 -137
  85. package/build/dex/woo-fi-v2/woo-fi-math.js.map +0 -1
  86. package/src/dex/balancer-v2/balancer-v2-pool.ts +0 -744
@@ -2,49 +2,50 @@ import { Interface } from '@ethersproject/abi';
2
2
  import { assert, DeepReadonly } from 'ts-essentials';
3
3
  import _, { keyBy } from 'lodash';
4
4
  import {
5
- Token,
5
+ AdapterExchangeParam,
6
6
  Address,
7
7
  ExchangePrices,
8
- PoolPrices,
9
8
  Log,
10
- AdapterExchangeParam,
11
- SimpleExchangeParam,
12
- PoolLiquidity,
13
9
  Logger,
10
+ PoolLiquidity,
11
+ PoolPrices,
12
+ SimpleExchangeParam,
13
+ Token,
14
14
  } from '../../types';
15
15
  import {
16
- SwapSide,
17
16
  ETHER_ADDRESS,
18
- NULL_ADDRESS,
19
17
  MAX_INT,
20
18
  MAX_UINT,
21
19
  Network,
20
+ NULL_ADDRESS,
22
21
  SUBGRAPH_TIMEOUT,
22
+ SwapSide,
23
23
  } from '../../constants';
24
24
  import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
25
- import { StablePool, WeightedPool } from './balancer-v2-pool';
26
- import { PhantomStablePool } from './PhantomStablePool';
27
- import { LinearPool } from './LinearPool';
25
+ import { StablePool } from './pools/stable/StablePool';
26
+ import { WeightedPool } from './pools/weighted/WeightedPool';
27
+ import { PhantomStablePool } from './pools/phantom-stable/PhantomStablePool';
28
+ import { LinearPool } from './pools/linear/LinearPool';
28
29
  import VaultABI from '../../abi/balancer-v2/vault.json';
29
30
  import { StatefulEventSubscriber } from '../../stateful-event-subscriber';
30
- import { getDexKeysWithNetwork, getBigIntPow } from '../../utils';
31
+ import { getBigIntPow, getDexKeysWithNetwork } from '../../utils';
31
32
  import { IDex } from '../../dex/idex';
32
33
  import { IDexHelper } from '../../dex-helper';
33
34
  import {
34
- PoolState,
35
- SubgraphPoolBase,
36
- BalancerV2Data,
37
35
  BalancerParam,
36
+ BalancerPoolTypes,
38
37
  BalancerSwap,
38
+ BalancerV2Data,
39
39
  OptimizedBalancerV2Data,
40
- SwapTypes,
41
- PoolStateMap,
40
+ PoolState,
42
41
  PoolStateCache,
43
- BalancerPoolTypes,
42
+ PoolStateMap,
44
43
  SubgraphPoolAddressDictionary,
44
+ SubgraphPoolBase,
45
+ SwapTypes,
45
46
  } from './types';
46
47
  import { SimpleExchange } from '../simple-exchange';
47
- import { BalancerConfig, Adapters } from './config';
48
+ import { Adapters, BalancerConfig } from './config';
48
49
  import {
49
50
  getAllPoolsUsedInPaths,
50
51
  isSameAddress,
@@ -407,13 +408,22 @@ export class BalancerV2EventPool extends StatefulEventSubscriber<PoolStateMap> {
407
408
  const unitResult =
408
409
  checkedUnitVolume === 0n
409
410
  ? 0n
410
- : pool.onSell([checkedUnitVolume], poolPairData as any)[0];
411
+ : side === SwapSide.SELL
412
+ ? pool.onSell([checkedUnitVolume], poolPairData as any)[0]
413
+ : pool.onBuy([checkedUnitVolume], poolPairData as any)[0];
411
414
 
412
415
  const prices: bigint[] = new Array(amounts.length).fill(0n);
413
- const outputs = pool.onSell(
414
- amountWithoutZero.slice(0, nonZeroAmountIndex),
415
- poolPairData as any,
416
- );
416
+
417
+ const outputs =
418
+ side === SwapSide.SELL
419
+ ? pool.onSell(
420
+ amountWithoutZero.slice(0, nonZeroAmountIndex),
421
+ poolPairData as any,
422
+ )
423
+ : pool.onBuy(
424
+ amountWithoutZero.slice(0, nonZeroAmountIndex),
425
+ poolPairData as any,
426
+ );
417
427
 
418
428
  assert(
419
429
  outputs.length <= prices.length,
@@ -618,8 +628,7 @@ export class BalancerV2
618
628
  }
619
629
 
620
630
  getAdapters(side: SwapSide): { name: string; index: number }[] | null {
621
- if (side === SwapSide.BUY) return null;
622
- return this.adapters;
631
+ return this.adapters[side] ? this.adapters[side] : null;
623
632
  }
624
633
 
625
634
  async getPoolIdentifiers(
@@ -628,7 +637,6 @@ export class BalancerV2
628
637
  side: SwapSide,
629
638
  blockNumber: number,
630
639
  ): Promise<string[]> {
631
- if (side === SwapSide.BUY) return [];
632
640
  const _from = this.dexHelper.config.wrapETH(from);
633
641
  const _to = this.dexHelper.config.wrapETH(to);
634
642
 
@@ -676,7 +684,6 @@ export class BalancerV2
676
684
  blockNumber: number,
677
685
  limitPools?: string[],
678
686
  ): Promise<null | ExchangePrices<BalancerV2Data>> {
679
- if (side === SwapSide.BUY) return null;
680
687
  try {
681
688
  const _from = this.dexHelper.config.wrapETH(from);
682
689
  const _to = this.dexHelper.config.wrapETH(to);
@@ -956,7 +963,12 @@ export class BalancerV2
956
963
  poolId: hop.pool.id,
957
964
  assetInIndex: swapOffset + index,
958
965
  assetOutIndex: swapOffset + index + 1,
959
- amount: index === 0 ? swapData.amount : '0',
966
+ amount:
967
+ side === SwapSide.SELL && index === 0
968
+ ? swapData.amount
969
+ : side === SwapSide.BUY && index === path.length - 1
970
+ ? swapData.amount
971
+ : '0',
960
972
  userData: '0x',
961
973
  }));
962
974
 
@@ -983,7 +995,7 @@ export class BalancerV2
983
995
 
984
996
  const params: BalancerParam = [
985
997
  side === SwapSide.SELL ? SwapTypes.SwapExactIn : SwapTypes.SwapExactOut,
986
- swaps,
998
+ side === SwapSide.SELL ? swaps : swaps.reverse(),
987
999
  assets,
988
1000
  funds,
989
1001
  limits,
@@ -1,6 +1,6 @@
1
1
  import { DexParams } from './types';
2
- import { DexConfigMap } from '../../types';
3
- import { Network } from '../../constants';
2
+ import { AdapterMappings, DexConfigMap } from '../../types';
3
+ import { Network, SwapSide } from '../../constants';
4
4
 
5
5
  export const BalancerConfig: DexConfigMap<DexParams> = {
6
6
  BalancerV2: {
@@ -42,37 +42,25 @@ export const BalancerConfig: DexConfigMap<DexParams> = {
42
42
  // },
43
43
  };
44
44
 
45
- export const Adapters: {
46
- [chainId: number]: { name: string; index: number }[];
47
- } = {
48
- [Network.MAINNET]: [
49
- {
50
- name: 'Adapter02',
51
- index: 9,
52
- },
53
- ],
54
- [Network.POLYGON]: [
55
- {
56
- name: 'PolygonAdapter01',
57
- index: 9,
58
- },
59
- ],
60
- [Network.FANTOM]: [
61
- {
62
- name: 'FantomAdapter01',
63
- index: 5,
64
- },
65
- ],
66
- [Network.ARBITRUM]: [
67
- {
68
- name: 'ArbitrumAdapter01',
69
- index: 5,
70
- },
71
- ],
72
- [Network.OPTIMISM]: [
73
- {
74
- name: 'OptimismAdapter01',
75
- index: 4,
76
- },
77
- ],
45
+ export const Adapters: Record<number, AdapterMappings> = {
46
+ [Network.MAINNET]: {
47
+ [SwapSide.SELL]: [{ name: 'Adapter02', index: 9 }],
48
+ [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 9 }],
49
+ },
50
+ [Network.POLYGON]: {
51
+ [SwapSide.SELL]: [{ name: 'PolygonAdapter01', index: 9 }],
52
+ [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 6 }],
53
+ },
54
+ [Network.FANTOM]:{
55
+ [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 5 }],
56
+ [SwapSide.BUY]: [{ name: 'FantomBuyAdapter', index: 4 }],
57
+ },
58
+ [Network.ARBITRUM]: {
59
+ [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 5 }],
60
+ [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 6 }],
61
+ },
62
+ [Network.OPTIMISM]: {
63
+ [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 4 }],
64
+ [SwapSide.BUY]: [{ name: 'OptimismBuyAdapter', index: 5 }],
65
+ },
78
66
  };
@@ -0,0 +1,274 @@
1
+ import { MathSol } from '../balancer-v2-math';
2
+ import { WeightedPoolPairData } from './weighted/WeightedPool';
3
+ import { StablePoolPairData } from './stable/StablePool';
4
+
5
+ export class BasePool {
6
+ _subtractSwapFeeAmount(amount: bigint, _swapFeePercentage: bigint): bigint {
7
+ // This returns amount - fee amount, so we round up (favoring a higher fee amount).
8
+ const feeAmount = MathSol.mulUpFixed(amount, _swapFeePercentage);
9
+ return amount - feeAmount;
10
+ }
11
+
12
+ _addFeeAmount(amount: bigint, _swapFeePercentage: bigint): bigint {
13
+ return MathSol.divUpFixed(
14
+ amount,
15
+ MathSol.complementFixed(_swapFeePercentage),
16
+ );
17
+ }
18
+
19
+ // These methods use fixed versions to match SC scaling
20
+ _upscaleArray(amounts: bigint[], scalingFactors: bigint[]): bigint[] {
21
+ return amounts.map((a, i) => MathSol.mulUpFixed(a, scalingFactors[i]));
22
+ }
23
+
24
+ _upscale(amount: bigint, scalingFactor: bigint): bigint {
25
+ return MathSol.mulUpFixed(amount, scalingFactor);
26
+ }
27
+
28
+ _downscaleDown(amount: bigint, scalingFactor: bigint): bigint {
29
+ return MathSol.divDownFixed(amount, scalingFactor);
30
+ }
31
+
32
+ _downscaleUp(amount: bigint, scalingFactor: bigint): bigint {
33
+ return MathSol.divUpFixed(amount, scalingFactor);
34
+ }
35
+
36
+ _nullifyIfMaxAmountExceeded(amountToTrade: bigint, swapMax: bigint): bigint {
37
+ return swapMax >= amountToTrade ? amountToTrade : 0n;
38
+ }
39
+ }
40
+
41
+ export abstract class BaseGeneralPool extends BasePool {
42
+ // Swap Hooks
43
+ onBuy(amounts: bigint[], poolPairData: StablePoolPairData): bigint[] {
44
+ return this._swapGivenOut(
45
+ amounts,
46
+ poolPairData.balances,
47
+ poolPairData.indexIn,
48
+ poolPairData.indexOut,
49
+ poolPairData.scalingFactors,
50
+ poolPairData.swapFee,
51
+ poolPairData.amp,
52
+ );
53
+ }
54
+
55
+ // Modification: this is inspired from the function onSwap which is in the original contract
56
+ onSell(amounts: bigint[], poolPairData: StablePoolPairData): bigint[] {
57
+ // _validateIndexes(indexIn, indexOut, _getTotalTokens());
58
+ // uint256[] memory scalingFactors = _scalingFactors();
59
+ return this._swapGivenIn(
60
+ amounts,
61
+ poolPairData.balances,
62
+ poolPairData.indexIn,
63
+ poolPairData.indexOut,
64
+ poolPairData.scalingFactors,
65
+ poolPairData.swapFee,
66
+ poolPairData.amp,
67
+ );
68
+ }
69
+
70
+ _swapGivenIn(
71
+ tokenAmountsIn: bigint[],
72
+ balances: bigint[],
73
+ indexIn: number,
74
+ indexOut: number,
75
+ scalingFactors: bigint[],
76
+ _swapFeePercentage: bigint,
77
+ _amplificationParameter: bigint,
78
+ ): bigint[] {
79
+ // Fees are subtracted before scaling, to reduce the complexity of the rounding direction analysis.
80
+ const tokenAmountsInWithFee = tokenAmountsIn.map(a =>
81
+ this._subtractSwapFeeAmount(a, _swapFeePercentage),
82
+ );
83
+
84
+ const balancesUpscaled = this._upscaleArray(balances, scalingFactors);
85
+ const tokenAmountsInScaled = tokenAmountsInWithFee.map(a =>
86
+ this._upscale(a, scalingFactors[indexIn]),
87
+ );
88
+
89
+ const amountsOut = this._onSwapGivenIn(
90
+ tokenAmountsInScaled,
91
+ balancesUpscaled,
92
+ indexIn,
93
+ indexOut,
94
+ _amplificationParameter,
95
+ );
96
+
97
+ // amountOut tokens are exiting the Pool, so we round down.
98
+ return amountsOut.map(a =>
99
+ this._downscaleDown(a, scalingFactors[indexOut]),
100
+ );
101
+ }
102
+
103
+ _swapGivenOut(
104
+ tokenAmountsOut: bigint[],
105
+ balances: bigint[],
106
+ indexIn: number,
107
+ indexOut: number,
108
+ scalingFactors: bigint[],
109
+ _swapFeePercentage: bigint,
110
+ _amplificationParameter: bigint,
111
+ ): bigint[] {
112
+ const balancesUpscaled = this._upscaleArray(balances, scalingFactors);
113
+ const tokenAmountsOutScaled = tokenAmountsOut.map(a =>
114
+ this._upscale(a, scalingFactors[indexOut]),
115
+ );
116
+
117
+ let amountsIn: bigint[];
118
+ try {
119
+ amountsIn = this._onSwapGivenOut(
120
+ tokenAmountsOutScaled,
121
+ balancesUpscaled,
122
+ indexIn,
123
+ indexOut,
124
+ _amplificationParameter,
125
+ );
126
+ } catch (e) {
127
+ amountsIn = new Array(tokenAmountsOut.length).fill(0n);
128
+ }
129
+
130
+ // amountIn tokens are entering the Pool, so we round up.
131
+ const amountsInDownscaled = amountsIn.map(a =>
132
+ this._downscaleUp(a, scalingFactors[indexIn]),
133
+ );
134
+
135
+ // Fees are added after scaling happens, to reduce the complexity of the rounding direction analysis.
136
+ return amountsInDownscaled.map(a =>
137
+ this._subtractSwapFeeAmount(a, _swapFeePercentage),
138
+ );
139
+ }
140
+
141
+ /*
142
+ * @dev Called when a swap with the Pool occurs, where the amount of tokens entering the Pool is known.
143
+ *
144
+ * Returns the amount of tokens that will be taken from the Pool in return.
145
+ *
146
+ * All amounts inside `swapRequest` and `balances` are upscaled. The swap fee has already been deducted from
147
+ * `swapRequest.amount`.
148
+ *
149
+ * The return value is also considered upscaled, and will be downscaled (rounding down) before returning it to the
150
+ * Vault.
151
+ */
152
+ abstract _onSwapGivenIn(
153
+ tokenAmountsIn: bigint[],
154
+ balances: bigint[],
155
+ indexIn: number,
156
+ indexOut: number,
157
+ _amplificationParameter: bigint,
158
+ ): bigint[];
159
+
160
+ abstract _onSwapGivenOut(
161
+ tokenAmountsOut: bigint[],
162
+ balances: bigint[],
163
+ indexIn: number,
164
+ indexOut: number,
165
+ _amplificationParameter: bigint,
166
+ ): bigint[];
167
+ }
168
+
169
+ export abstract class BaseMinimalSwapInfoPool extends BasePool {
170
+ // Swap Hooks
171
+
172
+ // This is inspired from the function onSwap which is in the original contract
173
+ onBuy(
174
+ tokenAmountsOut: bigint[],
175
+ poolPairData: WeightedPoolPairData,
176
+ ): bigint[] {
177
+ // uint256 scalingFactorTokenIn = _scalingFactor(request.tokenIn);
178
+ // uint256 scalingFactorTokenOut = _scalingFactor(request.tokenOut);
179
+
180
+ // All token amounts are upscaled.
181
+ const balanceTokenIn = this._upscale(
182
+ poolPairData.tokenInBalance,
183
+ poolPairData.tokenInScalingFactor,
184
+ );
185
+
186
+ const balanceTokenOut = this._upscale(
187
+ poolPairData.tokenOutBalance,
188
+ poolPairData.tokenOutScalingFactor,
189
+ );
190
+
191
+ const tokenAmountsOutScaled = tokenAmountsOut.map(a =>
192
+ this._upscale(a, poolPairData.tokenOutScalingFactor),
193
+ );
194
+
195
+ let amountsIn: bigint[];
196
+ try {
197
+ amountsIn = this._onSwapGivenOut(
198
+ tokenAmountsOutScaled,
199
+ balanceTokenIn,
200
+ balanceTokenOut,
201
+ poolPairData.tokenInWeight,
202
+ poolPairData.tokenOutWeight,
203
+ );
204
+ } catch (e) {
205
+ amountsIn = new Array(tokenAmountsOut.length).fill(0n);
206
+ }
207
+
208
+ // amountIn tokens are entering the Pool, so we round up.
209
+ const amountsInDownscaled = amountsIn.map(a =>
210
+ this._downscaleUp(a, poolPairData.tokenInScalingFactor),
211
+ );
212
+
213
+ // Fees are added after scaling happens, to reduce the complexity of the rounding direction analysis.
214
+ return amountsInDownscaled.map(a =>
215
+ this._addFeeAmount(a, poolPairData.swapFee),
216
+ );
217
+ }
218
+
219
+ // Modification: this is inspired from the function onSwap which is in the original contract
220
+ onSell(
221
+ tokenAmountsIn: bigint[],
222
+ poolPairData: WeightedPoolPairData,
223
+ ): bigint[] {
224
+ // uint256 _scalingFactorTokenIn = _scalingFactor(request.tokenIn);
225
+ // uint256 _scalingFactorTokenOut = _scalingFactor(request.tokenOut);
226
+
227
+ // Fees are subtracted before scaling, to reduce the complexity of the rounding direction analysis.
228
+ const tokenAmountsInWithFee = tokenAmountsIn.map(a =>
229
+ this._subtractSwapFeeAmount(a, poolPairData.swapFee),
230
+ );
231
+
232
+ // All token amounts are upscaled.
233
+ const balanceTokenIn = this._upscale(
234
+ poolPairData.tokenInBalance,
235
+ poolPairData.tokenInScalingFactor,
236
+ );
237
+ const balanceTokenOut = this._upscale(
238
+ poolPairData.tokenOutBalance,
239
+ poolPairData.tokenOutScalingFactor,
240
+ );
241
+ const tokenAmountsInScaled = tokenAmountsInWithFee.map(a =>
242
+ this._upscale(a, poolPairData.tokenInScalingFactor),
243
+ );
244
+
245
+ const amountsOut = this._onSwapGivenIn(
246
+ tokenAmountsInScaled,
247
+ balanceTokenIn,
248
+ balanceTokenOut,
249
+ poolPairData.tokenInWeight,
250
+ poolPairData.tokenOutWeight,
251
+ );
252
+
253
+ // amountOut tokens are exiting the Pool, so we round down.
254
+ return amountsOut.map(a =>
255
+ this._downscaleDown(a, poolPairData.tokenOutScalingFactor),
256
+ );
257
+ }
258
+
259
+ abstract _onSwapGivenIn(
260
+ tokenAmountsIn: bigint[],
261
+ currentBalanceTokenIn: bigint,
262
+ currentBalanceTokenOut: bigint,
263
+ _weightIn: bigint,
264
+ _weightOut: bigint,
265
+ ): bigint[];
266
+
267
+ abstract _onSwapGivenOut(
268
+ tokenAmountsOut: bigint[],
269
+ currentBalanceTokenIn: bigint,
270
+ currentBalanceTokenOut: bigint,
271
+ _weightIn: bigint,
272
+ _weightOut: bigint,
273
+ ): bigint[];
274
+ }
@@ -1,4 +1,4 @@
1
- import { MathSol } from './balancer-v2-math';
1
+ import { MathSol } from '../../balancer-v2-math';
2
2
 
3
3
  /*
4
4
  Note when comparing vs smart contract:
@@ -8,6 +8,7 @@ Similar for mul
8
8
  */
9
9
 
10
10
  type Params = {
11
+ rate: bigint;
11
12
  fee: bigint;
12
13
  lowerTarget: bigint;
13
14
  upperTarget: bigint;
@@ -29,7 +30,11 @@ export function _calcBptOutPerMainIn(
29
30
  const previousNominalMain = _toNominal(mainBalance, params);
30
31
  const afterNominalMain = _toNominal(mainBalance + mainIn, params);
31
32
  const deltaNominalMain = afterNominalMain - previousNominalMain;
32
- const invariant = _calcInvariant(previousNominalMain, wrappedBalance);
33
+ const invariant = _calcInvariantUp(
34
+ previousNominalMain,
35
+ wrappedBalance,
36
+ params,
37
+ );
33
38
  return MathSol.divDown(MathSol.mul(bptSupply, deltaNominalMain), invariant);
34
39
  }
35
40
 
@@ -44,7 +49,11 @@ export function _calcBptInPerMainOut(
44
49
  const previousNominalMain = _toNominal(mainBalance, params);
45
50
  const afterNominalMain = _toNominal(mainBalance - mainOut, params);
46
51
  const deltaNominalMain = previousNominalMain - afterNominalMain;
47
- const invariant = _calcInvariant(previousNominalMain, wrappedBalance);
52
+ const invariant = _calcInvariantDown(
53
+ previousNominalMain,
54
+ wrappedBalance,
55
+ params,
56
+ );
48
57
  return MathSol.divUp(MathSol.mul(bptSupply, deltaNominalMain), invariant);
49
58
  }
50
59
 
@@ -57,9 +66,17 @@ export function _calcBptInPerWrappedOut(
57
66
  ): bigint {
58
67
  // Amount in, so we round up overall.
59
68
  const nominalMain = _toNominal(mainBalance, params);
60
- const previousInvariant = _calcInvariant(nominalMain, wrappedBalance);
69
+ const previousInvariant = _calcInvariantUp(
70
+ nominalMain,
71
+ wrappedBalance,
72
+ params,
73
+ );
61
74
  const newWrappedBalance = wrappedBalance - wrappedOut;
62
- const newInvariant = _calcInvariant(nominalMain, newWrappedBalance);
75
+ const newInvariant = _calcInvariantDown(
76
+ nominalMain,
77
+ newWrappedBalance,
78
+ params,
79
+ );
63
80
  const newBptBalance = MathSol.divDown(
64
81
  MathSol.mul(bptSupply, newInvariant),
65
82
  previousInvariant,
@@ -75,7 +92,8 @@ export function _calcWrappedOutPerMainIn(
75
92
  // Amount out, so we round down overall.
76
93
  const previousNominalMain = _toNominal(mainBalance, params);
77
94
  const afterNominalMain = _toNominal(mainBalance + mainIn, params);
78
- return afterNominalMain - previousNominalMain;
95
+ const deltaNominalMain = afterNominalMain - previousNominalMain;
96
+ return MathSol.divDownFixed(deltaNominalMain, params.rate);
79
97
  }
80
98
 
81
99
  export function _calcWrappedInPerMainOut(
@@ -86,7 +104,8 @@ export function _calcWrappedInPerMainOut(
86
104
  // Amount in, so we round up overall.
87
105
  const previousNominalMain = _toNominal(mainBalance, params);
88
106
  const afterNominalMain = _toNominal(mainBalance - mainOut, params);
89
- return previousNominalMain - afterNominalMain;
107
+ const deltaNominalMain = previousNominalMain - afterNominalMain;
108
+ return MathSol.divUpFixed(deltaNominalMain, params.rate);
90
109
  }
91
110
 
92
111
  export function _calcMainInPerBptOut(
@@ -101,7 +120,11 @@ export function _calcMainInPerBptOut(
101
120
  return _fromNominal(bptOut, params);
102
121
  }
103
122
  const previousNominalMain = _toNominal(mainBalance, params);
104
- const invariant = _calcInvariant(previousNominalMain, wrappedBalance);
123
+ const invariant = _calcInvariantUp(
124
+ previousNominalMain,
125
+ wrappedBalance,
126
+ params,
127
+ );
105
128
  const deltaNominalMain = MathSol.divUp(
106
129
  MathSol.mul(invariant, bptOut),
107
130
  bptSupply,
@@ -120,7 +143,11 @@ export function _calcMainOutPerBptIn(
120
143
  ): bigint {
121
144
  // Amount out, so we round down overall.
122
145
  const previousNominalMain = _toNominal(mainBalance, params);
123
- const invariant = _calcInvariant(previousNominalMain, wrappedBalance);
146
+ const invariant = _calcInvariantDown(
147
+ previousNominalMain,
148
+ wrappedBalance,
149
+ params,
150
+ );
124
151
  const deltaNominalMain = MathSol.divDown(
125
152
  MathSol.mul(invariant, bptIn),
126
153
  bptSupply,
@@ -137,7 +164,8 @@ export function _calcMainOutPerWrappedIn(
137
164
  ): bigint {
138
165
  // Amount out, so we round down overall.
139
166
  const previousNominalMain = _toNominal(mainBalance, params);
140
- const afterNominalMain = previousNominalMain - wrappedIn;
167
+ const deltaNominalMain = MathSol.mulDownFixed(wrappedIn, params.rate);
168
+ const afterNominalMain = previousNominalMain - deltaNominalMain;
141
169
  const newMainBalance = _fromNominal(afterNominalMain, params);
142
170
  return mainBalance - newMainBalance;
143
171
  }
@@ -149,7 +177,8 @@ export function _calcMainInPerWrappedOut(
149
177
  ): bigint {
150
178
  // Amount in, so we round up overall.
151
179
  const previousNominalMain = _toNominal(mainBalance, params);
152
- const afterNominalMain = previousNominalMain + wrappedOut;
180
+ const deltaNominalMain = MathSol.mulUpFixed(wrappedOut, params.rate);
181
+ const afterNominalMain = previousNominalMain + deltaNominalMain;
153
182
  const newMainBalance = _fromNominal(afterNominalMain, params);
154
183
  return newMainBalance - mainBalance;
155
184
  }
@@ -164,13 +193,21 @@ export function _calcBptOutPerWrappedIn(
164
193
  // Amount out, so we round down overall.
165
194
  if (bptSupply == 0n) {
166
195
  // Return nominal DAI
167
- return wrappedIn;
196
+ return MathSol.mulDownFixed(wrappedIn, params.rate);
168
197
  }
169
198
 
170
199
  const nominalMain = _toNominal(mainBalance, params);
171
- const previousInvariant = _calcInvariant(nominalMain, wrappedBalance);
200
+ const previousInvariant = _calcInvariantUp(
201
+ nominalMain,
202
+ wrappedBalance,
203
+ params,
204
+ );
172
205
  const newWrappedBalance = wrappedBalance + wrappedIn;
173
- const newInvariant = _calcInvariant(nominalMain, newWrappedBalance);
206
+ const newInvariant = _calcInvariantDown(
207
+ nominalMain,
208
+ newWrappedBalance,
209
+ params,
210
+ );
174
211
  const newBptBalance = MathSol.divDown(
175
212
  MathSol.mul(bptSupply, newInvariant),
176
213
  previousInvariant,
@@ -188,15 +225,21 @@ export function _calcWrappedInPerBptOut(
188
225
  // Amount in, so we round up overall.
189
226
  if (bptSupply == 0n) {
190
227
  // Return nominal DAI
191
- return bptOut;
228
+ return MathSol.divUpFixed(bptOut, params.rate);
192
229
  }
193
230
 
194
231
  const nominalMain = _toNominal(mainBalance, params);
195
- const previousInvariant = _calcInvariant(nominalMain, wrappedBalance);
232
+ const previousInvariant = _calcInvariantUp(
233
+ nominalMain,
234
+ wrappedBalance,
235
+ params,
236
+ );
196
237
  const newBptBalance = bptSupply + bptOut;
197
- const newWrappedBalance =
238
+ const newWrappedBalance = MathSol.divUpFixed(
198
239
  MathSol.divUp(MathSol.mul(newBptBalance, previousInvariant), bptSupply) -
199
- nominalMain;
240
+ nominalMain,
241
+ params.rate,
242
+ );
200
243
  return newWrappedBalance - wrappedBalance;
201
244
  }
202
245
 
@@ -209,19 +252,34 @@ export function _calcWrappedOutPerBptIn(
209
252
  ): bigint {
210
253
  // Amount out, so we round down overall.
211
254
  const nominalMain = _toNominal(mainBalance, params);
212
- const previousInvariant = _calcInvariant(nominalMain, wrappedBalance);
255
+ const previousInvariant = _calcInvariantUp(
256
+ nominalMain,
257
+ wrappedBalance,
258
+ params,
259
+ );
213
260
  const newBptBalance = bptSupply - bptIn;
214
- const newWrappedBalance =
261
+ const newWrappedBalance = MathSol.divUpFixed(
215
262
  MathSol.divUp(MathSol.mul(newBptBalance, previousInvariant), bptSupply) -
216
- nominalMain;
263
+ nominalMain,
264
+ params.rate,
265
+ );
217
266
  return wrappedBalance - newWrappedBalance;
218
267
  }
219
268
 
220
- function _calcInvariant(
269
+ function _calcInvariantUp(
221
270
  nominalMainBalance: bigint,
222
271
  wrappedBalance: bigint,
272
+ params: Params,
273
+ ): bigint {
274
+ return nominalMainBalance + MathSol.mulUpFixed(wrappedBalance, params.rate);
275
+ }
276
+
277
+ function _calcInvariantDown(
278
+ nominalMainBalance: bigint,
279
+ wrappedBalance: bigint,
280
+ params: Params,
223
281
  ): bigint {
224
- return nominalMainBalance + wrappedBalance;
282
+ return nominalMainBalance + MathSol.mulDownFixed(wrappedBalance, params.rate);
225
283
  }
226
284
 
227
285
  function _toNominal(real: bigint, params: Params): bigint {