@pendle/core-v2 0.2.3 → 0.4.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.
Files changed (87) hide show
  1. package/contracts/SuperComposableYield/ISuperComposableYield.sol +15 -5
  2. package/contracts/SuperComposableYield/implementations/RewardManager.sol +2 -2
  3. package/contracts/SuperComposableYield/implementations/SCYBase.sol +23 -3
  4. package/contracts/SuperComposableYield/implementations/SCYBaseWithRewards.sol +4 -7
  5. package/contracts/core/PendleMarket.sol +24 -22
  6. package/contracts/core/PendleMarketFactory.sol +7 -6
  7. package/contracts/core/PendleSCYImpl/PendleBenQiErc20SCY.sol +1 -1
  8. package/contracts/core/PendleSCYImpl/PendleBtrflySCY.sol +2 -7
  9. package/contracts/core/PendleSCYImpl/PendleYearnVaultSCY.sol +2 -7
  10. package/contracts/core/PendleYieldContractFactory.sol +12 -7
  11. package/contracts/core/PendleYieldToken.sol +93 -55
  12. package/contracts/core/router/PendleRouterCoreUpg.sol +35 -21
  13. package/contracts/core/router/PendleRouterProxy.sol +12 -6
  14. package/contracts/core/router/PendleRouterStaticUpg.sol +43 -18
  15. package/contracts/core/router/PendleRouterYTUpg.sol +47 -13
  16. package/contracts/core/router/base/PendleRouterOTBaseUpg.sol +22 -32
  17. package/contracts/core/router/base/PendleRouterSCYAndForgeBaseUpg.sol +4 -4
  18. package/contracts/core/router/base/PendleRouterYTBaseUpg.sol +62 -43
  19. package/contracts/interfaces/IPMarket.sol +4 -2
  20. package/contracts/interfaces/{IPPermissionsV2.sol → IPPermissionsV2Upg.sol} +1 -1
  21. package/contracts/interfaces/IPRouterCore.sol +24 -21
  22. package/contracts/interfaces/IPRouterStatic.sol +10 -1
  23. package/contracts/interfaces/IPRouterYT.sol +16 -4
  24. package/contracts/interfaces/IPYieldContractFactory.sol +4 -0
  25. package/contracts/interfaces/IPYieldToken.sol +2 -4
  26. package/contracts/libraries/SCYIndex.sol +3 -3
  27. package/contracts/libraries/math/LogExpMath.sol +1 -90
  28. package/contracts/libraries/math/MarketApproxLib.sol +336 -94
  29. package/contracts/libraries/math/MarketMathAux.sol +101 -0
  30. package/contracts/libraries/math/MarketMathCore.sol +423 -0
  31. package/contracts/libraries/math/Math.sol +144 -0
  32. package/contracts/{core/misc → periphery}/PendleJoeSwapHelperUpg.sol +2 -2
  33. package/contracts/periphery/{PermissionsV2.sol → PermissionsV2Upg.sol} +2 -2
  34. package/package.json +1 -1
  35. package/typechain-types/IPMarket.ts +22 -11
  36. package/typechain-types/IPRouterCore.ts +68 -58
  37. package/typechain-types/IPRouterStatic.ts +52 -0
  38. package/typechain-types/IPRouterYT.ts +96 -12
  39. package/typechain-types/IPYieldContractFactory.ts +32 -0
  40. package/typechain-types/IPYieldToken.ts +14 -48
  41. package/typechain-types/IPermissionsV2Upg.ts +87 -0
  42. package/typechain-types/ISuperComposableYield.ts +98 -11
  43. package/typechain-types/OwnableUpgradeable.ts +165 -0
  44. package/typechain-types/PendleAaveV3SCY.ts +98 -11
  45. package/typechain-types/PendleBenQiErc20SCY.ts +98 -11
  46. package/typechain-types/PendleBtrflyScy.ts +98 -11
  47. package/typechain-types/PendleMarket.ts +22 -11
  48. package/typechain-types/PendleRouterCoreUpg.ts +66 -48
  49. package/typechain-types/PendleRouterProxy.ts +15 -118
  50. package/typechain-types/PendleRouterStaticUpg.ts +92 -0
  51. package/typechain-types/PendleRouterYTUpg.ts +96 -12
  52. package/typechain-types/PendleYearnVaultScy.ts +98 -11
  53. package/typechain-types/PendleYieldContractFactory.ts +40 -113
  54. package/typechain-types/PendleYieldToken.ts +106 -7
  55. package/typechain-types/PermissionsV2Upg.ts +87 -0
  56. package/typechain-types/SCYBase.ts +98 -11
  57. package/typechain-types/SCYBaseWithRewards.ts +98 -11
  58. package/typechain-types/factories/IPMarket__factory.ts +8 -2
  59. package/typechain-types/factories/IPRouterCore__factory.ts +38 -23
  60. package/typechain-types/factories/IPRouterStatic__factory.ts +29 -0
  61. package/typechain-types/factories/IPRouterYT__factory.ts +65 -6
  62. package/typechain-types/factories/IPYieldContractFactory__factory.ts +38 -0
  63. package/typechain-types/factories/IPYieldToken__factory.ts +1 -20
  64. package/typechain-types/factories/IPermissionsV2Upg__factory.ts +39 -0
  65. package/typechain-types/factories/ISuperComposableYield__factory.ts +65 -2
  66. package/typechain-types/factories/OwnableUpgradeable__factory.ts +78 -0
  67. package/typechain-types/factories/PendleAaveV3SCY__factory.ts +66 -3
  68. package/typechain-types/factories/PendleBenQiErc20SCY__factory.ts +66 -3
  69. package/typechain-types/factories/PendleBtrflyScy__factory.ts +66 -3
  70. package/typechain-types/factories/PendleMarketFactory__factory.ts +1 -1
  71. package/typechain-types/factories/PendleMarket__factory.ts +9 -3
  72. package/typechain-types/factories/PendleRouterCoreUpg__factory.ts +26 -11
  73. package/typechain-types/factories/PendleRouterProxy__factory.ts +14 -67
  74. package/typechain-types/factories/PendleRouterStaticUpg__factory.ts +63 -17
  75. package/typechain-types/factories/PendleRouterYTUpg__factory.ts +66 -7
  76. package/typechain-types/factories/PendleYearnVaultScy__factory.ts +66 -3
  77. package/typechain-types/factories/PendleYieldContractFactory__factory.ts +39 -54
  78. package/typechain-types/factories/PendleYieldToken__factory.ts +53 -2
  79. package/typechain-types/factories/PermissionsV2Upg__factory.ts +39 -0
  80. package/typechain-types/factories/SCYBaseWithRewards__factory.ts +65 -2
  81. package/typechain-types/factories/SCYBase__factory.ts +65 -2
  82. package/typechain-types/hardhat.d.ts +26 -53
  83. package/typechain-types/index.ts +8 -14
  84. package/contracts/core/misc/BoringOwnable.sol +0 -62
  85. package/contracts/core/misc/BoringOwnableUpg.sol +0 -64
  86. package/contracts/libraries/math/FixedPoint.sol +0 -205
  87. package/contracts/libraries/math/MarketMathLib.sol +0 -614
@@ -1,140 +1,382 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-or-later
2
2
  pragma solidity 0.8.9;
3
3
 
4
- import "./FixedPoint.sol";
5
- import "./MarketMathLib.sol";
4
+ import "./Math.sol";
5
+ import "./MarketMathCore.sol";
6
+ import "./MarketMathCore.sol";
7
+
8
+ struct ApproxParams {
9
+ uint256 guessMin;
10
+ uint256 guessMax;
11
+ uint256 maxIteration;
12
+ uint256 eps;
13
+ }
6
14
 
7
15
  // solhint-disable reason-string, ordering
8
16
  library MarketApproxLib {
9
- using FixedPoint for uint256;
10
- using FixedPoint for int256;
17
+ using Math for uint256;
18
+ using Math for int256;
11
19
  using LogExpMath for int256;
12
20
  using SCYIndexLib for SCYIndex;
13
- using MarketMathLib for MarketParameters;
14
-
15
- struct ApproxSwapExactScyForYtSlot {
16
- uint256 low;
17
- uint256 high;
18
- bool isAcceptableAnswerExisted;
19
- uint256 currentYtOutGuess;
20
- uint256 otToMarket;
21
- uint256 scyReceived;
22
- uint256 totalScyToMintYo;
23
- uint256 netYoFromScy;
24
- bool isResultAcceptable;
21
+ using MarketMathCore for MarketState;
22
+
23
+ function approxSwapOtForExactScy(
24
+ MarketState memory market,
25
+ SCYIndex index,
26
+ uint256 minScyOut,
27
+ uint256 blockTime,
28
+ ApproxParams memory approx
29
+ )
30
+ internal
31
+ pure
32
+ returns (
33
+ uint256, /*netOtIn*/
34
+ uint256 /*netScyOut*/
35
+ )
36
+ {
37
+ /// ------------------------------------------------------------
38
+ /// CHECKS
39
+ /// ------------------------------------------------------------
40
+ require(minScyOut > 0, "invalid minScyOut");
41
+ require(isValidApproxParams(approx), "invalid approx approx");
42
+
43
+ /// ------------------------------------------------------------
44
+ /// SET UP VAIRBALES
45
+ /// ------------------------------------------------------------
46
+ uint256 minAssetOut = index.scyToAsset(minScyOut);
47
+ uint256 largestGoodSlope;
48
+ bool isSlopeNonNeg;
49
+
50
+ MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
51
+
52
+ if (approx.guessMax == type(uint256).max) {
53
+ approx.guessMax = calcMaxOtIn(market.totalOt, comp.totalAsset);
54
+ }
55
+
56
+ /// ------------------------------------------------------------
57
+ /// BINARY SEARCH
58
+ /// ------------------------------------------------------------
59
+
60
+ while (approx.maxIteration != 0) {
61
+ unchecked {
62
+ approx.maxIteration--;
63
+ }
64
+ uint256 otInGuess = (approx.guessMin + approx.guessMax) / 2;
65
+
66
+ /// ------------------------------------------------------------
67
+ /// CHECK SLOPE
68
+ /// ------------------------------------------------------------
69
+ (isSlopeNonNeg, largestGoodSlope) = updateSlope(
70
+ market.totalOt,
71
+ otInGuess,
72
+ comp,
73
+ largestGoodSlope
74
+ );
75
+ if (!isSlopeNonNeg) {
76
+ approx.guessMax = otInGuess;
77
+ continue;
78
+ }
79
+
80
+ /// ------------------------------------------------------------
81
+ /// CHECK ASSET
82
+ /// ------------------------------------------------------------
83
+ (int256 _assetToAccount, ) = market.calcTrade(comp, otInGuess.neg());
84
+ uint256 netAssetOut = _assetToAccount.Uint();
85
+
86
+ if (netAssetOut >= minAssetOut) {
87
+ approx.guessMax = otInGuess;
88
+ /// ------------------------------------------------------------
89
+ /// CHECK IF ANSWER FOUND
90
+ /// ------------------------------------------------------------
91
+ if (Math.isAGreaterApproxB(netAssetOut, minAssetOut, approx.eps)) {
92
+ return (otInGuess, index.assetToScy(netAssetOut));
93
+ }
94
+ } else {
95
+ approx.guessMin = otInGuess + 1;
96
+ }
97
+ }
98
+ revert("approx fail");
25
99
  }
26
100
 
27
101
  function approxSwapExactScyForOt(
28
- MarketParameters memory marketImmutable,
102
+ MarketState memory market,
29
103
  SCYIndex index,
30
- uint256 exactScyIn,
104
+ uint256 maxScyIn,
31
105
  uint256 blockTime,
32
- uint256 netOtOutGuessMin,
33
- uint256 netOtOutGuessMax
34
- ) internal pure returns (uint256 netOtOut) {
35
- require(exactScyIn > 0, "invalid scy in");
36
- require(
37
- netOtOutGuessMin >= 0 && netOtOutGuessMax >= 0 && netOtOutGuessMin <= netOtOutGuessMax,
38
- "invalid guess"
39
- );
106
+ ApproxParams memory approx
107
+ )
108
+ internal
109
+ pure
110
+ returns (
111
+ uint256, /*netOtOut*/
112
+ uint256 /*netScyIn*/
113
+ )
114
+ {
115
+ /// ------------------------------------------------------------
116
+ /// CHECKS
117
+ /// ------------------------------------------------------------
118
+ require(maxScyIn > 0, "invalid maxScyIn");
119
+ require(isValidApproxParams(approx), "invalid approx approx");
120
+
121
+ /// ------------------------------------------------------------
122
+ /// SET UP VAIRBALES
123
+ /// ------------------------------------------------------------
124
+ uint256 maxAssetIn = index.scyToAsset(maxScyIn);
125
+
126
+ MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
40
127
 
41
- uint256 low = netOtOutGuessMin;
42
- uint256 high = netOtOutGuessMax;
43
- bool isAcceptableAnswerExisted;
128
+ if (approx.guessMax == type(uint256).max) {
129
+ approx.guessMax = calcMaxOtOut(market.totalOt, comp);
130
+ }
131
+
132
+ /// ------------------------------------------------------------
133
+ /// BINARY SEARCH
134
+ /// ------------------------------------------------------------
135
+
136
+ while (approx.maxIteration != 0) {
137
+ unchecked {
138
+ approx.maxIteration--;
139
+ }
140
+ uint256 otOutGuess = (approx.guessMin + approx.guessMax + 1) / 2;
44
141
 
45
- while (low != high) {
46
- uint256 currentOtOutGuess = (low + high + 1) / 2;
47
- MarketParameters memory market = MarketMathLib.deepCloneMarket(marketImmutable);
142
+ /// ------------------------------------------------------------
143
+ /// CHECK ASSET
144
+ /// ------------------------------------------------------------
145
+ (int256 _assetToAccount, ) = market.calcTrade(comp, otOutGuess.Int());
146
+ uint256 netAssetIn = _assetToAccount.neg().Uint();
48
147
 
49
- (uint256 netScyNeed, ) = market.swapScyForExactOt(index, currentOtOutGuess, blockTime);
50
- bool isResultAcceptable = (netScyNeed <= exactScyIn);
51
- if (isResultAcceptable) {
52
- low = currentOtOutGuess;
53
- isAcceptableAnswerExisted = true;
54
- } else high = currentOtOutGuess - 1;
148
+ if (netAssetIn <= maxAssetIn) {
149
+ approx.guessMin = otOutGuess;
150
+ /// ------------------------------------------------------------
151
+ /// CHECK IF ANSWER FOUND
152
+ /// ------------------------------------------------------------
153
+ if (Math.isASmallerApproxB(netAssetIn, maxAssetIn, approx.eps)) {
154
+ return (otOutGuess, index.assetToScy(netAssetIn));
155
+ }
156
+ } else {
157
+ approx.guessMax = otOutGuess - 1;
158
+ }
55
159
  }
160
+ revert("approx fail");
161
+ }
56
162
 
57
- require(isAcceptableAnswerExisted, "guess fail");
58
- netOtOut = low;
163
+ struct SlotSwapExactScyForYt {
164
+ uint256 otInGuess;
165
+ int256 _assetToAccount;
166
+ uint256 netAssetOut;
167
+ uint256 amountAssetNeedMore;
59
168
  }
60
169
 
61
- function approxSwapOtForExactScy(
62
- MarketParameters memory marketImmutable,
170
+ function approxSwapExactScyForYt(
171
+ MarketState memory market,
63
172
  SCYIndex index,
64
- uint256 exactScyOut,
173
+ uint256 maxScyIn,
65
174
  uint256 blockTime,
66
- uint256 netOtInGuessMin,
67
- uint256 netOtInGuessMax
68
- ) internal pure returns (uint256 netOtIn) {
69
- require(exactScyOut > 0, "invalid scy in");
70
- require(
71
- netOtInGuessMin >= 0 && netOtInGuessMax >= 0 && netOtInGuessMin <= netOtInGuessMax,
72
- "invalid guess"
73
- );
175
+ ApproxParams memory approx
176
+ )
177
+ internal
178
+ pure
179
+ returns (
180
+ uint256, /*netYtOut*/
181
+ uint256 /*netScyIn*/
182
+ )
183
+ {
184
+ /// ------------------------------------------------------------
185
+ /// CHECKS
186
+ /// ------------------------------------------------------------
187
+ require(maxScyIn > 0, "invalid maxScyIn");
188
+ require(isValidApproxParams(approx), "invalid approx approx");
189
+
190
+ /// ------------------------------------------------------------
191
+ /// SET UP VAIRBALES
192
+ /// ------------------------------------------------------------
193
+ uint256 maxAssetIn = index.scyToAsset(maxScyIn);
194
+ uint256 largestGoodSlope;
195
+ bool isSlopeNonNeg;
196
+
197
+ MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
74
198
 
75
- uint256 low = netOtInGuessMin;
76
- uint256 high = netOtInGuessMax;
77
- bool isAcceptableAnswerExisted;
199
+ if (approx.guessMax == type(uint256).max) {
200
+ approx.guessMax = calcMaxOtIn(market.totalOt, comp.totalAsset);
201
+ }
202
+
203
+ /// ------------------------------------------------------------
204
+ /// BINARY SEARCH
205
+ /// ------------------------------------------------------------
206
+
207
+ while (approx.maxIteration != 0) {
208
+ unchecked {
209
+ approx.maxIteration--;
210
+ }
78
211
 
79
- while (low != high) {
80
- uint256 currentOtInGuess = (low + high) / 2;
81
- MarketParameters memory market = MarketMathLib.deepCloneMarket(marketImmutable);
212
+ SlotSwapExactScyForYt memory slot;
213
+ // ytOutGuess = otInGuess
214
+ slot.otInGuess = (approx.guessMin + approx.guessMax + 1) / 2;
82
215
 
83
- (uint256 netScyToAccount, ) = market.swapExactOtForScy(
84
- index,
85
- currentOtInGuess,
86
- blockTime
216
+ /// ------------------------------------------------------------
217
+ /// CHECK SLOPE
218
+ /// ------------------------------------------------------------
219
+ (isSlopeNonNeg, largestGoodSlope) = updateSlope(
220
+ market.totalOt,
221
+ slot.otInGuess,
222
+ comp,
223
+ largestGoodSlope
87
224
  );
88
- bool isResultAcceptable = (netScyToAccount >= exactScyOut);
89
- if (isResultAcceptable) {
90
- high = currentOtInGuess;
91
- isAcceptableAnswerExisted = true;
225
+ if (!isSlopeNonNeg) {
226
+ approx.guessMax = slot.otInGuess - 1;
227
+ continue;
228
+ }
229
+
230
+ /// ------------------------------------------------------------
231
+ /// CHECK ASSET
232
+ /// ------------------------------------------------------------
233
+ (slot._assetToAccount, ) = market.calcTrade(comp, slot.otInGuess.neg());
234
+ slot.netAssetOut = slot._assetToAccount.Uint();
235
+ slot.amountAssetNeedMore = slot.otInGuess - slot.netAssetOut;
236
+
237
+ if (slot.amountAssetNeedMore <= maxAssetIn) {
238
+ approx.guessMin = slot.otInGuess;
239
+ /// ------------------------------------------------------------
240
+ /// CHECK IF ANSWER FOUND
241
+ /// ------------------------------------------------------------
242
+ if (Math.isASmallerApproxB(slot.amountAssetNeedMore, maxAssetIn, approx.eps)) {
243
+ return (slot.otInGuess, index.assetToScy(slot.amountAssetNeedMore));
244
+ }
92
245
  } else {
93
- low = currentOtInGuess + 1;
246
+ approx.guessMax = slot.otInGuess - 1;
94
247
  }
95
248
  }
96
-
97
- require(isAcceptableAnswerExisted, "guess fail");
98
- netOtIn = high;
249
+ revert("approx fail");
99
250
  }
100
251
 
101
- function approxSwapExactScyForYt(
102
- MarketParameters memory marketImmutable,
252
+ function approxSwapYtForExactScy(
253
+ MarketState memory market,
103
254
  SCYIndex index,
104
- uint256 exactScyIn,
255
+ uint256 minScyOut,
105
256
  uint256 blockTime,
106
- uint256 netYtOutGuessMin,
107
- uint256 netYtOutGuessMax
108
- ) internal pure returns (uint256 netYtOut) {
109
- require(exactScyIn > 0, "invalid scy in");
110
- require(netYtOutGuessMin >= 0 && netYtOutGuessMax >= 0, "invalid guess");
257
+ ApproxParams memory approx
258
+ )
259
+ internal
260
+ pure
261
+ returns (
262
+ uint256, /*netYtIn*/
263
+ uint256 /*netScyOut*/
264
+ )
265
+ {
266
+ /// ------------------------------------------------------------
267
+ /// CHECKS
268
+ /// ------------------------------------------------------------
269
+ require(minScyOut > 0, "invalid maxScyIn");
270
+ require(isValidApproxParams(approx), "invalid approx approx");
271
+
272
+ /// ------------------------------------------------------------
273
+ /// SET UP VAIRBALES
274
+ /// ------------------------------------------------------------
275
+ uint256 minAssetOut = index.scyToAsset(minScyOut);
111
276
 
112
- ApproxSwapExactScyForYtSlot memory slot;
277
+ MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
113
278
 
114
- slot.low = netYtOutGuessMin;
115
- slot.high = netYtOutGuessMax;
279
+ if (approx.guessMax == type(uint256).max) {
280
+ approx.guessMax = calcMaxOtOut(market.totalOt, comp);
281
+ }
116
282
 
117
- while (slot.low != slot.high) {
118
- slot.currentYtOutGuess = (slot.low + slot.high + 1) / 2;
119
- MarketParameters memory market = MarketMathLib.deepCloneMarket(marketImmutable);
283
+ /// ------------------------------------------------------------
284
+ /// BINARY SEARCH
285
+ /// ------------------------------------------------------------
120
286
 
121
- slot.otToMarket = slot.currentYtOutGuess;
287
+ while (approx.maxIteration != 0) {
288
+ unchecked {
289
+ approx.maxIteration--;
290
+ }
291
+ // ytInGuess = otOutGuess
292
+ uint256 otOutGuess = (approx.guessMin + approx.guessMax) / 2;
122
293
 
123
- (slot.scyReceived, ) = market.swapExactOtForScy(index, slot.otToMarket, blockTime);
294
+ /// ------------------------------------------------------------
295
+ /// CHECK ASSET
296
+ /// ------------------------------------------------------------
297
+ (int256 _assetToAccount, ) = market.calcTrade(comp, otOutGuess.Int());
298
+ uint256 netAssetOwed = _assetToAccount.neg().Uint();
124
299
 
125
- slot.totalScyToMintYo = slot.scyReceived + exactScyIn;
300
+ // since otOutGuess is between guessMin & guessMax, it's guaranteed that
301
+ // there are enough Yt to pair with otOut
126
302
 
127
- slot.netYoFromScy = index.scyToAsset(slot.totalScyToMintYo);
303
+ uint256 netAssetOut = otOutGuess - netAssetOwed;
128
304
 
129
- bool isResultAcceptable = (slot.netYoFromScy >= slot.currentYtOutGuess);
305
+ if (netAssetOut >= minAssetOut) {
306
+ approx.guessMax = otOutGuess;
307
+ /// ------------------------------------------------------------
308
+ /// CHECK IF ANSWER FOUND
309
+ /// ------------------------------------------------------------
310
+ if (Math.isAGreaterApproxB(netAssetOut, minAssetOut, approx.eps)) {
311
+ return (otOutGuess, index.assetToScy(netAssetOut));
312
+ }
313
+ } else {
314
+ approx.guessMin = otOutGuess + 1;
315
+ }
316
+ }
317
+ revert("approx fail");
318
+ }
130
319
 
131
- if (isResultAcceptable) {
132
- slot.low = slot.currentYtOutGuess;
133
- slot.isAcceptableAnswerExisted = true;
134
- } else slot.high = slot.currentYtOutGuess - 1;
320
+ function updateSlope(
321
+ int256 totalOt,
322
+ uint256 otInGuess,
323
+ MarketPreCompute memory comp,
324
+ uint256 largestGoodSlope
325
+ ) internal pure returns (bool isSlopeNonNeg, uint256 newLargestGoodSlop) {
326
+ if (otInGuess <= largestGoodSlope) {
327
+ return (true, largestGoodSlope);
135
328
  }
329
+ // it's not guaranteed that the current slop is good
330
+ // we therefore have to recalculate the slope
331
+ int256 slope = slopeFactor(totalOt, otInGuess.neg(), comp);
332
+ if (slope >= 0) return (true, otInGuess);
333
+ else return (false, largestGoodSlope);
334
+ }
335
+
336
+ // otToMarket < totalAsset && totalOt
337
+ function slopeFactor(
338
+ int256 totalOt,
339
+ int256 otToAccount,
340
+ MarketPreCompute memory comp
341
+ ) internal pure returns (int256) {
342
+ int256 otToMarket = -otToAccount;
343
+ int256 diffAssetOtToMarket = comp.totalAsset - otToMarket;
344
+ int256 sumOt = otToMarket + totalOt;
345
+
346
+ require(diffAssetOtToMarket > 0 && sumOt > 0, "invalid otToMarket");
347
+
348
+ int256 part1 = (otToMarket * (totalOt + comp.totalAsset)).divDown(
349
+ sumOt * diffAssetOtToMarket
350
+ );
351
+
352
+ int256 part2 = sumOt.divDown(diffAssetOtToMarket).ln();
353
+ int256 part3 = Math.IONE.divDown(comp.rateScalar);
354
+
355
+ return comp.rateAnchor - (part1 - part2).mulDown(part3);
356
+ }
357
+
358
+ function calcMaxOtOut(int256 totalOt, MarketPreCompute memory comp)
359
+ internal
360
+ pure
361
+ returns (uint256)
362
+ {
363
+ int256 logitP = (Math.IONE.mulDown(comp.feeRate) - comp.rateAnchor)
364
+ .mulDown(comp.rateScalar)
365
+ .exp();
366
+ int256 proportion = logitP.divDown(logitP + Math.IONE);
367
+ int256 numerator = proportion.mulDown(totalOt + comp.totalAsset);
368
+ int256 maxOtOut = totalOt - numerator;
369
+ // TODO: 999 & 1000 are magic numbers
370
+ return (maxOtOut.Uint() * 999) / 1000;
371
+ }
372
+
373
+ function calcMaxOtIn(int256 totalOt, int256 totalAsset) internal pure returns (uint256) {
374
+ return Math.min(totalOt, totalAsset).Uint() - 1;
375
+ }
136
376
 
137
- require(slot.isAcceptableAnswerExisted, "guess fail");
138
- netYtOut = slot.low;
377
+ function isValidApproxParams(ApproxParams memory approx) internal pure returns (bool) {
378
+ return (approx.guessMin <= approx.guessMax &&
379
+ approx.maxIteration <= 256 &&
380
+ approx.eps <= Math.ONE);
139
381
  }
140
382
  }
@@ -0,0 +1,101 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ pragma solidity 0.8.9;
3
+
4
+ import "./Math.sol";
5
+ import "./LogExpMath.sol";
6
+ import "../SCYIndex.sol";
7
+ import "./MarketMathCore.sol";
8
+
9
+ // solhint-disable ordering
10
+ library MarketMathAux {
11
+ using Math for uint256;
12
+ using Math for int256;
13
+
14
+ function addLiquidity(
15
+ MarketState memory market,
16
+ SCYIndex index,
17
+ uint256 scyDesired,
18
+ uint256 otDesired,
19
+ bool updateState
20
+ )
21
+ internal
22
+ pure
23
+ returns (
24
+ uint256 lpToReserve,
25
+ uint256 lpToAccount,
26
+ uint256 scyUsed,
27
+ uint256 otUsed
28
+ )
29
+ {
30
+ (
31
+ int256 _lpToReserve,
32
+ int256 _lpToAccount,
33
+ int256 _scyUsed,
34
+ int256 _otUsed
35
+ ) = MarketMathCore.addLiquidityCore(
36
+ market,
37
+ index,
38
+ scyDesired.Int(),
39
+ otDesired.Int(),
40
+ updateState
41
+ );
42
+
43
+ lpToReserve = _lpToReserve.Uint();
44
+ lpToAccount = _lpToAccount.Uint();
45
+ scyUsed = _scyUsed.Uint();
46
+ otUsed = _otUsed.Uint();
47
+ }
48
+
49
+ function removeLiquidity(
50
+ MarketState memory market,
51
+ uint256 lpToRemove,
52
+ bool updateState
53
+ ) internal pure returns (uint256 scyToAccount, uint256 netOtToAccount) {
54
+ (int256 _scyToAccount, int256 _otToAccount) = MarketMathCore.removeLiquidityCore(
55
+ market,
56
+ lpToRemove.Int(),
57
+ updateState
58
+ );
59
+
60
+ scyToAccount = _scyToAccount.Uint();
61
+ netOtToAccount = _otToAccount.Uint();
62
+ }
63
+
64
+ function swapExactOtForScy(
65
+ MarketState memory market,
66
+ SCYIndex index,
67
+ uint256 exactOtToMarket,
68
+ uint256 blockTime,
69
+ bool updateState
70
+ ) internal pure returns (uint256 netScyToAccount, uint256 netScyToReserve) {
71
+ (int256 _netScyToAccount, int256 _netScyToReserve) = MarketMathCore.executeTradeCore(
72
+ market,
73
+ index,
74
+ exactOtToMarket.neg(),
75
+ blockTime,
76
+ updateState
77
+ );
78
+
79
+ netScyToAccount = _netScyToAccount.Uint();
80
+ netScyToReserve = _netScyToReserve.Uint();
81
+ }
82
+
83
+ function swapScyForExactOt(
84
+ MarketState memory market,
85
+ SCYIndex index,
86
+ uint256 exactOtToAccount,
87
+ uint256 blockTime,
88
+ bool updateState
89
+ ) internal pure returns (uint256 netScyToMarket, uint256 netScyToReserve) {
90
+ (int256 _netScyToAccount, int256 _netScyToReserve) = MarketMathCore.executeTradeCore(
91
+ market,
92
+ index,
93
+ exactOtToAccount.Int(),
94
+ blockTime,
95
+ updateState
96
+ );
97
+
98
+ netScyToMarket = _netScyToAccount.neg().Uint();
99
+ netScyToReserve = _netScyToReserve.Uint();
100
+ }
101
+ }