@paraswap/dex-lib 2.16.1 → 2.16.2-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 (91) hide show
  1. package/build/abi/uniswap-v3/UniswapV3Pool.abi.json +363 -67
  2. package/build/abi/uniswap-v3/UniswapV3Quoter.abi.json +119 -23
  3. package/build/abi/uniswap-v3/pancakeswap-v3/PancakeswapV3QuoterV2.abi.json +285 -0
  4. package/build/abi/uniswap-v3/pancakeswap-v3/PancakeswapV3Router.abi.json +583 -0
  5. package/build/config.js +6 -6
  6. package/build/dex/balancer-v2/balancer-v2.d.ts +9 -14
  7. package/build/dex/balancer-v2/balancer-v2.js +19 -16
  8. package/build/dex/balancer-v2/balancer-v2.js.map +1 -1
  9. package/build/dex/balancer-v2/config.d.ts +2 -7
  10. package/build/dex/balancer-v2/config.js +20 -30
  11. package/build/dex/balancer-v2/config.js.map +1 -1
  12. package/build/dex/balancer-v2/pools/balancer-v2-pool.d.ts +24 -0
  13. package/build/dex/balancer-v2/pools/balancer-v2-pool.js +102 -0
  14. package/build/dex/balancer-v2/pools/balancer-v2-pool.js.map +1 -0
  15. package/build/dex/balancer-v2/pools/linear/LinearMath.d.ts +19 -0
  16. package/build/dex/balancer-v2/pools/linear/LinearMath.js +179 -0
  17. package/build/dex/balancer-v2/pools/linear/LinearMath.js.map +1 -0
  18. package/build/dex/balancer-v2/pools/linear/LinearPool.d.ts +50 -0
  19. package/build/dex/balancer-v2/pools/linear/LinearPool.js +458 -0
  20. package/build/dex/balancer-v2/pools/linear/LinearPool.js.map +1 -0
  21. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStableMath.d.ts +10 -0
  22. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStableMath.js +314 -0
  23. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStableMath.js.map +1 -0
  24. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStablePool.d.ts +50 -0
  25. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStablePool.js +367 -0
  26. package/build/dex/balancer-v2/pools/phantom-stable/PhantomStablePool.js.map +1 -0
  27. package/build/dex/balancer-v2/pools/stable/StableMath.d.ts +7 -0
  28. package/build/dex/balancer-v2/pools/stable/StableMath.js +111 -0
  29. package/build/dex/balancer-v2/pools/stable/StableMath.js.map +1 -0
  30. package/build/dex/balancer-v2/pools/stable/StablePool.d.ts +30 -0
  31. package/build/dex/balancer-v2/pools/stable/StablePool.js +129 -0
  32. package/build/dex/balancer-v2/pools/stable/StablePool.js.map +1 -0
  33. package/build/dex/balancer-v2/pools/weighted/WeightedMath.d.ts +6 -0
  34. package/build/dex/balancer-v2/pools/weighted/WeightedMath.js +61 -0
  35. package/build/dex/balancer-v2/pools/weighted/WeightedMath.js.map +1 -0
  36. package/build/dex/balancer-v2/pools/weighted/WeightedPool.d.ts +30 -0
  37. package/build/dex/balancer-v2/pools/weighted/WeightedPool.js +112 -0
  38. package/build/dex/balancer-v2/pools/weighted/WeightedPool.js.map +1 -0
  39. package/build/dex/index.js +4 -0
  40. package/build/dex/index.js.map +1 -1
  41. package/build/dex/maverick-v1/config.js +1 -1
  42. package/build/dex/maverick-v1/config.js.map +1 -1
  43. package/build/dex/quickswap/config.js +8 -0
  44. package/build/dex/quickswap/config.js.map +1 -1
  45. package/build/dex/quickswap/spiritswap-v3.d.ts +6 -0
  46. package/build/dex/quickswap/spiritswap-v3.js +19 -0
  47. package/build/dex/quickswap/spiritswap-v3.js.map +1 -0
  48. package/build/dex/uniswap-v3/config.js +42 -0
  49. package/build/dex/uniswap-v3/config.js.map +1 -1
  50. package/build/dex/uniswap-v3/forks/pancakeswap-v3/pancakeswap-v3.d.ts +12 -0
  51. package/build/dex/uniswap-v3/forks/pancakeswap-v3/pancakeswap-v3.js +23 -0
  52. package/build/dex/uniswap-v3/forks/pancakeswap-v3/pancakeswap-v3.js.map +1 -0
  53. package/build/dex/uniswap-v3/types.d.ts +3 -0
  54. package/build/dex/uniswap-v3/types.js.map +1 -1
  55. package/build/dex/uniswap-v3/uniswap-v3-pool.d.ts +2 -1
  56. package/build/dex/uniswap-v3/uniswap-v3-pool.js +3 -2
  57. package/build/dex/uniswap-v3/uniswap-v3-pool.js.map +1 -1
  58. package/build/dex/uniswap-v3/uniswap-v3.js +6 -3
  59. package/build/dex/uniswap-v3/uniswap-v3.js.map +1 -1
  60. package/package.json +1 -1
  61. package/src/abi/uniswap-v3/UniswapV3Pool.abi.json +363 -67
  62. package/src/abi/uniswap-v3/UniswapV3Quoter.abi.json +119 -23
  63. package/src/abi/uniswap-v3/pancakeswap-v3/PancakeswapV3QuoterV2.abi.json +285 -0
  64. package/src/abi/uniswap-v3/pancakeswap-v3/PancakeswapV3Router.abi.json +583 -0
  65. package/src/config.ts +6 -6
  66. package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +99 -160
  67. package/src/dex/balancer-v2/balancer-v2.ts +41 -29
  68. package/src/dex/balancer-v2/config.ts +23 -35
  69. package/src/dex/balancer-v2/pools/balancer-v2-pool.ts +273 -0
  70. package/src/dex/balancer-v2/{LinearMath.ts → pools/linear/LinearMath.ts} +1 -1
  71. package/src/dex/balancer-v2/{LinearPool.ts → pools/linear/LinearPool.ts} +210 -5
  72. package/src/dex/balancer-v2/{StableMath.ts → pools/phantom-stable/PhantomStableMath.ts} +101 -21
  73. package/src/dex/balancer-v2/{PhantomStablePool.ts → pools/phantom-stable/PhantomStablePool.ts} +165 -11
  74. package/src/dex/balancer-v2/pools/stable/StableMath.ts +204 -0
  75. package/src/dex/balancer-v2/pools/stable/StablePool.ts +221 -0
  76. package/src/dex/balancer-v2/pools/weighted/WeightedMath.ts +84 -0
  77. package/src/dex/balancer-v2/pools/weighted/WeightedPool.ts +189 -0
  78. package/src/dex/index.ts +4 -0
  79. package/src/dex/maverick-v1/config.ts +1 -1
  80. package/src/dex/quickswap/config.ts +9 -0
  81. package/src/dex/quickswap/quickswap-e2e.test.ts +94 -0
  82. package/src/dex/quickswap/spiritswap-v3.ts +19 -0
  83. package/src/dex/uniswap-v3/config.ts +50 -0
  84. package/src/dex/uniswap-v3/forks/pancakeswap-v3/pancakeswap-v3.ts +28 -0
  85. package/src/dex/uniswap-v3/types.ts +3 -0
  86. package/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +156 -0
  87. package/src/dex/uniswap-v3/uniswap-v3-pool.ts +3 -2
  88. package/src/dex/uniswap-v3/uniswap-v3.ts +7 -3
  89. package/tests/constants-e2e.ts +11 -6
  90. package/.idea/runConfigurations.xml +0 -10
  91. package/src/dex/balancer-v2/balancer-v2-pool.ts +0 -744
@@ -0,0 +1,273 @@
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
+ // These methods use fixed versions to match SC scaling
13
+ _upscaleArray(amounts: bigint[], scalingFactors: bigint[]): bigint[] {
14
+ return amounts.map((a, i) => MathSol.mulUpFixed(a, scalingFactors[i]));
15
+ }
16
+
17
+ _upscale(amount: bigint, scalingFactor: bigint): bigint {
18
+ return MathSol.mulUpFixed(amount, scalingFactor);
19
+ }
20
+
21
+ _downscaleDown(amount: bigint, scalingFactor: bigint): bigint {
22
+ return MathSol.divDownFixed(amount, scalingFactor);
23
+ }
24
+
25
+ _downscaleUp(amount: bigint, scalingFactor: bigint): bigint {
26
+ return MathSol.divUpFixed(amount, scalingFactor);
27
+ }
28
+
29
+ _nullifyIfMaxAmountExceeded(amountToTrade: bigint, swapMax: bigint): bigint {
30
+ return swapMax >= amountToTrade ? amountToTrade : 0n;
31
+ }
32
+ }
33
+
34
+
35
+ export abstract class BaseGeneralPool extends BasePool {
36
+
37
+ // Swap Hooks
38
+ onBuy(amounts: bigint[], poolPairData: StablePoolPairData): bigint[] {
39
+ return this._swapGivenOut(
40
+ amounts,
41
+ poolPairData.balances,
42
+ poolPairData.indexIn,
43
+ poolPairData.indexOut,
44
+ poolPairData.scalingFactors,
45
+ poolPairData.swapFee,
46
+ poolPairData.amp,
47
+ );
48
+ }
49
+
50
+ // Modification: this is inspired from the function onSwap which is in the original contract
51
+ onSell(amounts: bigint[], poolPairData: StablePoolPairData): bigint[] {
52
+ // _validateIndexes(indexIn, indexOut, _getTotalTokens());
53
+ // uint256[] memory scalingFactors = _scalingFactors();
54
+ return this._swapGivenIn(
55
+ amounts,
56
+ poolPairData.balances,
57
+ poolPairData.indexIn,
58
+ poolPairData.indexOut,
59
+ poolPairData.scalingFactors,
60
+ poolPairData.swapFee,
61
+ poolPairData.amp,
62
+ );
63
+ }
64
+
65
+ _swapGivenIn(
66
+ tokenAmountsIn: bigint[],
67
+ balances: bigint[],
68
+ indexIn: number,
69
+ indexOut: number,
70
+ scalingFactors: bigint[],
71
+ _swapFeePercentage: bigint,
72
+ _amplificationParameter: bigint,
73
+ ): bigint[] {
74
+ // Fees are subtracted before scaling, to reduce the complexity of the rounding direction analysis.
75
+ const tokenAmountsInWithFee = tokenAmountsIn.map(a =>
76
+ this._subtractSwapFeeAmount(a, _swapFeePercentage),
77
+ );
78
+
79
+ const balancesUpscaled = this._upscaleArray(balances, scalingFactors);
80
+ const tokenAmountsInScaled = tokenAmountsInWithFee.map(a =>
81
+ this._upscale(a, scalingFactors[indexIn]),
82
+ );
83
+
84
+ const amountsOut = this._onSwapGivenIn(
85
+ tokenAmountsInScaled,
86
+ balancesUpscaled,
87
+ indexIn,
88
+ indexOut,
89
+ _amplificationParameter,
90
+ );
91
+
92
+ // amountOut tokens are exiting the Pool, so we round down.
93
+ return amountsOut.map(a =>
94
+ this._downscaleDown(a, scalingFactors[indexOut]),
95
+ );
96
+ }
97
+
98
+ _swapGivenOut(
99
+ tokenAmountsOut: bigint[],
100
+ balances: bigint[],
101
+ indexIn: number,
102
+ indexOut: number,
103
+ scalingFactors: bigint[],
104
+ _swapFeePercentage: bigint,
105
+ _amplificationParameter: bigint,
106
+ ): bigint[] {
107
+
108
+ const balancesUpscaled = this._upscaleArray(balances, scalingFactors);
109
+ const tokenAmountsOutScaled = tokenAmountsOut.map(a =>
110
+ this._upscale(a, scalingFactors[indexOut]),
111
+ );
112
+
113
+ let amountsIn: bigint[];
114
+ try {
115
+ amountsIn = this._onSwapGivenOut(
116
+ tokenAmountsOutScaled,
117
+ balancesUpscaled,
118
+ indexIn,
119
+ indexOut,
120
+ _amplificationParameter,
121
+ );
122
+ } catch (e) {
123
+ amountsIn = new Array(tokenAmountsOut.length).fill(
124
+ 0n,
125
+ );
126
+ }
127
+
128
+ // amountIn tokens are entering the Pool, so we round up.
129
+ const amountsInDownscaled = amountsIn.map(a =>
130
+ this._downscaleUp(a, scalingFactors[indexIn]),
131
+ );
132
+
133
+ // Fees are added after scaling happens, to reduce the complexity of the rounding direction analysis.
134
+ return amountsInDownscaled.map(a =>
135
+ this._subtractSwapFeeAmount(a, _swapFeePercentage),
136
+ );
137
+ }
138
+
139
+ /*
140
+ * @dev Called when a swap with the Pool occurs, where the amount of tokens entering the Pool is known.
141
+ *
142
+ * Returns the amount of tokens that will be taken from the Pool in return.
143
+ *
144
+ * All amounts inside `swapRequest` and `balances` are upscaled. The swap fee has already been deducted from
145
+ * `swapRequest.amount`.
146
+ *
147
+ * The return value is also considered upscaled, and will be downscaled (rounding down) before returning it to the
148
+ * Vault.
149
+ */
150
+ abstract _onSwapGivenIn(
151
+ tokenAmountsIn: bigint[],
152
+ balances: bigint[],
153
+ indexIn: number,
154
+ indexOut: number,
155
+ _amplificationParameter: bigint,
156
+ ): bigint[];
157
+
158
+ abstract _onSwapGivenOut(
159
+ tokenAmountsOut: bigint[],
160
+ balances: bigint[],
161
+ indexIn: number,
162
+ indexOut: number,
163
+ _amplificationParameter: bigint,
164
+ ): bigint[];
165
+ }
166
+
167
+ export abstract class BaseMinimalSwapInfoPool extends BasePool {
168
+ // Swap Hooks
169
+
170
+ // This is inspired from the function onSwap which is in the original contract
171
+ onBuy(
172
+ tokenAmountsOut: bigint[],
173
+ poolPairData: WeightedPoolPairData,
174
+ ): bigint[] {
175
+ // uint256 scalingFactorTokenIn = _scalingFactor(request.tokenIn);
176
+ // uint256 scalingFactorTokenOut = _scalingFactor(request.tokenOut);
177
+
178
+ // All token amounts are upscaled.
179
+ const balanceTokenIn = this._upscale(
180
+ poolPairData.tokenInBalance,
181
+ poolPairData.tokenInScalingFactor,
182
+ );
183
+
184
+ const balanceTokenOut = this._upscale(
185
+ poolPairData.tokenOutBalance,
186
+ poolPairData.tokenOutScalingFactor,
187
+ );
188
+
189
+ const tokenAmountsOutScaled = tokenAmountsOut.map(a =>
190
+ this._upscale(a, poolPairData.tokenOutScalingFactor),
191
+ );
192
+
193
+ let amountsIn: bigint[];
194
+ try {
195
+ amountsIn = this._onSwapGivenOut(
196
+ tokenAmountsOutScaled,
197
+ balanceTokenIn,
198
+ balanceTokenOut,
199
+ poolPairData.tokenInWeight,
200
+ poolPairData.tokenOutWeight,
201
+ );
202
+ } catch (e) {
203
+ amountsIn = new Array(tokenAmountsOut.length).fill(
204
+ 0n,
205
+ );
206
+ }
207
+
208
+ const amountsInDownscaled = amountsIn.map(a =>
209
+ this._downscaleUp(a, poolPairData.tokenInScalingFactor),
210
+ );
211
+
212
+ return amountsInDownscaled.map(a =>
213
+ this._subtractSwapFeeAmount(a, poolPairData.swapFee),
214
+ );
215
+ }
216
+
217
+ // Modification: this is inspired from the function onSwap which is in the original contract
218
+ onSell(
219
+ tokenAmountsIn: bigint[],
220
+ poolPairData: WeightedPoolPairData,
221
+ ): bigint[] {
222
+ // uint256 _scalingFactorTokenIn = _scalingFactor(request.tokenIn);
223
+ // uint256 _scalingFactorTokenOut = _scalingFactor(request.tokenOut);
224
+
225
+ // Fees are subtracted before scaling, to reduce the complexity of the rounding direction analysis.
226
+ const tokenAmountsInWithFee = tokenAmountsIn.map(a =>
227
+ this._subtractSwapFeeAmount(a, poolPairData.swapFee),
228
+ );
229
+
230
+ // All token amounts are upscaled.
231
+ const balanceTokenIn = this._upscale(
232
+ poolPairData.tokenInBalance,
233
+ poolPairData.tokenInScalingFactor,
234
+ );
235
+ const balanceTokenOut = this._upscale(
236
+ poolPairData.tokenOutBalance,
237
+ poolPairData.tokenOutScalingFactor,
238
+ );
239
+ const tokenAmountsInScaled = tokenAmountsInWithFee.map(a =>
240
+ this._upscale(a, poolPairData.tokenInScalingFactor),
241
+ );
242
+
243
+ const amountsOut = this._onSwapGivenIn(
244
+ tokenAmountsInScaled,
245
+ balanceTokenIn,
246
+ balanceTokenOut,
247
+ poolPairData.tokenInWeight,
248
+ poolPairData.tokenOutWeight,
249
+ );
250
+
251
+ // amountOut tokens are exiting the Pool, so we round down.
252
+ return amountsOut.map(a =>
253
+ this._downscaleDown(a, poolPairData.tokenOutScalingFactor),
254
+ );
255
+ }
256
+
257
+ abstract _onSwapGivenIn(
258
+ tokenAmountsIn: bigint[],
259
+ currentBalanceTokenIn: bigint,
260
+ currentBalanceTokenOut: bigint,
261
+ _weightIn: bigint,
262
+ _weightOut: bigint,
263
+ ): bigint[];
264
+
265
+ abstract _onSwapGivenOut(
266
+ tokenAmountsOut: bigint[],
267
+ currentBalanceTokenIn: bigint,
268
+ currentBalanceTokenOut: bigint,
269
+ _weightIn: bigint,
270
+ _weightOut: bigint,
271
+ ): bigint[];
272
+ }
273
+
@@ -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:
@@ -1,11 +1,11 @@
1
1
  import { Interface } from '@ethersproject/abi';
2
2
  import { BigNumber } from '@ethersproject/bignumber';
3
- import { isSameAddress, decodeThrowError } from './utils';
3
+ import { isSameAddress, decodeThrowError } from '../../utils';
4
4
  import * as LinearMath from './LinearMath';
5
- import { BasePool } from './balancer-v2-pool';
6
- import { callData, SubgraphPoolBase, PoolState, TokenState } from './types';
7
- import LinearPoolABI from '../../abi/balancer-v2/linearPoolAbi.json';
8
- import { SwapSide } from '../../constants';
5
+ import { BasePool } from '../balancer-v2-pool';
6
+ import { callData, SubgraphPoolBase, PoolState, TokenState } from '../../types';
7
+ import LinearPoolABI from '../../../../abi/balancer-v2/linearPoolAbi.json';
8
+ import { SwapSide } from '../../../../constants';
9
9
  import { keyBy } from 'lodash';
10
10
 
11
11
  export enum PairTypes {
@@ -82,6 +82,211 @@ export class LinearPool extends BasePool {
82
82
  );
83
83
  }
84
84
 
85
+ onBuy(amounts: bigint[], poolPairData: LinearPoolPairData): bigint[] {
86
+ return this._swapGivenOut(
87
+ amounts,
88
+ poolPairData.tokens,
89
+ poolPairData.balances,
90
+ poolPairData.indexIn,
91
+ poolPairData.indexOut,
92
+ poolPairData.bptIndex,
93
+ poolPairData.wrappedIndex,
94
+ poolPairData.mainIndex,
95
+ poolPairData.scalingFactors,
96
+ poolPairData.swapFee,
97
+ poolPairData.lowerTarget,
98
+ poolPairData.upperTarget,
99
+ );
100
+ }
101
+
102
+ _swapGivenOut(
103
+ tokenAmountsOut: bigint[],
104
+ tokens: string[],
105
+ balances: bigint[],
106
+ indexIn: number,
107
+ indexOut: number,
108
+ bptIndex: number,
109
+ wrappedIndex: number,
110
+ mainIndex: number,
111
+ scalingFactors: bigint[],
112
+ swapFeePercentage: bigint,
113
+ lowerTarget: bigint,
114
+ upperTarget: bigint,
115
+ ): bigint[] {
116
+ let pairType: PairTypes;
117
+ if (isSameAddress(tokens[indexIn], tokens[bptIndex])) {
118
+ if (isSameAddress(tokens[indexOut], tokens[wrappedIndex]))
119
+ pairType = PairTypes.BptToWrappedToken;
120
+ else pairType = PairTypes.BptToMainToken;
121
+ } else if (isSameAddress(tokens[indexOut], tokens[bptIndex])) {
122
+ if (isSameAddress(tokens[indexIn], tokens[wrappedIndex]))
123
+ pairType = PairTypes.WrappedTokenToBpt;
124
+ else pairType = PairTypes.MainTokenToBpt;
125
+ } else {
126
+ if (isSameAddress(tokens[indexIn], tokens[wrappedIndex]))
127
+ pairType = PairTypes.WrappedTokenToMainToken;
128
+ else pairType = PairTypes.MainTokenToWrappedToken;
129
+ }
130
+
131
+ const balancesUpscaled = this._upscaleArray(balances, scalingFactors);
132
+ const tokenAmountsOutScaled = tokenAmountsOut.map(a =>
133
+ this._upscale(a, scalingFactors[indexOut]),
134
+ );
135
+
136
+ // VirtualBPTSupply must be used for the maths
137
+ const virtualBptSupply = this.MAX_TOKEN_BALANCE.sub(
138
+ balances[bptIndex],
139
+ ).toBigInt();
140
+
141
+ const amountsIn = this._onSwapGivenOut(
142
+ tokenAmountsOutScaled,
143
+ balancesUpscaled[mainIndex],
144
+ balancesUpscaled[wrappedIndex],
145
+ swapFeePercentage,
146
+ lowerTarget,
147
+ upperTarget,
148
+ virtualBptSupply,
149
+ pairType,
150
+ );
151
+
152
+ return amountsIn.map(a =>
153
+ this._downscaleDown(a, scalingFactors[indexIn]),
154
+ );
155
+ }
156
+
157
+ _onSwapGivenOut(
158
+ tokenAmountsIn: bigint[],
159
+ mainBalance: bigint,
160
+ wrappedBalance: bigint,
161
+ fee: bigint,
162
+ lowerTarget: bigint,
163
+ upperTarget: bigint,
164
+ virtualBptSupply: bigint,
165
+ pairType: PairTypes,
166
+ ): bigint[] {
167
+ const amountsIn: bigint[] = [];
168
+
169
+ switch (pairType) {
170
+ case PairTypes.BptToMainToken:
171
+ tokenAmountsIn.forEach(amountIn => {
172
+ let amt: bigint;
173
+ try {
174
+ amt = LinearMath._calcMainOutPerBptIn(
175
+ amountIn,
176
+ mainBalance,
177
+ wrappedBalance,
178
+ virtualBptSupply,
179
+ {
180
+ fee: fee,
181
+ lowerTarget: lowerTarget,
182
+ upperTarget: upperTarget,
183
+ },
184
+ );
185
+ } catch (err) {
186
+ amt = 0n;
187
+ }
188
+ amountsIn.push(amt);
189
+ });
190
+ break;
191
+ case PairTypes.MainTokenToBpt:
192
+ tokenAmountsIn.forEach(amountIn => {
193
+ let amt: bigint;
194
+ try {
195
+ amt = LinearMath._calcBptOutPerMainIn(
196
+ amountIn,
197
+ mainBalance,
198
+ wrappedBalance,
199
+ virtualBptSupply,
200
+ {
201
+ fee: fee,
202
+ lowerTarget: lowerTarget,
203
+ upperTarget: upperTarget,
204
+ },
205
+ );
206
+ } catch (err) {
207
+ amt = 0n;
208
+ }
209
+ amountsIn.push(amt);
210
+ });
211
+ break;
212
+ case PairTypes.MainTokenToWrappedToken:
213
+ tokenAmountsIn.forEach(amountIn => {
214
+ let amt: bigint;
215
+ try {
216
+ amt = LinearMath._calcWrappedInPerMainOut(amountIn, mainBalance, {
217
+ fee: fee,
218
+ lowerTarget: lowerTarget,
219
+ upperTarget: upperTarget,
220
+ });
221
+ } catch (err) {
222
+ amt = 0n;
223
+ }
224
+ amountsIn.push(amt);
225
+ });
226
+ break;
227
+ case PairTypes.WrappedTokenToMainToken:
228
+ tokenAmountsIn.forEach(amountIn => {
229
+ let amt: bigint;
230
+ try {
231
+ amt = LinearMath._calcMainInPerWrappedOut(amountIn, mainBalance, {
232
+ fee: fee,
233
+ lowerTarget: lowerTarget,
234
+ upperTarget: upperTarget,
235
+ });
236
+ } catch (err) {
237
+ amt = 0n;
238
+ }
239
+ amountsIn.push(amt);
240
+ });
241
+ break;
242
+ case PairTypes.BptToWrappedToken:
243
+ tokenAmountsIn.forEach(amountIn => {
244
+ let amt: bigint;
245
+ try {
246
+ amt = LinearMath._calcWrappedInPerBptOut(
247
+ amountIn,
248
+ mainBalance,
249
+ wrappedBalance,
250
+ virtualBptSupply,
251
+ {
252
+ fee: fee,
253
+ lowerTarget: lowerTarget,
254
+ upperTarget: upperTarget,
255
+ },
256
+ );
257
+ } catch (err) {
258
+ amt = 0n;
259
+ }
260
+ amountsIn.push(amt);
261
+ });
262
+ break;
263
+ case PairTypes.WrappedTokenToBpt:
264
+ tokenAmountsIn.forEach(amountIn => {
265
+ let amt: bigint;
266
+ try {
267
+ amt = LinearMath._calcBptInPerWrappedOut(
268
+ amountIn,
269
+ mainBalance,
270
+ wrappedBalance,
271
+ virtualBptSupply,
272
+ {
273
+ fee: fee,
274
+ lowerTarget: lowerTarget,
275
+ upperTarget: upperTarget,
276
+ },
277
+ );
278
+ } catch (err) {
279
+ amt = 0n;
280
+ }
281
+ amountsIn.push(amt);
282
+ });
283
+ break;
284
+ default:
285
+ amountsIn.push(0n);
286
+ }
287
+ return amountsIn;
288
+ }
289
+
85
290
  _swapGivenIn(
86
291
  tokenAmountsIn: bigint[],
87
292
  tokens: string[],
@@ -1,5 +1,5 @@
1
- import { BI_POWS } from '../../bigint-constants';
2
- import { MathSol } from './balancer-v2-math';
1
+ import { BI_POWS } from '../../../../bigint-constants';
2
+ import { MathSol } from '../../balancer-v2-math';
3
3
 
4
4
  const AMP_PRECISION = BI_POWS[3];
5
5
 
@@ -9,15 +9,15 @@ export function _calculateInvariant(
9
9
  roundUp: boolean,
10
10
  ): bigint {
11
11
  /**********************************************************************************************
12
- // invariant //
13
- // D = invariant D^(n+1) //
14
- // A = amplification coefficient A n^n S + D = A D n^n + ----------- //
15
- // S = sum of balances n^n P //
16
- // P = product of balances //
17
- // n = number of tokens //
18
- *********x************************************************************************************/
12
+ // invariant //
13
+ // D = invariant D^(n+1) //
14
+ // A = amplification coefficient A n^n S + D = A D n^n + ----------- //
15
+ // S = sum of balances n^n P //
16
+ // P = product of balances //
17
+ // n = number of tokens //
18
+ *********x************************************************************************************/
19
19
 
20
- // We support rounding up or down.
20
+ // We support rounding up or down.
21
21
 
22
22
  let sum = 0n;
23
23
  const numTokens = balances.length;
@@ -44,18 +44,18 @@ export function _calculateInvariant(
44
44
  prevInvariant = invariant;
45
45
  invariant = MathSol.div(
46
46
  MathSol.mul(MathSol.mul(BigInt(numTokens), invariant), invariant) +
47
- MathSol.div(
48
- MathSol.mul(MathSol.mul(ampTimesTotal, sum), P_D),
49
- AMP_PRECISION,
50
- roundUp,
51
- ),
47
+ MathSol.div(
48
+ MathSol.mul(MathSol.mul(ampTimesTotal, sum), P_D),
49
+ AMP_PRECISION,
50
+ roundUp,
51
+ ),
52
52
  MathSol.mul(BigInt(numTokens + 1), invariant) +
53
- // No need to use checked arithmetic for the amp precision, the amp is guaranteed to be at least 1
54
- MathSol.div(
55
- MathSol.mul(ampTimesTotal - AMP_PRECISION, P_D),
56
- AMP_PRECISION,
57
- !roundUp,
58
- ),
53
+ // No need to use checked arithmetic for the amp precision, the amp is guaranteed to be at least 1
54
+ MathSol.div(
55
+ MathSol.mul(ampTimesTotal - AMP_PRECISION, P_D),
56
+ AMP_PRECISION,
57
+ !roundUp,
58
+ ),
59
59
  roundUp,
60
60
  );
61
61
 
@@ -81,6 +81,17 @@ export function _calcOutGivenIn(
81
81
  amountIn: bigint,
82
82
  invariant?: bigint,
83
83
  ): bigint {
84
+ /**************************************************************************************************************
85
+ // outGivenIn token x for y - polynomial equation to solve //
86
+ // ay = amount out to calculate //
87
+ // by = balance token out //
88
+ // y = by - ay (finalBalanceOut) //
89
+ // D = invariant D D^(n+1) //
90
+ // A = amplification coefficient y^2 + ( S - ---------- - D) * y - ------------- = 0 //
91
+ // n = number of tokens (A * n^n) A * n^2n * P //
92
+ // S = sum of final balances but y //
93
+ // P = product of final balances but y //
94
+ **************************************************************************************************************/
84
95
  balances = [...balances];
85
96
  // Given that we need to have a greater final balance out, the invariant needs to be rounded up
86
97
  if (!invariant) invariant = _calculateInvariant(amp, balances, true);
@@ -105,6 +116,19 @@ export function _calcInGivenOut(
105
116
  fee: bigint,
106
117
  invariant?: bigint,
107
118
  ): bigint {
119
+ /**************************************************************************************************************
120
+ // inGivenOut token x for y - polynomial equation to solve //
121
+ // ax = amount in to calculate //
122
+ // bx = balance token in //
123
+ // x = bx + ax (finalBalanceIn) //
124
+ // D = invariant D D^(n+1) //
125
+ // A = amplification coefficient x^2 + ( S - ---------- - D) * x - ------------- = 0 //
126
+ // n = number of tokens (A * n^n) A * n^2n * P //
127
+ // S = sum of final balances but x //
128
+ // P = product of final balances but x //
129
+ **************************************************************************************************************/
130
+
131
+ // Given that we need to have a greater final balance in, the invariant needs to be rounded up
108
132
  balances = [...balances];
109
133
  if (!invariant) invariant = _calculateInvariant(amp, balances, true);
110
134
  balances[tokenIndexOut] = MathSol.sub(balances[tokenIndexOut], amountOut);
@@ -120,6 +144,7 @@ export function _calcInGivenOut(
120
144
  MathSol.sub(finalBalanceIn, balances[tokenIndexIn]),
121
145
  1n,
122
146
  );
147
+
123
148
  amountIn = addFee(amountIn, fee);
124
149
  return amountIn;
125
150
  }
@@ -195,6 +220,61 @@ export function _calcBptOutGivenExactTokensIn(
195
220
  }
196
221
  }
197
222
 
223
+ export function _calcTokenInGivenExactBptOut(
224
+ amp: bigint,
225
+ balances: bigint[],
226
+ tokenIndexIn: number,
227
+ bptAmountOut: bigint,
228
+ bptTotalSupply: bigint,
229
+ fee: bigint,
230
+ invariant?: bigint,
231
+ ): bigint {
232
+ if (!invariant) invariant = _calculateInvariant(amp, balances, true);
233
+
234
+ const newInvariant = MathSol.mulUpFixed(
235
+ MathSol.divUpFixed(
236
+ MathSol.add(bptTotalSupply, bptAmountOut),
237
+ bptTotalSupply
238
+ ),
239
+ invariant
240
+ );
241
+
242
+ const newBalanceTokenIndex =
243
+ _getTokenBalanceGivenInvariantAndAllOtherBalances(
244
+ amp,
245
+ balances,
246
+ newInvariant,
247
+ tokenIndexIn
248
+ );
249
+ const amountInWithoutFee = MathSol.sub(
250
+ newBalanceTokenIndex,
251
+ balances[tokenIndexIn]
252
+ );
253
+
254
+ let sumBalances = BigInt(0);
255
+ for (let i = 0; i < balances.length; i++) {
256
+ sumBalances = MathSol.add(sumBalances, balances[i]);
257
+ }
258
+
259
+ // We can now compute how much extra balance is being deposited
260
+ // and used in virtual swaps, and charge swap fees accordingly.
261
+ const currentWeight = MathSol.divDownFixed(
262
+ balances[tokenIndexIn],
263
+ sumBalances
264
+ );
265
+ const taxablePercentage = MathSol.complementFixed(currentWeight);
266
+ const taxableAmount = MathSol.mulUpFixed(
267
+ amountInWithoutFee,
268
+ taxablePercentage
269
+ );
270
+ const nonTaxableAmount = MathSol.sub(amountInWithoutFee, taxableAmount);
271
+
272
+ return MathSol.add(
273
+ nonTaxableAmount,
274
+ MathSol.divUpFixed(taxableAmount, MathSol.sub(MathSol.ONE, fee))
275
+ );
276
+ }
277
+
198
278
  /*
199
279
  Flow of calculations:
200
280
  amountsTokenOut -> amountsOutProportional ->