@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
@@ -0,0 +1,423 @@
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
+
8
+ struct MarketState {
9
+ int256 totalOt;
10
+ int256 totalScy;
11
+ int256 totalLp;
12
+ uint256 oracleRate;
13
+ /// immutable variables ///
14
+ int256 scalarRoot;
15
+ uint256 feeRateRoot;
16
+ uint256 rateOracleTimeWindow;
17
+ uint256 expiry;
18
+ int256 reserveFeePercent; // base 100
19
+ /// last trade data ///
20
+ uint256 lastImpliedRate;
21
+ uint256 lastTradeTime;
22
+ }
23
+
24
+ // params that are expensive to compute, therefore we pre-compute them
25
+ struct MarketPreCompute {
26
+ int256 rateScalar;
27
+ int256 totalAsset;
28
+ int256 rateAnchor;
29
+ int256 feeRate;
30
+ }
31
+
32
+ struct MarketStorage {
33
+ int128 totalOt;
34
+ int128 totalScy;
35
+ uint112 lastImpliedRate;
36
+ uint112 oracleRate;
37
+ uint32 lastTradeTime;
38
+ }
39
+
40
+ // solhint-disable ordering
41
+ library MarketMathCore {
42
+ using Math for uint256;
43
+ using Math for int256;
44
+ using LogExpMath for int256;
45
+ using SCYIndexLib for SCYIndex;
46
+
47
+ int256 internal constant MINIMUM_LIQUIDITY = 10**3;
48
+ int256 internal constant PERCENTAGE_DECIMALS = 100;
49
+ uint256 internal constant DAY = 86400;
50
+ uint256 internal constant IMPLIED_RATE_TIME = 360 * DAY;
51
+
52
+ int256 internal constant MAX_MARKET_PROPORTION = (1e18 * 96) / 100;
53
+
54
+ function addLiquidityCore(
55
+ MarketState memory market,
56
+ SCYIndex index,
57
+ int256 scyDesired,
58
+ int256 otDesired,
59
+ bool updateState
60
+ )
61
+ internal
62
+ pure
63
+ returns (
64
+ int256 lpToReserve,
65
+ int256 lpToAccount,
66
+ int256 scyUsed,
67
+ int256 otUsed
68
+ )
69
+ {
70
+ /// ------------------------------------------------------------
71
+ /// CHECKS
72
+ /// ------------------------------------------------------------
73
+ require(scyDesired > 0 && otDesired > 0, "ZERO_AMOUNTS");
74
+
75
+ /// ------------------------------------------------------------
76
+ /// MATH
77
+ /// ------------------------------------------------------------
78
+ if (market.totalLp == 0) {
79
+ lpToAccount = index.scyToAsset(scyDesired).subNoNeg(MINIMUM_LIQUIDITY);
80
+ lpToReserve = MINIMUM_LIQUIDITY;
81
+ scyUsed = scyDesired;
82
+ otUsed = otDesired;
83
+ } else {
84
+ int256 netLpByOt = (otDesired * market.totalLp) / market.totalOt;
85
+ int256 netLpByScy = (scyDesired * market.totalLp) / market.totalScy;
86
+ if (netLpByOt < netLpByScy) {
87
+ lpToAccount = netLpByOt;
88
+ otUsed = otDesired;
89
+ scyUsed = (market.totalScy * lpToAccount) / market.totalLp;
90
+ } else {
91
+ lpToAccount = netLpByScy;
92
+ scyUsed = scyDesired;
93
+ otUsed = (market.totalOt * lpToAccount) / market.totalLp;
94
+ }
95
+ }
96
+
97
+ require(lpToAccount > 0, "INSUFFICIENT_LIQUIDITY_MINTED");
98
+
99
+ /// ------------------------------------------------------------
100
+ /// WRITE
101
+ /// ------------------------------------------------------------
102
+ if (updateState) {
103
+ market.totalScy += scyUsed;
104
+ market.totalOt += otUsed;
105
+ market.totalLp += lpToAccount + lpToReserve;
106
+ }
107
+ }
108
+
109
+ function removeLiquidityCore(
110
+ MarketState memory market,
111
+ int256 lpToRemove,
112
+ bool updateState
113
+ ) internal pure returns (int256 scyToAccount, int256 netOtToAccount) {
114
+ /// ------------------------------------------------------------
115
+ /// CHECKS
116
+ /// ------------------------------------------------------------
117
+ require(lpToRemove > 0, "invalid lp amount");
118
+
119
+ /// ------------------------------------------------------------
120
+ /// MATH
121
+ /// ------------------------------------------------------------
122
+ scyToAccount = (lpToRemove * market.totalScy) / market.totalLp;
123
+ netOtToAccount = (lpToRemove * market.totalOt) / market.totalLp;
124
+
125
+ /// ------------------------------------------------------------
126
+ /// WRITE
127
+ /// ------------------------------------------------------------
128
+ if (updateState) {
129
+ market.totalLp = market.totalLp.subNoNeg(lpToRemove);
130
+ market.totalOt = market.totalOt.subNoNeg(netOtToAccount);
131
+ market.totalScy = market.totalScy.subNoNeg(scyToAccount);
132
+ }
133
+ }
134
+
135
+ function executeTradeCore(
136
+ MarketState memory market,
137
+ SCYIndex index,
138
+ int256 netOtToAccount,
139
+ uint256 blockTime,
140
+ bool updateState
141
+ ) internal pure returns (int256 netScyToAccount, int256 netScyToReserve) {
142
+ /// ------------------------------------------------------------
143
+ /// CHECKS
144
+ /// ------------------------------------------------------------
145
+ require(blockTime < market.expiry, "market expired");
146
+ require(market.totalOt > netOtToAccount, "insufficient liquidity");
147
+
148
+ /// ------------------------------------------------------------
149
+ /// MATH
150
+ /// ------------------------------------------------------------
151
+ MarketPreCompute memory comp = getMarketPreCompute(market, index, blockTime);
152
+
153
+ (int256 netAssetToAccount, int256 netAssetToReserve) = calcTrade(
154
+ market,
155
+ comp,
156
+ netOtToAccount
157
+ );
158
+
159
+ netScyToAccount = index.assetToScy(netAssetToAccount);
160
+ netScyToReserve = index.assetToScy(netAssetToReserve);
161
+
162
+ /// ------------------------------------------------------------
163
+ /// WRITE
164
+ /// ------------------------------------------------------------
165
+ if (updateState) {
166
+ _setNewMarketStateTrade(
167
+ market,
168
+ comp,
169
+ index,
170
+ netOtToAccount,
171
+ netScyToAccount,
172
+ blockTime
173
+ );
174
+ }
175
+ }
176
+
177
+ function getMarketPreCompute(
178
+ MarketState memory market,
179
+ SCYIndex index,
180
+ uint256 blockTime
181
+ ) internal pure returns (MarketPreCompute memory res) {
182
+ require(blockTime < market.expiry, "market expired");
183
+
184
+ uint256 timeToExpiry = market.expiry - blockTime;
185
+
186
+ res.rateScalar = _getRateScalar(market, timeToExpiry);
187
+ res.totalAsset = index.scyToAsset(market.totalScy);
188
+
189
+ require(market.totalOt != 0 && res.totalAsset != 0, "invalid market state");
190
+
191
+ res.rateAnchor = _getRateAnchor(
192
+ market.totalOt,
193
+ market.lastImpliedRate,
194
+ res.totalAsset,
195
+ res.rateScalar,
196
+ timeToExpiry
197
+ );
198
+ res.feeRate = _getExchangeRateFromImpliedRate(market.feeRateRoot, timeToExpiry);
199
+ }
200
+
201
+ function calcTrade(
202
+ MarketState memory market,
203
+ MarketPreCompute memory comp,
204
+ int256 netOtToAccount
205
+ ) internal pure returns (int256 netAssetToAccount, int256 netAssetToReserve) {
206
+ int256 preFeeExchangeRate = _getExchangeRate(
207
+ market.totalOt,
208
+ comp.totalAsset,
209
+ comp.rateScalar,
210
+ comp.rateAnchor,
211
+ netOtToAccount
212
+ );
213
+
214
+ int256 preFeeAssetToAccount = netOtToAccount.divDown(preFeeExchangeRate).neg();
215
+ int256 fee = comp.feeRate;
216
+
217
+ if (netOtToAccount > 0) {
218
+ int256 postFeeExchangeRate = preFeeExchangeRate.divDown(fee);
219
+ require(postFeeExchangeRate >= Math.IONE, "exchange rate below 1");
220
+ fee = preFeeAssetToAccount.mulDown(Math.IONE - fee);
221
+ } else {
222
+ fee = ((preFeeAssetToAccount * (Math.IONE - fee)) / fee).neg();
223
+ }
224
+
225
+ netAssetToReserve = (fee * market.reserveFeePercent) / PERCENTAGE_DECIMALS;
226
+ netAssetToAccount = preFeeAssetToAccount - fee;
227
+ // netAssetToMarket = (preFeeAssetToAccount - fee + netAssetToReserve)
228
+ // .neg();
229
+ }
230
+
231
+ function _setNewMarketStateTrade(
232
+ MarketState memory market,
233
+ MarketPreCompute memory comp,
234
+ SCYIndex index,
235
+ int256 netOtToAccount,
236
+ int256 netScyToAccount,
237
+ uint256 blockTime
238
+ ) internal pure {
239
+ uint256 timeToExpiry = market.expiry - blockTime;
240
+
241
+ market.lastTradeTime = blockTime;
242
+
243
+ market.totalOt = market.totalOt.subNoNeg(netOtToAccount);
244
+ market.totalScy = market.totalScy.subNoNeg(netScyToAccount);
245
+
246
+ market.lastImpliedRate = _getImpliedRate(
247
+ market.totalOt,
248
+ index.scyToAsset(market.totalScy),
249
+ comp.rateScalar,
250
+ comp.rateAnchor,
251
+ timeToExpiry
252
+ );
253
+ require(market.lastImpliedRate != 0, "zero impliedRate");
254
+ }
255
+
256
+ function _getRateAnchor(
257
+ int256 totalOt,
258
+ uint256 lastImpliedRate,
259
+ int256 totalAsset,
260
+ int256 rateScalar,
261
+ uint256 timeToExpiry
262
+ ) internal pure returns (int256 rateAnchor) {
263
+ // This is the exchange rate at the new time to expiry
264
+ int256 newExchangeRate = _getExchangeRateFromImpliedRate(lastImpliedRate, timeToExpiry);
265
+
266
+ require(newExchangeRate >= Math.IONE, "exchange rate below 1");
267
+
268
+ {
269
+ // totalOt / (totalOt + totalAsset)
270
+ int256 proportion = totalOt.divDown(totalOt + totalAsset);
271
+
272
+ int256 lnProportion = _logProportion(proportion);
273
+
274
+ // newExchangeRate - ln(proportion / (1 - proportion)) / rateScalar
275
+ rateAnchor = newExchangeRate - lnProportion.divDown(rateScalar);
276
+ }
277
+ }
278
+
279
+ /// @notice Calculates the current market implied rate.
280
+ /// @return impliedRate the implied rate
281
+ function _getImpliedRate(
282
+ int256 totalOt,
283
+ int256 totalAsset,
284
+ int256 rateScalar,
285
+ int256 rateAnchor,
286
+ uint256 timeToExpiry
287
+ ) internal pure returns (uint256 impliedRate) {
288
+ // This will check for exchange rates < Math.IONE
289
+ int256 exchangeRate = _getExchangeRate(totalOt, totalAsset, rateScalar, rateAnchor, 0);
290
+
291
+ // exchangeRate >= 1 so its ln >= 0
292
+ uint256 lnRate = exchangeRate.ln().Uint();
293
+
294
+ impliedRate = (lnRate * IMPLIED_RATE_TIME) / timeToExpiry;
295
+ }
296
+
297
+ /// @notice Converts an implied rate to an exchange rate given a time to expiry. The
298
+ /// formula is E = e^rt
299
+ function _getExchangeRateFromImpliedRate(uint256 impliedRate, uint256 timeToExpiry)
300
+ internal
301
+ pure
302
+ returns (int256 exchangeRate)
303
+ {
304
+ uint256 rt = (impliedRate * timeToExpiry) / IMPLIED_RATE_TIME;
305
+
306
+ exchangeRate = LogExpMath.exp(rt.Int());
307
+ }
308
+
309
+ /// @notice Returns the exchange rate between OT and Asset for the given market
310
+ /// Calculates the following exchange rate:
311
+ /// (1 / rateScalar) * ln(proportion / (1 - proportion)) + rateAnchor
312
+ /// where:
313
+ /// proportion = totalOt / (totalOt + totalUnderlyingAsset)
314
+ function _getExchangeRate(
315
+ int256 totalOt,
316
+ int256 totalAsset,
317
+ int256 rateScalar,
318
+ int256 rateAnchor,
319
+ int256 netOtToAccount
320
+ ) internal pure returns (int256 exchangeRate) {
321
+ int256 numerator = totalOt.subNoNeg(netOtToAccount);
322
+
323
+ // This is the proportion scaled by Math.IONE
324
+ // (totalOt - netOtToAccount) / (totalOt + totalAsset)
325
+ int256 proportion = (numerator.divDown(totalOt + totalAsset));
326
+
327
+ // This limit is here to prevent the market from reaching extremely high interest rates via an
328
+ // excessively large proportion (high amounts of OT relative to Asset).
329
+ // Market proportion can only increase via swapping OT to SCY (OT is added to the market and SCY is
330
+ // removed). Over time, the yield from SCY will slightly decrease the proportion (the
331
+ // amount of Asset in the market must be monotonically increasing). Therefore it is not
332
+ // possible for the proportion to go over max market proportion unless borrowing occurs.
333
+ require(proportion <= MAX_MARKET_PROPORTION, "max proportion exceeded");
334
+
335
+ int256 lnProportion = _logProportion(proportion);
336
+
337
+ // lnProportion / rateScalar + rateAnchor
338
+ exchangeRate = lnProportion.divDown(rateScalar) + rateAnchor;
339
+
340
+ // Do not succeed if interest rates fall below 1
341
+ require(exchangeRate >= Math.IONE, "exchange rate below 1");
342
+ }
343
+
344
+ function _logProportion(int256 proportion) internal pure returns (int256 res) {
345
+ // This will result in divide by zero, short circuit
346
+ require(proportion != Math.IONE, "proportion must not be one");
347
+
348
+ // Convert proportion to what is used inside the logit function (p / (1-p))
349
+ int256 logitP = proportion.divDown(Math.IONE - proportion);
350
+
351
+ res = logitP.ln();
352
+ }
353
+
354
+ function _getRateScalar(MarketState memory market, uint256 timeToExpiry)
355
+ internal
356
+ pure
357
+ returns (int256 rateScalar)
358
+ {
359
+ rateScalar = (market.scalarRoot * IMPLIED_RATE_TIME.Int()) / timeToExpiry.Int();
360
+ require(rateScalar > 0, "rateScalar underflow");
361
+ }
362
+
363
+ function setInitialImpliedRate(
364
+ MarketState memory market,
365
+ SCYIndex index,
366
+ int256 initialAnchor,
367
+ uint256 blockTime
368
+ ) internal pure {
369
+ /// ------------------------------------------------------------
370
+ /// CHECKS
371
+ /// ------------------------------------------------------------
372
+ require(blockTime < market.expiry, "market expired");
373
+
374
+ /// ------------------------------------------------------------
375
+ /// MATH
376
+ /// ------------------------------------------------------------
377
+ int256 totalAsset = index.scyToAsset(market.totalScy);
378
+ uint256 timeToExpiry = market.expiry - blockTime;
379
+ int256 rateScalar = _getRateScalar(market, timeToExpiry);
380
+
381
+ /// ------------------------------------------------------------
382
+ /// WRITE
383
+ /// ------------------------------------------------------------
384
+ market.lastImpliedRate = _getImpliedRate(
385
+ market.totalOt,
386
+ totalAsset,
387
+ rateScalar,
388
+ initialAnchor,
389
+ market.expiry - blockTime
390
+ );
391
+ }
392
+
393
+ function updateNewRateOracle(MarketState memory market, uint256 blockTime)
394
+ internal
395
+ pure
396
+ returns (uint256)
397
+ {
398
+ // This can occur when using a view function get to a market state in the past
399
+ if (market.lastTradeTime > blockTime) {
400
+ market.oracleRate = market.lastImpliedRate;
401
+ return market.oracleRate;
402
+ }
403
+
404
+ uint256 timeDiff = blockTime - market.lastTradeTime;
405
+ if (timeDiff > market.rateOracleTimeWindow) {
406
+ // If past the time window just return the market.lastImpliedRate
407
+ market.oracleRate = market.lastImpliedRate;
408
+ return market.oracleRate;
409
+ }
410
+
411
+ // (currentTs - previousTs) / timeWindow
412
+ uint256 lastTradeWeight = timeDiff.divDown(market.rateOracleTimeWindow);
413
+
414
+ // 1 - (currentTs - previousTs) / timeWindow
415
+ uint256 oracleWeight = Math.ONE - lastTradeWeight;
416
+
417
+ uint256 newOracleRate = market.lastTradeTime.mulDown(lastTradeWeight) +
418
+ market.oracleRate.mulDown(oracleWeight);
419
+
420
+ market.oracleRate = newOracleRate;
421
+ return market.oracleRate;
422
+ }
423
+ }
@@ -0,0 +1,144 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ // This program is free software: you can redistribute it and/or modify
3
+ // it under the terms of the GNU General Public License as published by
4
+ // the Free Software Foundation, either version 3 of the License, or
5
+ // (at your option) any later version.
6
+
7
+ // This program is distributed in the hope that it will be useful,
8
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ // GNU General Public License for more details.
11
+
12
+ // You should have received a copy of the GNU General Public License
13
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
14
+
15
+ pragma solidity 0.8.9;
16
+
17
+ import "./LogExpMath.sol";
18
+
19
+ /* solhint-disable private-vars-leading-underscore, reason-string */
20
+
21
+ library Math {
22
+ uint256 internal constant ONE = 1e18; // 18 decimal places
23
+ int256 internal constant IONE = 1e18; // 18 decimal places
24
+
25
+ uint256 internal constant MAX_POW_RELATIVE_ERROR = 10000; // 10^(-14)
26
+
27
+ function subMax0(uint256 a, uint256 b) internal pure returns (uint256) {
28
+ unchecked {
29
+ return (a >= b ? a - b : 0);
30
+ }
31
+ }
32
+
33
+ function subNoNeg(int256 a, int256 b) internal pure returns (int256) {
34
+ require(a >= b, "NEGATIVE");
35
+ unchecked {
36
+ return a - b;
37
+ }
38
+ }
39
+
40
+ function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {
41
+ uint256 product = a * b;
42
+ unchecked {
43
+ return product / ONE;
44
+ }
45
+ }
46
+
47
+ function mulDown(int256 a, int256 b) internal pure returns (int256) {
48
+ int256 product = a * b;
49
+ unchecked {
50
+ return product / IONE;
51
+ }
52
+ }
53
+
54
+ function divDown(uint256 a, uint256 b) internal pure returns (uint256) {
55
+ uint256 aInflated = a * ONE;
56
+ unchecked {
57
+ return aInflated / b;
58
+ }
59
+ }
60
+
61
+ function divDown(int256 a, int256 b) internal pure returns (int256) {
62
+ int256 aInflated = a * IONE;
63
+ unchecked {
64
+ return aInflated / b;
65
+ }
66
+ }
67
+
68
+ function abs(int256 x) internal pure returns (uint256) {
69
+ return uint256(x > 0 ? x : -x);
70
+ }
71
+
72
+ function neg(int256 x) internal pure returns (int256) {
73
+ return -x;
74
+ }
75
+
76
+ function neg(uint256 x) internal pure returns (int256) {
77
+ return -Int(x);
78
+ }
79
+
80
+ function max(uint256 x, uint256 y) internal pure returns (uint256) {
81
+ return (x > y ? x : y);
82
+ }
83
+
84
+ function max(int256 x, int256 y) internal pure returns (int256) {
85
+ return (x > y ? x : y);
86
+ }
87
+
88
+ function min(uint256 x, uint256 y) internal pure returns (uint256) {
89
+ return (x < y ? x : y);
90
+ }
91
+
92
+ function min(int256 x, int256 y) internal pure returns (int256) {
93
+ return (x < y ? x : y);
94
+ }
95
+
96
+ function Uint(int256 x) internal pure returns (uint256) {
97
+ require(x >= 0);
98
+ return uint256(x);
99
+ }
100
+
101
+ function Int(uint256 x) internal pure returns (int256) {
102
+ require(x < (1 << 255)); // signed, lim = bit-1
103
+ return int256(x);
104
+ }
105
+
106
+ function Int128(int256 x) internal pure returns (int128) {
107
+ require(x < (1 << 127)); // signed, lim = bit-1
108
+ return int128(x);
109
+ }
110
+
111
+ function Uint32(uint256 x) internal pure returns (uint32) {
112
+ require(x < (1 << 32)); // unsigned, lim = bit
113
+ return uint32(x);
114
+ }
115
+
116
+ function Uint112(uint256 x) internal pure returns (uint112) {
117
+ require(x < (1 << 112)); // unsigned, lim = bit
118
+ return uint112(x);
119
+ }
120
+
121
+ function isAApproxB(
122
+ uint256 a,
123
+ uint256 b,
124
+ uint256 eps
125
+ ) internal pure returns (bool) {
126
+ return (isAGreaterApproxB(a, b, eps) || isASmallerApproxB(a, b, eps));
127
+ }
128
+
129
+ function isAGreaterApproxB(
130
+ uint256 a,
131
+ uint256 b,
132
+ uint256 eps
133
+ ) internal pure returns (bool) {
134
+ return a >= b && a <= mulDown(b, Math.ONE + eps);
135
+ }
136
+
137
+ function isASmallerApproxB(
138
+ uint256 a,
139
+ uint256 b,
140
+ uint256 eps
141
+ ) internal pure returns (bool) {
142
+ return a <= b && a >= mulDown(b, Math.ONE - eps);
143
+ }
144
+ }
@@ -22,8 +22,8 @@
22
22
  */
23
23
 
24
24
  pragma solidity 0.8.9;
25
- import "../../interfaces/IJoeRouter01.sol";
26
- import "../../libraries/JoeLibrary.sol";
25
+ import "../interfaces/IJoeRouter01.sol";
26
+ import "../libraries/JoeLibrary.sol";
27
27
  import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
28
28
  import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
29
29
 
@@ -2,9 +2,9 @@
2
2
  pragma solidity 0.8.9;
3
3
 
4
4
  import "../interfaces/IPGovernanceManager.sol";
5
- import "../interfaces/IPPermissionsV2.sol";
5
+ import "../interfaces/IPPermissionsV2Upg.sol";
6
6
 
7
- abstract contract PermissionsV2 is IPermissionsV2 {
7
+ abstract contract PermissionsV2Upg is IPermissionsV2Upg {
8
8
  address public immutable governanceManager;
9
9
 
10
10
  modifier onlyGovernance() {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@pendle/core-v2",
3
3
  "description": "Core smart contracts of Pendle Protocol.",
4
4
  "license": "BUSL-1.1",
5
- "version": "0.2.3",
5
+ "version": "0.4.0",
6
6
  "homepage": "https://pendle.finance",
7
7
  "keywords": [
8
8
  "pendle",
@@ -22,7 +22,7 @@ import type {
22
22
  OnEvent,
23
23
  } from "./common";
24
24
 
25
- export type MarketParametersStruct = {
25
+ export type MarketStateStruct = {
26
26
  totalOt: BigNumberish;
27
27
  totalScy: BigNumberish;
28
28
  totalLp: BigNumberish;
@@ -36,7 +36,7 @@ export type MarketParametersStruct = {
36
36
  lastTradeTime: BigNumberish;
37
37
  };
38
38
 
39
- export type MarketParametersStructOutput = [
39
+ export type MarketStateStructOutput = [
40
40
  BigNumber,
41
41
  BigNumber,
42
42
  BigNumber,
@@ -76,7 +76,7 @@ export interface IPMarketInterface extends utils.Interface {
76
76
  "expiry()": FunctionFragment;
77
77
  "isExpired()": FunctionFragment;
78
78
  "name()": FunctionFragment;
79
- "readState()": FunctionFragment;
79
+ "readState(bool)": FunctionFragment;
80
80
  "readTokens()": FunctionFragment;
81
81
  "removeLiquidity(address,uint256,bytes)": FunctionFragment;
82
82
  "swapExactOtForScy(address,uint256,uint256,bytes)": FunctionFragment;
@@ -107,7 +107,7 @@ export interface IPMarketInterface extends utils.Interface {
107
107
  encodeFunctionData(functionFragment: "expiry", values?: undefined): string;
108
108
  encodeFunctionData(functionFragment: "isExpired", values?: undefined): string;
109
109
  encodeFunctionData(functionFragment: "name", values?: undefined): string;
110
- encodeFunctionData(functionFragment: "readState", values?: undefined): string;
110
+ encodeFunctionData(functionFragment: "readState", values: [boolean]): string;
111
111
  encodeFunctionData(
112
112
  functionFragment: "readTokens",
113
113
  values?: undefined
@@ -265,10 +265,9 @@ export interface IPMarket extends BaseContract {
265
265
  name(overrides?: CallOverrides): Promise<[string]>;
266
266
 
267
267
  readState(
268
+ updateRateOracle: boolean,
268
269
  overrides?: CallOverrides
269
- ): Promise<
270
- [MarketParametersStructOutput] & { market: MarketParametersStructOutput }
271
- >;
270
+ ): Promise<[MarketStateStructOutput] & { market: MarketStateStructOutput }>;
272
271
 
273
272
  readTokens(
274
273
  overrides?: CallOverrides
@@ -353,7 +352,10 @@ export interface IPMarket extends BaseContract {
353
352
 
354
353
  name(overrides?: CallOverrides): Promise<string>;
355
354
 
356
- readState(overrides?: CallOverrides): Promise<MarketParametersStructOutput>;
355
+ readState(
356
+ updateRateOracle: boolean,
357
+ overrides?: CallOverrides
358
+ ): Promise<MarketStateStructOutput>;
357
359
 
358
360
  readTokens(
359
361
  overrides?: CallOverrides
@@ -444,7 +446,10 @@ export interface IPMarket extends BaseContract {
444
446
 
445
447
  name(overrides?: CallOverrides): Promise<string>;
446
448
 
447
- readState(overrides?: CallOverrides): Promise<MarketParametersStructOutput>;
449
+ readState(
450
+ updateRateOracle: boolean,
451
+ overrides?: CallOverrides
452
+ ): Promise<MarketStateStructOutput>;
448
453
 
449
454
  readTokens(
450
455
  overrides?: CallOverrides
@@ -569,7 +574,10 @@ export interface IPMarket extends BaseContract {
569
574
 
570
575
  name(overrides?: CallOverrides): Promise<BigNumber>;
571
576
 
572
- readState(overrides?: CallOverrides): Promise<BigNumber>;
577
+ readState(
578
+ updateRateOracle: boolean,
579
+ overrides?: CallOverrides
580
+ ): Promise<BigNumber>;
573
581
 
574
582
  readTokens(overrides?: CallOverrides): Promise<BigNumber>;
575
583
 
@@ -654,7 +662,10 @@ export interface IPMarket extends BaseContract {
654
662
 
655
663
  name(overrides?: CallOverrides): Promise<PopulatedTransaction>;
656
664
 
657
- readState(overrides?: CallOverrides): Promise<PopulatedTransaction>;
665
+ readState(
666
+ updateRateOracle: boolean,
667
+ overrides?: CallOverrides
668
+ ): Promise<PopulatedTransaction>;
658
669
 
659
670
  readTokens(overrides?: CallOverrides): Promise<PopulatedTransaction>;
660
671