@pendle/core-v2 4.5.2 → 4.7.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 (160) hide show
  1. package/build/artifacts/contracts/core/StandardizedYield/implementations/Ethena/PendleSUSDESY.sol/PendleSUSDESY.dbg.json +1 -1
  2. package/build/artifacts/contracts/core/StandardizedYield/implementations/Ethena/PendleSUSDESY.sol/PendleSUSDESY.json +2 -2
  3. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultERC20SY.sol/PendleKarakVaultERC20SY.dbg.json +4 -0
  4. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultERC20SY.sol/PendleKarakVaultERC20SY.json +1070 -0
  5. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultEzETHSY.sol/PendleKarakVaultEzETHSY.dbg.json +4 -0
  6. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultEzETHSY.sol/PendleKarakVaultEzETHSY.json +1144 -0
  7. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultSUSDESY.sol/PendleKarakVaultSUSDESY.dbg.json +4 -0
  8. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultSUSDESY.sol/PendleKarakVaultSUSDESY.json +1111 -0
  9. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultSYBaseUpg.sol/PendleKarakVaultSYBaseUpg.dbg.json +4 -0
  10. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultSYBaseUpg.sol/PendleKarakVaultSYBaseUpg.json +1036 -0
  11. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultUSDESY.sol/PendleKarakVaultUSDESY.dbg.json +4 -0
  12. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultUSDESY.sol/PendleKarakVaultUSDESY.json +1096 -0
  13. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultWEETHSY.sol/PendleKarakVaultWEETHSY.dbg.json +4 -0
  14. package/build/artifacts/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultWEETHSY.sol/PendleKarakVaultWEETHSY.json +1116 -0
  15. package/build/artifacts/contracts/core/StandardizedYield/implementations/PendleERC4626SY.sol/PendleERC4626SY.dbg.json +1 -1
  16. package/build/artifacts/contracts/core/StandardizedYield/implementations/PendleERC4626SY.sol/PendleERC4626SY.json +2 -2
  17. package/build/artifacts/contracts/core/StandardizedYield/implementations/PendleERC4626UpgSY.sol/PendleERC4626SYUpg.dbg.json +1 -1
  18. package/build/artifacts/contracts/core/StandardizedYield/implementations/PendleERC4626UpgSY.sol/PendleERC4626SYUpg.json +2 -2
  19. package/build/artifacts/contracts/core/StandardizedYield/implementations/PendleGdaiSY.sol/PendleGDaiSY.dbg.json +1 -1
  20. package/build/artifacts/contracts/core/StandardizedYield/implementations/PendleGdaiSY.sol/PendleGDaiSY.json +2 -2
  21. package/build/artifacts/contracts/core/StandardizedYield/implementations/PendleSfrxEthSY.sol/PendleSfrxEthSY.dbg.json +1 -1
  22. package/build/artifacts/contracts/core/StandardizedYield/implementations/PendleSfrxEthSY.sol/PendleSfrxEthSY.json +2 -2
  23. package/build/artifacts/contracts/core/StandardizedYield/implementations/PirexETH/PendleApxETHSY.sol/PendleApxETHSY.dbg.json +1 -1
  24. package/build/artifacts/contracts/core/StandardizedYield/implementations/PirexETH/PendleApxETHSY.sol/PendleApxETHSY.json +2 -2
  25. package/build/artifacts/contracts/core/StandardizedYield/implementations/Puffer/PendlePufStETHSY.sol/PendlePufStETHSY.dbg.json +1 -1
  26. package/build/artifacts/contracts/core/StandardizedYield/implementations/Puffer/PendlePufStETHSY.sol/PendlePufStETHSY.json +2 -2
  27. package/build/artifacts/contracts/core/StandardizedYield/implementations/Puffer/PendlePufWETHSY.sol/PendlePufWETHSY.dbg.json +1 -1
  28. package/build/artifacts/contracts/core/StandardizedYield/implementations/Puffer/PendlePufWETHSY.sol/PendlePufWETHSY.json +2 -2
  29. package/build/artifacts/contracts/interfaces/IERC4626.sol/IERC4626.dbg.json +1 -1
  30. package/build/artifacts/contracts/interfaces/IERC4626.sol/IERC4626.json +19 -0
  31. package/build/artifacts/contracts/interfaces/IPActionMiscV3.sol/IPActionMiscV3.dbg.json +1 -1
  32. package/build/artifacts/contracts/interfaces/IPActionMiscV3.sol/IPActionMiscV3.json +1200 -34
  33. package/build/artifacts/contracts/interfaces/IPAllActionV3.sol/IPAllActionV3.dbg.json +1 -1
  34. package/build/artifacts/contracts/interfaces/IPAllActionV3.sol/IPAllActionV3.json +1228 -62
  35. package/build/artifacts/contracts/interfaces/IPPYLpOracle.sol/IPPYLpOracle.dbg.json +4 -0
  36. package/build/artifacts/contracts/interfaces/{IPPtLpOracle.sol/IPPtLpOracle.json → IPPYLpOracle.sol/IPPYLpOracle.json} +50 -2
  37. package/build/artifacts/contracts/interfaces/IPReflector.sol/IPReflector.dbg.json +4 -0
  38. package/build/artifacts/contracts/interfaces/IPReflector.sol/IPReflector.json +30 -0
  39. package/build/artifacts/contracts/interfaces/IPTokenWithSupplyCap.sol/IPTokenWithSupplyCap.dbg.json +4 -0
  40. package/build/artifacts/contracts/interfaces/IPTokenWithSupplyCap.sol/IPTokenWithSupplyCap.json +37 -0
  41. package/build/artifacts/contracts/interfaces/Karak/IKarakVault.sol/IKarakVault.dbg.json +4 -0
  42. package/build/artifacts/contracts/interfaces/Karak/IKarakVault.sol/IKarakVault.json +24 -0
  43. package/build/artifacts/contracts/interfaces/Karak/IKarakVaultSupervisor.sol/IKarakVaultSupervisor.dbg.json +4 -0
  44. package/build/artifacts/contracts/interfaces/Karak/IKarakVaultSupervisor.sol/IKarakVaultSupervisor.json +76 -0
  45. package/build/artifacts/contracts/offchain-helpers/PendlePoolDeployHelper.sol/PendlePoolDeployHelper.dbg.json +1 -1
  46. package/build/artifacts/contracts/offchain-helpers/PendlePoolDeployHelper.sol/PendlePoolDeployHelper.json +25 -2
  47. package/build/artifacts/contracts/offchain-helpers/SupplyCapReader.sol/IPossibleSupplyCapInterface.dbg.json +1 -1
  48. package/build/artifacts/contracts/offchain-helpers/SupplyCapReader.sol/SupplyCapReader.dbg.json +1 -1
  49. package/build/artifacts/contracts/oracles/PendleLpOracleLib.sol/PendleLpOracleLib.dbg.json +1 -1
  50. package/build/artifacts/contracts/oracles/PendleLpOracleLib.sol/PendleLpOracleLib.json +2 -2
  51. package/build/artifacts/contracts/oracles/PendlePYLpOracle.sol/PendlePYLpOracle.dbg.json +4 -0
  52. package/build/artifacts/contracts/oracles/PendlePYLpOracle.sol/PendlePYLpOracle.json +422 -0
  53. package/build/artifacts/contracts/oracles/PendlePYOracleLib.sol/PendlePYOracleLib.dbg.json +4 -0
  54. package/build/artifacts/contracts/oracles/{PendlePtOracleLib.sol/PendlePtOracleLib.json → PendlePYOracleLib.sol/PendlePYOracleLib.json} +4 -4
  55. package/build/artifacts/contracts/oracles/samples/BoringLpGlpOracle.sol/BoringLpGlpOracle.dbg.json +1 -1
  56. package/build/artifacts/contracts/oracles/samples/BoringLpGlpOracle.sol/BoringLpGlpOracle.json +2 -2
  57. package/build/artifacts/contracts/oracles/samples/BoringPYUsdChainlinkAssetOracle.sol/BoringPYUsdChainlinkAssetOracle.dbg.json +4 -0
  58. package/build/artifacts/contracts/oracles/samples/BoringPYUsdChainlinkAssetOracle.sol/BoringPYUsdChainlinkAssetOracle.json +183 -0
  59. package/build/artifacts/contracts/oracles/samples/BoringPYUsdChainlinkSYOracle.sol/BoringPYUsdChainlinkSYOracle.dbg.json +4 -0
  60. package/build/artifacts/contracts/oracles/samples/BoringPYUsdChainlinkSYOracle.sol/BoringPYUsdChainlinkSYOracle.json +183 -0
  61. package/build/artifacts/contracts/router/ActionAddRemoveLiqV3.sol/ActionAddRemoveLiqV3.dbg.json +1 -1
  62. package/build/artifacts/contracts/router/ActionAddRemoveLiqV3.sol/ActionAddRemoveLiqV3.json +2 -2
  63. package/build/artifacts/contracts/router/ActionMiscV3.sol/ActionMiscV3.dbg.json +1 -1
  64. package/build/artifacts/contracts/router/ActionMiscV3.sol/ActionMiscV3.json +1202 -36
  65. package/build/artifacts/contracts/router/ActionSwapPTV3.sol/ActionSwapPTV3.dbg.json +1 -1
  66. package/build/artifacts/contracts/router/ActionSwapPTV3.sol/ActionSwapPTV3.json +2 -2
  67. package/build/artifacts/contracts/router/ActionSwapYTV3.sol/ActionSwapYTV3.dbg.json +1 -1
  68. package/build/artifacts/contracts/router/ActionSwapYTV3.sol/ActionSwapYTV3.json +2 -2
  69. package/build/artifacts/contracts/router/Reflector.sol/Reflector.dbg.json +4 -0
  70. package/build/artifacts/contracts/router/Reflector.sol/Reflector.json +34 -0
  71. package/build/artifacts/contracts/router/base/ActionBase.sol/ActionBase.dbg.json +1 -1
  72. package/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultERC20SY.sol +32 -0
  73. package/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultEzETHSY.sol +80 -0
  74. package/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultSUSDESY.sol +73 -0
  75. package/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultSYBaseUpg.sol +141 -0
  76. package/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultUSDESY.sol +18 -0
  77. package/contracts/core/StandardizedYield/implementations/Karak/PendleKarakVaultWEETHSY.sol +71 -0
  78. package/contracts/interfaces/IERC4626.sol +2 -0
  79. package/contracts/interfaces/IPActionMiscV3.sol +99 -0
  80. package/contracts/interfaces/{IPPtLpOracle.sol → IPPYLpOracle.sol} +5 -1
  81. package/contracts/interfaces/IPReflector.sol +6 -0
  82. package/contracts/interfaces/IPTokenWithSupplyCap.sol +9 -0
  83. package/contracts/interfaces/Karak/IKarakVault.sol +6 -0
  84. package/contracts/interfaces/Karak/IKarakVaultSupervisor.sol +8 -0
  85. package/contracts/offchain-helpers/PendlePoolDeployHelper.sol +5 -0
  86. package/contracts/oracles/PendleLpOracleLib.sol +4 -4
  87. package/contracts/oracles/{PendlePtLpOracle.sol → PendlePYLpOracle.sol} +51 -21
  88. package/contracts/oracles/{PendlePtOracleLib.sol → PendlePYOracleLib.sol} +31 -1
  89. package/contracts/oracles/samples/BoringLpGlpOracle.sol +2 -2
  90. package/contracts/oracles/samples/{BoringPtUsdChainlinkOracle.sol → BoringPYUsdChainlinkAssetOracle.sol} +36 -12
  91. package/contracts/oracles/samples/BoringPYUsdChainlinkSYOracle.sol +102 -0
  92. package/contracts/router/ActionMiscV3.sol +182 -34
  93. package/contracts/router/ActionSwapYTV3.sol +0 -85
  94. package/contracts/router/Reflector.sol +70 -0
  95. package/contracts/router/base/ActionBase.sol +90 -1
  96. package/deployments/1-core.json +11 -2
  97. package/deployments/1-markets/KARAK-SUSDE-MAINNET-SEP2024.json +14 -0
  98. package/deployments/1-markets/KARAK-USDE-MAINNET-SEP2024.json +14 -0
  99. package/deployments/1-markets/KARAK-WEETH-MAINNET-SEP2024.json +14 -0
  100. package/deployments/10-core.json +11 -2
  101. package/deployments/42161-core.json +11 -2
  102. package/deployments/42161-markets/CAMELOT-PEP-ARBITRUM-JUNE2025.json +14 -0
  103. package/deployments/42161-markets/RSETH-ARBITRUM-SEP2024-NEW.json +11 -0
  104. package/deployments/5000-core.json +11 -2
  105. package/deployments/56-core.json +11 -2
  106. package/package.json +1 -1
  107. package/typechain-types/ActionMiscV3.ts +628 -16
  108. package/typechain-types/IERC4626.ts +34 -0
  109. package/typechain-types/IKarakVault.ts +84 -0
  110. package/typechain-types/IKarakVaultSupervisor.ts +190 -0
  111. package/typechain-types/IPActionMiscV3.ts +628 -16
  112. package/typechain-types/IPAllActionV3.ts +535 -0
  113. package/typechain-types/IPReflector.ts +95 -0
  114. package/typechain-types/IPTokenWithSupplyCap.ts +110 -0
  115. package/typechain-types/PendleKarakVaultERC20SY.ts +1324 -0
  116. package/typechain-types/PendleKarakVaultEzETHSY.ts +1400 -0
  117. package/typechain-types/PendleKarakVaultSUSDESY.ts +1380 -0
  118. package/typechain-types/PendleKarakVaultSYBaseUpg.ts +1312 -0
  119. package/typechain-types/PendleKarakVaultUSDESY.ts +1366 -0
  120. package/typechain-types/PendleKarakVaultWEETHSY.ts +1370 -0
  121. package/typechain-types/PendlePYLpOracle.ts +10 -3
  122. package/typechain-types/PendlePoolDeployHelper.ts +44 -0
  123. package/typechain-types/Reflector.ts +95 -0
  124. package/typechain-types/factories/ActionAddRemoveLiqV3__factory.ts +1 -1
  125. package/typechain-types/factories/ActionMiscV3__factory.ts +1201 -35
  126. package/typechain-types/factories/ActionSwapPTV3__factory.ts +1 -1
  127. package/typechain-types/factories/ActionSwapYTV3__factory.ts +1 -1
  128. package/typechain-types/factories/BoringLpGlpOracle__factory.ts +1 -1
  129. package/typechain-types/factories/IERC4626__factory.ts +19 -0
  130. package/typechain-types/factories/IKarakVaultSupervisor__factory.ts +95 -0
  131. package/typechain-types/factories/IKarakVault__factory.ts +36 -0
  132. package/typechain-types/factories/IPActionMiscV3__factory.ts +1200 -34
  133. package/typechain-types/factories/IPAllActionV3__factory.ts +1228 -62
  134. package/typechain-types/factories/IPReflector__factory.ts +42 -0
  135. package/typechain-types/factories/IPTokenWithSupplyCap__factory.ts +56 -0
  136. package/typechain-types/factories/PendleApxETHSY__factory.ts +1 -1
  137. package/typechain-types/factories/PendleERC4626SYUpg__factory.ts +1 -1
  138. package/typechain-types/factories/PendleERC4626SY__factory.ts +1 -1
  139. package/typechain-types/factories/PendleGDaiSY__factory.ts +1 -1
  140. package/typechain-types/factories/PendleKarakVaultERC20SY__factory.ts +1139 -0
  141. package/typechain-types/factories/PendleKarakVaultEzETHSY__factory.ts +1236 -0
  142. package/typechain-types/factories/PendleKarakVaultSUSDESY__factory.ts +1180 -0
  143. package/typechain-types/factories/PendleKarakVaultSYBaseUpg__factory.ts +1055 -0
  144. package/typechain-types/factories/PendleKarakVaultUSDESY__factory.ts +1165 -0
  145. package/typechain-types/factories/PendleKarakVaultWEETHSY__factory.ts +1189 -0
  146. package/typechain-types/factories/PendlePYLpOracle__factory.ts +12 -24
  147. package/typechain-types/factories/PendlePoolDeployHelper__factory.ts +24 -1
  148. package/typechain-types/factories/PendlePufStETHSY__factory.ts +1 -1
  149. package/typechain-types/factories/PendlePufWETHSY__factory.ts +1 -1
  150. package/typechain-types/factories/PendleSUSDESY__factory.ts +1 -1
  151. package/typechain-types/factories/PendleSfrxEthSY__factory.ts +1 -1
  152. package/typechain-types/factories/Reflector__factory.ts +84 -0
  153. package/typechain-types/hardhat.d.ts +99 -0
  154. package/typechain-types/index.ts +22 -0
  155. package/build/artifacts/contracts/interfaces/IPPtLpOracle.sol/IPPtLpOracle.dbg.json +0 -4
  156. package/build/artifacts/contracts/oracles/PendlePtLpOracle.sol/PendlePtLpOracle.dbg.json +0 -4
  157. package/build/artifacts/contracts/oracles/PendlePtLpOracle.sol/PendlePtLpOracle.json +0 -367
  158. package/build/artifacts/contracts/oracles/PendlePtOracleLib.sol/PendlePtOracleLib.dbg.json +0 -4
  159. package/build/artifacts/contracts/oracles/samples/BoringPtUsdChainlinkOracle.sol/BoringPtUsdChainlinkOracle.dbg.json +0 -4
  160. package/build/artifacts/contracts/oracles/samples/BoringPtUsdChainlinkOracle.sol/BoringPtUsdChainlinkOracle.json +0 -157
@@ -6,7 +6,7 @@ import "../core/libraries/math/PMath.sol";
6
6
 
7
7
  // This library can & should be integrated directly for optimal gas usage.
8
8
  // If you prefer not to integrate it directly, the PendlePtOracle contract (a pre-deployed version of this contract) can be used.
9
- library PendlePtOracleLib {
9
+ library PendlePYOracleLib {
10
10
  using PMath for uint256;
11
11
  using PMath for int256;
12
12
 
@@ -25,6 +25,21 @@ library PendlePtOracleLib {
25
25
  }
26
26
  }
27
27
 
28
+ /**
29
+ * This function returns the twap rate YT/Asset on market, but take into account the current rate of SY
30
+ This is to account for special cases where underlying asset becomes insolvent and has decreasing exchangeRate
31
+ * @param market market to get rate from
32
+ * @param duration twap duration
33
+ */
34
+ function getYtToAssetRate(IPMarket market, uint32 duration) internal view returns (uint256) {
35
+ (uint256 syIndex, uint256 pyIndex) = getSYandPYIndexCurrent(market);
36
+ if (syIndex >= pyIndex) {
37
+ return getYtToAssetRateRaw(market, duration);
38
+ } else {
39
+ return (getYtToAssetRateRaw(market, duration) * syIndex) / pyIndex;
40
+ }
41
+ }
42
+
28
43
  /// @notice Similar to getPtToAsset but returns the rate in SY instead
29
44
  function getPtToSyRate(IPMarket market, uint32 duration) internal view returns (uint256) {
30
45
  (uint256 syIndex, uint256 pyIndex) = getSYandPYIndexCurrent(market);
@@ -35,6 +50,16 @@ library PendlePtOracleLib {
35
50
  }
36
51
  }
37
52
 
53
+ /// @notice Similar to getPtToAsset but returns the rate in SY instead
54
+ function getYtToSyRate(IPMarket market, uint32 duration) internal view returns (uint256) {
55
+ (uint256 syIndex, uint256 pyIndex) = getSYandPYIndexCurrent(market);
56
+ if (syIndex >= pyIndex) {
57
+ return getYtToAssetRateRaw(market, duration).divDown(syIndex);
58
+ } else {
59
+ return getYtToAssetRateRaw(market, duration).divDown(pyIndex);
60
+ }
61
+ }
62
+
38
63
  /// @notice returns the raw rate without taking into account whether SY is solvent
39
64
  function getPtToAssetRateRaw(IPMarket market, uint32 duration) internal view returns (uint256) {
40
65
  uint256 expiry = market.expiry();
@@ -49,6 +74,11 @@ library PendlePtOracleLib {
49
74
  }
50
75
  }
51
76
 
77
+ /// @notice returns the raw rate without taking into account whether SY is solvent
78
+ function getYtToAssetRateRaw(IPMarket market, uint32 duration) internal view returns (uint256) {
79
+ return PMath.ONE - getPtToAssetRateRaw(market, duration);
80
+ }
81
+
52
82
  function getSYandPYIndexCurrent(IPMarket market) internal view returns (uint256 syIndex, uint256 pyIndex) {
53
83
  (IStandardizedYield SY, , IPYieldToken YT) = market.readTokens();
54
84
 
@@ -2,7 +2,7 @@
2
2
  pragma solidity ^0.8.17;
3
3
 
4
4
  import "../PendleLpOracleLib.sol";
5
- import "../../interfaces/IPPtLpOracle.sol";
5
+ import "../../interfaces/IPPYLpOracle.sol";
6
6
  import "../../interfaces/GMX/IGlpManager.sol";
7
7
  import "../../core/libraries/math/PMath.sol";
8
8
 
@@ -23,7 +23,7 @@ contract BoringLpGlpOracle {
23
23
  market = _market;
24
24
  glpManager = _glpManager;
25
25
 
26
- (bool increaseCardinalityRequired, , bool oldestObservationSatisfied) = IPPtLpOracle(_ptOracle).getOracleState(
26
+ (bool increaseCardinalityRequired, , bool oldestObservationSatisfied) = IPPYLpOracle(_ptOracle).getOracleState(
27
27
  market,
28
28
  twapDuration
29
29
  );
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-or-later
2
2
  pragma solidity ^0.8.17;
3
3
 
4
- import "../../interfaces/IPPtLpOracle.sol";
4
+ import "../../interfaces/IPPYLpOracle.sol";
5
5
  import "../../interfaces/IPMarket.sol";
6
6
  import "../../core/libraries/math/PMath.sol";
7
7
  import "../PendleLpOracleLib.sol";
@@ -9,29 +9,41 @@ import "../PendleLpOracleLib.sol";
9
9
  import {AggregatorV2V3Interface as IChainlinkAggregator} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol";
10
10
 
11
11
  /**
12
- * @notice The returned price from this contract is multiplied by the default USD price of the asset, as read from Chainlink Oracles.
13
- * For more details into how the oracle is implemented, refer to PendlePtOracle & PendlePtOracleLib.
12
+ * @notice The returned price from this contract is multiplied by the default USD price of the
13
+ * underlying asset, as read from a Chainlink-interface oracle.
14
+ *
15
+ * Example of this usage:
16
+ * - PT-wstETH = ptToAssetRate * stETH price
17
+ * - PT-silo-crvUSD = ptToAssetRate * crvUSD price
18
+ *
19
+ * For more details into how the oracle is implemented, refer to PendlePYLpOracle & PendlePYOracleLib.
14
20
  */
15
- contract BoringPtUsdChainlinkOracle {
16
- using PendlePtOracleLib for IPMarket;
21
+ contract BoringPYUsdChainlinkAssetOracle {
22
+ using PendlePYOracleLib for IPMarket;
17
23
 
18
24
  uint32 public immutable twapDuration;
19
25
  address public immutable market;
20
26
  address public immutable feed;
21
27
  uint8 public immutable feedDecimals;
22
- address public immutable ptOracle;
28
+ address public immutable pyLpOracle;
23
29
 
24
- constructor(uint32 _twapDuration, address _market, address _feed, address _ptOracle) {
30
+ constructor(uint32 _twapDuration, address _market, address _feed, address _pyLpOracle) {
25
31
  twapDuration = _twapDuration;
26
32
  market = _market;
27
33
  feed = _feed;
28
34
  feedDecimals = IChainlinkAggregator(feed).decimals();
29
35
 
30
36
  // required only for sample2
31
- ptOracle = _ptOracle;
37
+ pyLpOracle = _pyLpOracle;
38
+
39
+ /**
40
+ * @notice All pricing functions in this contract should only be used after checkOracleState() is ran successfully without reverting.
41
+ * This equals to calling checkOracleState() in your oracle constructor.
42
+ */
43
+ // checkOracleState();
32
44
  }
33
45
 
34
- /// @notice direct integration with PendlePtOracleLib, which optimizes gas efficiency.
46
+ /// @notice direct integration with PendlePYOracleLib, which optimizes gas efficiency.
35
47
  /// @notice please checkOracleState() before use
36
48
  function getPtPriceSample1() external view virtual returns (uint256) {
37
49
  uint256 ptRate = IPMarket(market).getPtToAssetRate(twapDuration);
@@ -43,11 +55,23 @@ contract BoringPtUsdChainlinkOracle {
43
55
  /// but slightly higher gas usage (~ 4000 gas, 2 external calls & 1 cold code load)
44
56
  /// @notice please checkOracleState() before use
45
57
  function getPtPriceSample2() external view virtual returns (uint256) {
46
- uint256 ptRate = IPPtLpOracle(ptOracle).getPtToAssetRate(market, twapDuration);
58
+ uint256 ptRate = IPPYLpOracle(pyLpOracle).getPtToAssetRate(market, twapDuration);
47
59
  uint256 assetPrice = _getUnderlyingAssetPrice();
48
60
  return (assetPrice * ptRate) / PMath.ONE;
49
61
  }
50
62
 
63
+ function getYtPriceSample1() external view virtual returns (uint256) {
64
+ uint256 ytRate = IPMarket(market).getYtToAssetRate(twapDuration);
65
+ uint256 assetPrice = _getUnderlyingAssetPrice();
66
+ return (assetPrice * ytRate) / PMath.ONE;
67
+ }
68
+
69
+ function getYtPriceSample2() external view virtual returns (uint256) {
70
+ uint256 ytRate = IPPYLpOracle(pyLpOracle).getYtToAssetRate(market, twapDuration);
71
+ uint256 assetPrice = _getUnderlyingAssetPrice();
72
+ return (assetPrice * ytRate) / PMath.ONE;
73
+ }
74
+
51
75
  function _getUnderlyingAssetPrice() internal view virtual returns (uint256) {
52
76
  uint256 rawPrice = uint256(IChainlinkAggregator(feed).latestAnswer());
53
77
  return feedDecimals < 18 ? rawPrice * 10 ** (18 - feedDecimals) : rawPrice / 10 ** (feedDecimals - 18);
@@ -60,8 +84,8 @@ contract BoringPtUsdChainlinkOracle {
60
84
 
61
85
  /// @notice Call only once for each (market, duration). Once successful, it's permanently valid (also for any shorter duration).
62
86
  function checkOracleState() external view {
63
- (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied) = IPPtLpOracle(
64
- ptOracle
87
+ (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied) = IPPYLpOracle(
88
+ pyLpOracle
65
89
  ).getOracleState(market, twapDuration);
66
90
 
67
91
  if (increaseCardinalityRequired) {
@@ -0,0 +1,102 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ pragma solidity ^0.8.17;
3
+
4
+ import "../../interfaces/IPPYLpOracle.sol";
5
+ import "../../interfaces/IPMarket.sol";
6
+ import "../../core/libraries/math/PMath.sol";
7
+ import "../PendleLpOracleLib.sol";
8
+
9
+ import {AggregatorV2V3Interface as IChainlinkAggregator} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol";
10
+
11
+ /**
12
+ * @notice The returned price from this contract is multiplied by the default USD price of the
13
+ * SY-equivalent token, as read from a Chainlink-interface oracle.
14
+ *
15
+ * Example of this usage:
16
+ * - PT-weETH = ptToSyRate * weETH price
17
+ * - PT-ezETH = ptToSyRate * ezETH price
18
+ *
19
+ * For more details into how the oracle is implemented, refer to PendlePYLpOracle & PendlePYOracleLib.
20
+ */
21
+ contract BoringPYUsdChainlinkSYOracle {
22
+ using PendlePYOracleLib for IPMarket;
23
+
24
+ uint32 public immutable twapDuration;
25
+ address public immutable market;
26
+ address public immutable feed;
27
+ uint8 public immutable feedDecimals;
28
+ address public immutable pyLpOracle;
29
+
30
+ constructor(uint32 _twapDuration, address _market, address _feed, address _pyLpOracle) {
31
+ twapDuration = _twapDuration;
32
+ market = _market;
33
+ feed = _feed;
34
+ feedDecimals = IChainlinkAggregator(feed).decimals();
35
+
36
+ // required only for sample2
37
+ pyLpOracle = _pyLpOracle;
38
+
39
+ /**
40
+ * @notice All pricing functions in this contract should only be used after checkOracleState() is ran successfully without reverting.
41
+ * This equals to calling checkOracleState() in your oracle constructor.
42
+ */
43
+ // checkOracleState();
44
+ }
45
+
46
+ /// @notice direct integration with PendlePYOracleLib, which optimizes gas efficiency.
47
+ /// @notice please checkOracleState() before use
48
+ function getPtPriceSample1() external view virtual returns (uint256) {
49
+ uint256 ptRate = IPMarket(market).getPtToSyRate(twapDuration);
50
+ uint256 syEquivalentTokenPrice = _getSYEquivalentTokenPrice();
51
+ return (syEquivalentTokenPrice * ptRate) / PMath.ONE;
52
+ }
53
+
54
+ /// @notice integration with the PendlePtOracle contract, resulting in a smaller bytecode size and simpler structure
55
+ /// but slightly higher gas usage (~ 4000 gas, 2 external calls & 1 cold code load)
56
+ /// @notice please checkOracleState() before use
57
+ function getPtPriceSample2() external view virtual returns (uint256) {
58
+ uint256 ptRate = IPPYLpOracle(pyLpOracle).getPtToSyRate(market, twapDuration);
59
+ uint256 syEquivalentTokenPrice = _getSYEquivalentTokenPrice();
60
+ return (syEquivalentTokenPrice * ptRate) / PMath.ONE;
61
+ }
62
+
63
+ function getYtPriceSample1() external view virtual returns (uint256) {
64
+ uint256 ytRate = IPMarket(market).getYtToSyRate(twapDuration);
65
+ uint256 syEquivalentTokenPrice = _getSYEquivalentTokenPrice();
66
+ return (syEquivalentTokenPrice * ytRate) / PMath.ONE;
67
+ }
68
+
69
+ function getYtPriceSample2() external view virtual returns (uint256) {
70
+ uint256 ytRate = IPPYLpOracle(pyLpOracle).getYtToSyRate(market, twapDuration);
71
+ uint256 syEquivalentTokenPrice = _getSYEquivalentTokenPrice();
72
+ return (syEquivalentTokenPrice * ytRate) / PMath.ONE;
73
+ }
74
+
75
+ function _getSYEquivalentTokenPrice() internal view virtual returns (uint256) {
76
+ uint256 rawPrice = uint256(IChainlinkAggregator(feed).latestAnswer());
77
+ return feedDecimals < 18 ? rawPrice * 10 ** (18 - feedDecimals) : rawPrice / 10 ** (feedDecimals - 18);
78
+ }
79
+
80
+ // ------------------ NOT TO INCLUDE IN PRODUCTION CODE ------------------
81
+
82
+ error IncreaseCardinalityRequired(uint16 cardinalityRequired);
83
+ error AdditionalWaitRequired(uint32 duration);
84
+
85
+ /// @notice Call only once for each (market, duration). Once successful, it's permanently valid (also for any shorter duration).
86
+ function checkOracleState() external view {
87
+ (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied) = IPPYLpOracle(
88
+ pyLpOracle
89
+ ).getOracleState(market, twapDuration);
90
+
91
+ if (increaseCardinalityRequired) {
92
+ // It's required to call IPMarket(market).increaseObservationsCardinalityNext(cardinalityRequired) and wait for
93
+ // at least the twapDuration, to allow data population.
94
+ revert IncreaseCardinalityRequired(cardinalityRequired);
95
+ }
96
+
97
+ if (!oldestObservationSatisfied) {
98
+ // It's necessary to wait for at least the twapDuration, to allow data population.
99
+ revert AdditionalWaitRequired(twapDuration);
100
+ }
101
+ }
102
+ }
@@ -3,6 +3,7 @@ pragma solidity ^0.8.17;
3
3
 
4
4
  import "./base/ActionBase.sol";
5
5
  import "../interfaces/IPActionMiscV3.sol";
6
+ import "../interfaces/IPReflector.sol";
6
7
 
7
8
  contract ActionMiscV3 is IPActionMiscV3, ActionBase {
8
9
  function mintSyFromToken(
@@ -79,18 +80,16 @@ contract ActionMiscV3 is IPActionMiscV3, ActionBase {
79
80
  address[] calldata yts,
80
81
  address[] calldata markets
81
82
  ) external {
82
- unchecked {
83
- for (uint256 i = 0; i < sys.length; ++i) {
84
- IStandardizedYield(sys[i]).claimRewards(user);
85
- }
83
+ for (uint256 i = 0; i < sys.length; ++i) {
84
+ IStandardizedYield(sys[i]).claimRewards(user);
85
+ }
86
86
 
87
- for (uint256 i = 0; i < yts.length; ++i) {
88
- IPYieldToken(yts[i]).redeemDueInterestAndRewards(user, true, true);
89
- }
87
+ for (uint256 i = 0; i < yts.length; ++i) {
88
+ IPYieldToken(yts[i]).redeemDueInterestAndRewards(user, true, true);
89
+ }
90
90
 
91
- for (uint256 i = 0; i < markets.length; ++i) {
92
- IPMarket(markets[i]).redeemRewards(user);
93
- }
91
+ for (uint256 i = 0; i < markets.length; ++i) {
92
+ IPMarket(markets[i]).redeemRewards(user);
94
93
  }
95
94
  }
96
95
 
@@ -118,45 +117,194 @@ contract ActionMiscV3 is IPActionMiscV3, ActionBase {
118
117
  netTokenOut = IStandardizedYield(SY).redeem(receiver, netSyInterm, tokenRedeemSy, minTokenOut, true);
119
118
  }
120
119
 
120
+ /// @dev The interface might change in the future, check with Pendle team before use
121
+ function exitPreExpToToken(
122
+ address receiver,
123
+ address market,
124
+ uint256 netPtIn,
125
+ uint256 netYtIn,
126
+ uint256 netLpIn,
127
+ TokenOutput calldata output,
128
+ LimitOrderData calldata limit
129
+ ) external returns (uint256 totalTokenOut, ExitPreExpReturnParams memory params) {
130
+ IStandardizedYield SY;
131
+
132
+ (SY, params) = _exitPreExpToSy(true, address(0), market, netPtIn, netYtIn, netLpIn, limit);
133
+ totalTokenOut = _redeemSyToToken(receiver, address(SY), params.totalSyOut, output, false);
134
+
135
+ emit ExitPreExpToToken(msg.sender, market, output.tokenOut, receiver, netLpIn, totalTokenOut, params);
136
+ }
137
+
138
+ /// @dev The interface might change in the future, check with Pendle team before use
139
+ function exitPreExpToSy(
140
+ address receiver,
141
+ address market,
142
+ uint256 netPtIn,
143
+ uint256 netYtIn,
144
+ uint256 netLpIn,
145
+ uint256 minSyOut,
146
+ LimitOrderData calldata limit
147
+ ) external returns (ExitPreExpReturnParams memory params) {
148
+ (, params) = _exitPreExpToSy(false, receiver, market, netPtIn, netYtIn, netLpIn, limit);
149
+ require(params.totalSyOut >= minSyOut, "Slippage: INSUFFICIENT_SY_OUT");
150
+
151
+ emit ExitPreExpToSy(msg.sender, market, receiver, netLpIn, params);
152
+ }
153
+
154
+ function _exitPreExpToSy(
155
+ bool setReceiverToSy,
156
+ address receiver,
157
+ address market,
158
+ uint256 netPtIn,
159
+ uint256 netYtIn,
160
+ uint256 netLpIn,
161
+ LimitOrderData calldata limit
162
+ ) internal returns (IStandardizedYield SY, ExitPreExpReturnParams memory p) {
163
+ IPPrincipalToken PT;
164
+ IPYieldToken YT;
165
+ (SY, PT, YT) = IPMarket(market).readTokens();
166
+
167
+ if (setReceiverToSy) receiver = address(SY);
168
+
169
+ if (netLpIn > 0) {
170
+ _transferFrom(IERC20(market), msg.sender, market, netLpIn);
171
+ (p.netSyFromRemove, p.netPtFromRemove) = IPMarket(market).burn(receiver, address(this), netLpIn);
172
+ }
173
+
174
+ if (netPtIn > 0) {
175
+ _transferIn(address(PT), msg.sender, netPtIn);
176
+ }
177
+
178
+ p.netPyRedeem = PMath.min(p.netPtFromRemove + netPtIn, netYtIn);
179
+
180
+ if (p.netPyRedeem > 0) {
181
+ _transferOut(address(PT), address(YT), p.netPyRedeem);
182
+ _transferFrom(YT, msg.sender, address(YT), p.netPyRedeem);
183
+ p.netSyFromRedeem = IPYieldToken(YT).redeemPY(receiver);
184
+ }
185
+
186
+ p.netPtSwap = p.netPtFromRemove + netPtIn - p.netPyRedeem;
187
+ p.netYtSwap = netYtIn - p.netPyRedeem;
188
+
189
+ if (p.netPtSwap > 0) {
190
+ address ptEntry = _entry_swapExactPtForSy(market, limit);
191
+ if (ptEntry != address(this)) _transferOut(address(PT), ptEntry, p.netPtSwap);
192
+ (p.netSyFromSwap, p.netSyFee) = _swapExactPtForSy(receiver, market, p.netPtSwap, 0, limit);
193
+ } else if (p.netYtSwap > 0) {
194
+ _transferFrom(YT, msg.sender, _entry_swapExactYtForSy(YT, limit), p.netYtSwap);
195
+ (p.netSyFromSwap, p.netSyFee) = _swapExactYtForSy(receiver, market, SY, YT, p.netYtSwap, 0, limit);
196
+ }
197
+
198
+ p.totalSyOut = p.netSyFromRemove + p.netSyFromRedeem + p.netSyFromSwap;
199
+ }
200
+
201
+ /// @dev The interface might change in the future, check with Pendle team before use
202
+ function exitPostExpToToken(
203
+ address receiver,
204
+ address market,
205
+ uint256 netPtIn,
206
+ uint256 netLpIn,
207
+ TokenOutput calldata output
208
+ ) external returns (uint256 totalTokenOut, ExitPostExpReturnParams memory params) {
209
+ IStandardizedYield SY;
210
+
211
+ (SY, params) = _exitPostExpToSy(true, address(0), market, netPtIn, netLpIn);
212
+ totalTokenOut = _redeemSyToToken(receiver, address(SY), params.totalSyOut, output, false);
213
+
214
+ emit ExitPostExpToToken(msg.sender, market, output.tokenOut, receiver, netLpIn, totalTokenOut, params);
215
+ }
216
+
217
+ /// @dev The interface might change in the future, check with Pendle team before use
218
+ function exitPostExpToSy(
219
+ address receiver,
220
+ address market,
221
+ uint256 netPtIn,
222
+ uint256 netLpIn,
223
+ uint256 minSyOut
224
+ ) external returns (ExitPostExpReturnParams memory params) {
225
+ (, params) = _exitPostExpToSy(false, receiver, market, netPtIn, netLpIn);
226
+ require(params.totalSyOut >= minSyOut, "Slippage: INSUFFICIENT_SY_OUT");
227
+
228
+ emit ExitPostExpToSy(msg.sender, market, receiver, netLpIn, params);
229
+ }
230
+
231
+ function _exitPostExpToSy(
232
+ bool setReceiverToSy,
233
+ address receiver,
234
+ address market,
235
+ uint256 netPtIn,
236
+ uint256 netLpIn
237
+ ) internal returns (IStandardizedYield SY, ExitPostExpReturnParams memory p) {
238
+ IPPrincipalToken PT;
239
+ IPYieldToken YT;
240
+ (SY, PT, YT) = IPMarket(market).readTokens();
241
+
242
+ if (setReceiverToSy) receiver = address(SY);
243
+
244
+ if (netLpIn > 0) {
245
+ _transferFrom(IERC20(market), msg.sender, market, netLpIn);
246
+ (p.netSyFromRemove, p.netPtFromRemove) = IPMarket(market).burn(receiver, address(YT), netLpIn);
247
+ }
248
+
249
+ if (netPtIn > 0) {
250
+ _transferFrom(PT, msg.sender, address(YT), netPtIn);
251
+ }
252
+
253
+ p.netPtRedeem = p.netPtFromRemove + netPtIn;
254
+ p.netSyFromRedeem = IPYieldToken(YT).redeemPY(receiver);
255
+
256
+ p.totalSyOut = p.netSyFromRemove + p.netSyFromRedeem;
257
+ }
258
+
121
259
  // ----------------- MISC FUNCTIONS -----------------
122
260
 
123
261
  function boostMarkets(address[] memory markets) external {
124
- for (uint256 i = 0; i < markets.length; ) {
262
+ for (uint256 i = 0; i < markets.length; i++) {
125
263
  IPMarket(markets[i]).transferFrom(msg.sender, markets[i], 0);
126
- unchecked {
127
- i++;
128
- }
129
264
  }
130
265
  }
131
266
 
132
267
  function multicall(Call3[] calldata calls) external payable returns (Result[] memory res) {
133
268
  uint256 length = calls.length;
134
269
  res = new Result[](length);
135
- Call3 calldata call;
136
- for (uint256 i = 0; i < length; ) {
137
- call = calls[i];
138
-
139
- // delegatecall to itself, it turns allowing invoking functions from other actions
140
- (bool success, bytes memory result) = address(this).delegatecall(call.callData);
141
-
142
- if (!success && !call.allowFailure) {
143
- assembly {
144
- // We use Yul's revert() to bubble up errors from the target contract.
145
- revert(add(32, result), mload(result))
146
- }
147
- }
148
-
149
- res[i].success = success;
150
- res[i].returnData = result;
151
-
152
- unchecked {
153
- ++i;
154
- }
270
+ for (uint256 i = 0; i < length; i++) {
271
+ (bool success, bytes memory result) = _delegateToSelf(calls[i].callData, calls[i].allowFailure);
272
+ res[i] = Result(success, result);
155
273
  }
156
274
  }
157
275
 
276
+ /// @dev The interface might change in the future, check with Pendle team before use
277
+ function callAndReflect(
278
+ address payable reflector,
279
+ bytes calldata selfCall1,
280
+ bytes calldata selfCall2,
281
+ bytes calldata reflectCall
282
+ ) external payable returns (bytes memory selfRes1, bytes memory selfRes2, bytes memory reflectRes) {
283
+ (, selfRes1) = _delegateToSelf(selfCall1, false);
284
+ if (selfCall2.length > 0) (, selfRes2) = _delegateToSelf(selfCall2, false);
285
+ reflectRes = _callToReflector(reflector, reflectCall);
286
+ }
287
+
158
288
  function simulate(address target, bytes calldata data) external payable {
159
289
  (bool success, bytes memory result) = target.delegatecall(data);
160
290
  revert Errors.SimulationResults(success, result);
161
291
  }
292
+
293
+ function _delegateToSelf(
294
+ bytes memory data,
295
+ bool allowFailure
296
+ ) internal returns (bool success, bytes memory result) {
297
+ (success, result) = address(this).delegatecall(data);
298
+
299
+ if (!success && !allowFailure) {
300
+ assembly {
301
+ // We use Yul's revert() to bubble up errors from the target contract.
302
+ revert(add(32, result), mload(result))
303
+ }
304
+ }
305
+ }
306
+
307
+ function _callToReflector(address payable reflector, bytes memory data) internal returns (bytes memory) {
308
+ return IPReflector(reflector).reflect(data);
309
+ }
162
310
  }
@@ -52,51 +52,6 @@ contract ActionSwapYTV3 is CallbackHelper, IPActionSwapYTV3, ActionBase {
52
52
  emit SwapYtAndSy(msg.sender, market, receiver, netYtOut.Int(), exactSyIn.neg());
53
53
  }
54
54
 
55
- function _entry_swapExactSyForYt(IPYieldToken YT, LimitOrderData calldata limit) internal view returns (address) {
56
- return !_isEmptyLimit(limit) ? address(this) : address(YT);
57
- }
58
-
59
- function _swapExactSyForYt(
60
- address receiver,
61
- address market,
62
- IStandardizedYield SY,
63
- IPYieldToken YT,
64
- uint256 exactSyIn,
65
- uint256 minYtOut,
66
- ApproxParams calldata guessYtOut,
67
- LimitOrderData calldata limit
68
- ) internal returns (uint256 netYtOut, uint256 netSyFee) {
69
- uint256 netSyLeft = exactSyIn;
70
- bool doMarketOrder = true;
71
-
72
- if (!_isEmptyLimit(limit)) {
73
- (netSyLeft, netYtOut, netSyFee, doMarketOrder) = _fillLimit(receiver, SY, netSyLeft, limit);
74
- if (doMarketOrder) {
75
- _transferOut(address(SY), address(YT), netSyLeft);
76
- }
77
- }
78
-
79
- if (doMarketOrder) {
80
- (uint256 netYtOutMarket, ) = _readMarket(market).approxSwapExactSyForYt(
81
- YT.newIndex(),
82
- netSyLeft,
83
- block.timestamp,
84
- guessYtOut
85
- );
86
-
87
- (, uint256 netSyFeeMarket) = IPMarket(market).swapExactPtForSy(
88
- address(YT),
89
- netYtOutMarket, // exactPtIn = netYtOut
90
- _encodeSwapExactSyForYt(receiver, YT)
91
- );
92
-
93
- netYtOut += netYtOutMarket;
94
- netSyFee += netSyFeeMarket;
95
- }
96
-
97
- if (netYtOut < minYtOut) revert("Slippage: INSUFFICIENT_YT_OUT");
98
- }
99
-
100
55
  // ------------------ SWAP TOKEN FOR TOKEN ------------------
101
56
 
102
57
  function swapExactYtForToken(
@@ -138,46 +93,6 @@ contract ActionSwapYTV3 is CallbackHelper, IPActionSwapYTV3, ActionBase {
138
93
  emit SwapYtAndSy(msg.sender, market, receiver, exactYtIn.neg(), netSyOut.Int());
139
94
  }
140
95
 
141
- function _entry_swapExactYtForSy(IPYieldToken YT, LimitOrderData calldata limit) internal view returns (address) {
142
- return !_isEmptyLimit(limit) ? address(this) : address(YT);
143
- }
144
-
145
- function _swapExactYtForSy(
146
- address receiver,
147
- address market,
148
- IStandardizedYield SY,
149
- IPYieldToken YT,
150
- uint256 exactYtIn,
151
- uint256 minSyOut,
152
- LimitOrderData calldata limit
153
- ) internal returns (uint256 netSyOut, uint256 netSyFee) {
154
- uint256 netYtLeft = exactYtIn;
155
- bool doMarketOrder = true;
156
-
157
- if (!_isEmptyLimit(limit)) {
158
- (netYtLeft, netSyOut, netSyFee, doMarketOrder) = _fillLimit(receiver, YT, netYtLeft, limit);
159
- if (doMarketOrder) {
160
- _transferOut(address(YT), address(YT), netYtLeft);
161
- }
162
- }
163
-
164
- if (doMarketOrder) {
165
- uint256 preSyBalance = SY.balanceOf(receiver);
166
-
167
- (, uint256 netSyFeeMarket) = IPMarket(market).swapSyForExactPt(
168
- address(YT),
169
- netYtLeft, // exactPtOut = netYtLeft
170
- _encodeSwapYtForSy(receiver, YT)
171
- );
172
-
173
- // avoid stack issue
174
- netSyFee += netSyFeeMarket;
175
- netSyOut += SY.balanceOf(receiver) - preSyBalance;
176
- }
177
-
178
- if (netSyOut < minSyOut) revert("Slippage: INSUFFICIENT_SY_OUT");
179
- }
180
-
181
96
  // ------------------ SWAP PT FOR YT ------------------
182
97
 
183
98
  function swapExactPtForYt(