@pendle/core-v2 0.1.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 (182) hide show
  1. package/LICENSE +100 -0
  2. package/contracts/SuperComposableYield/ISuperComposableYield.sol +68 -0
  3. package/contracts/SuperComposableYield/SCYUtils.sol +14 -0
  4. package/contracts/SuperComposableYield/implementations/RewardManager.sol +117 -0
  5. package/contracts/SuperComposableYield/implementations/SCYBase.sol +126 -0
  6. package/contracts/SuperComposableYield/implementations/SCYBaseWithRewards.sol +79 -0
  7. package/contracts/core/PendleBaseToken.sol +39 -0
  8. package/contracts/core/PendleMarket.sol +248 -0
  9. package/contracts/core/PendleMarketFactory.sol +60 -0
  10. package/contracts/core/PendleOwnershipToken.sol +44 -0
  11. package/contracts/core/PendleSCYImpl/AaveV3/PendleAaveV3SCY.sol +139 -0
  12. package/contracts/core/PendleSCYImpl/AaveV3/WadRayMath.sol +126 -0
  13. package/contracts/core/PendleSCYImpl/PendleBenQiErc20SCY.sol +127 -0
  14. package/contracts/core/PendleSCYImpl/PendleBtrflySCY.sol +125 -0
  15. package/contracts/core/PendleSCYImpl/PendleYearnVaultSCY.sol +115 -0
  16. package/contracts/core/PendleYieldContractFactory.sol +109 -0
  17. package/contracts/core/PendleYieldToken.sol +240 -0
  18. package/contracts/core/misc/BoringOwnable.sol +62 -0
  19. package/contracts/core/misc/BoringOwnableUpg.sol +64 -0
  20. package/contracts/core/misc/PendleJoeSwapHelperUpg.sol +82 -0
  21. package/contracts/core/router/PendleRouterCoreUpg.sol +219 -0
  22. package/contracts/core/router/PendleRouterProxy.sol +64 -0
  23. package/contracts/core/router/PendleRouterYTUpg.sol +134 -0
  24. package/contracts/core/router/base/PendleRouterOTBaseUpg.sol +218 -0
  25. package/contracts/core/router/base/PendleRouterSCYAndForgeBaseUpg.sol +141 -0
  26. package/contracts/core/router/base/PendleRouterYTBaseUpg.sol +212 -0
  27. package/contracts/interfaces/IAToken.sol +34 -0
  28. package/contracts/interfaces/IAavePool.sol +41 -0
  29. package/contracts/interfaces/IAaveRewardsController.sol +32 -0
  30. package/contracts/interfaces/IBenQiComptroller.sol +33 -0
  31. package/contracts/interfaces/IJoePair.sol +98 -0
  32. package/contracts/interfaces/IJoeRouter01.sol +162 -0
  33. package/contracts/interfaces/IPBaseToken.sol +9 -0
  34. package/contracts/interfaces/IPFlashCallBack.sol +10 -0
  35. package/contracts/interfaces/IPGovernanceManager.sol +28 -0
  36. package/contracts/interfaces/IPMarket.sol +57 -0
  37. package/contracts/interfaces/IPMarketAddRemoveCallback.sol +18 -0
  38. package/contracts/interfaces/IPMarketFactory.sol +8 -0
  39. package/contracts/interfaces/IPMarketSwapCallback.sol +10 -0
  40. package/contracts/interfaces/IPOwnershipToken.sol +15 -0
  41. package/contracts/interfaces/IPPermissionsV2.sol +28 -0
  42. package/contracts/interfaces/IPRouterCore.sol +108 -0
  43. package/contracts/interfaces/IPRouterYT.sol +47 -0
  44. package/contracts/interfaces/IPYieldContractFactory.sol +36 -0
  45. package/contracts/interfaces/IPYieldToken.sol +19 -0
  46. package/contracts/interfaces/IQiErc20.sol +35 -0
  47. package/contracts/interfaces/IQiToken.sol +29 -0
  48. package/contracts/interfaces/IREDACTEDStaking.sol +35 -0
  49. package/contracts/interfaces/IWETH.sol +34 -0
  50. package/contracts/interfaces/IWXBTRFLY.sol +37 -0
  51. package/contracts/interfaces/IYearnVault.sol +32 -0
  52. package/contracts/libraries/JoeLibrary.sol +121 -0
  53. package/contracts/libraries/SCYIndex.sol +55 -0
  54. package/contracts/libraries/helpers/ExpiryUtilsLib.sol +166 -0
  55. package/contracts/libraries/math/FixedPoint.sol +208 -0
  56. package/contracts/libraries/math/LogExpMath.sol +515 -0
  57. package/contracts/libraries/math/MarketApproxLib.sol +140 -0
  58. package/contracts/libraries/math/MarketMathLib.sol +606 -0
  59. package/contracts/periphery/PendleGovernanceManager.sol +36 -0
  60. package/contracts/periphery/PermissionsV2.sol +23 -0
  61. package/package.json +76 -0
  62. package/typechain-types/BoringOwnable.ts +194 -0
  63. package/typechain-types/BoringOwnableData.ts +100 -0
  64. package/typechain-types/BoringOwnableUpg.ts +194 -0
  65. package/typechain-types/BoringOwnableUpgData.ts +100 -0
  66. package/typechain-types/ERC1967UpgradeUpgradeable.ts +97 -0
  67. package/typechain-types/ERC20.ts +417 -0
  68. package/typechain-types/IAToken.ts +331 -0
  69. package/typechain-types/IAavePool.ts +192 -0
  70. package/typechain-types/IAaveRewardsController.ts +148 -0
  71. package/typechain-types/IBeaconUpgradeable.ts +87 -0
  72. package/typechain-types/IBenQiComptroller.ts +125 -0
  73. package/typechain-types/IERC1822ProxiableUpgradeable.ts +87 -0
  74. package/typechain-types/IERC20.ts +300 -0
  75. package/typechain-types/IERC20Metadata.ts +339 -0
  76. package/typechain-types/IJoePair.ts +888 -0
  77. package/typechain-types/IJoeRouter01.ts +1107 -0
  78. package/typechain-types/IPBaseToken.ts +365 -0
  79. package/typechain-types/IPFlashCallback.ts +115 -0
  80. package/typechain-types/IPGovernanceManager.ts +84 -0
  81. package/typechain-types/IPMarket.ts +701 -0
  82. package/typechain-types/IPMarketAddRemoveCallback.ts +169 -0
  83. package/typechain-types/IPMarketFactory.ts +109 -0
  84. package/typechain-types/IPMarketSwapCallback.ts +115 -0
  85. package/typechain-types/IPOwnershipToken.ts +488 -0
  86. package/typechain-types/IPRouterCore.ts +759 -0
  87. package/typechain-types/IPRouterYT.ts +405 -0
  88. package/typechain-types/IPYieldContractFactory.ts +192 -0
  89. package/typechain-types/IPYieldToken.ts +525 -0
  90. package/typechain-types/IPermissionsV2.ts +87 -0
  91. package/typechain-types/IQiErc20.ts +402 -0
  92. package/typechain-types/IQiToken.ts +327 -0
  93. package/typechain-types/IREDACTEDStaking.ts +216 -0
  94. package/typechain-types/ISuperComposableYield.ts +652 -0
  95. package/typechain-types/IWETH.ts +380 -0
  96. package/typechain-types/IWXBTRFLY.ts +254 -0
  97. package/typechain-types/IYearnVault.ts +152 -0
  98. package/typechain-types/PendleAaveV3SCY.ts +901 -0
  99. package/typechain-types/PendleBaseToken.ts +505 -0
  100. package/typechain-types/PendleBenQiErc20SCY.ts +914 -0
  101. package/typechain-types/PendleBtrflyScy.ts +794 -0
  102. package/typechain-types/PendleGovernanceManager.ts +187 -0
  103. package/typechain-types/PendleJoeSwapHelperUpg.ts +97 -0
  104. package/typechain-types/PendleMarket.ts +1008 -0
  105. package/typechain-types/PendleMarketFactory.ts +246 -0
  106. package/typechain-types/PendleOwnershipToken.ts +628 -0
  107. package/typechain-types/PendleRouterCoreUpg.ts +780 -0
  108. package/typechain-types/PendleRouterProxy.ts +417 -0
  109. package/typechain-types/PendleRouterSCYAndForgeBaseUpg.ts +98 -0
  110. package/typechain-types/PendleRouterYTBaseUpg.ts +134 -0
  111. package/typechain-types/PendleRouterYTUpg.ts +453 -0
  112. package/typechain-types/PendleYearnVaultScy.ts +784 -0
  113. package/typechain-types/PendleYieldContractFactory.ts +479 -0
  114. package/typechain-types/PendleYieldToken.ts +1030 -0
  115. package/typechain-types/PermissionsV2.ts +87 -0
  116. package/typechain-types/Proxy.ts +57 -0
  117. package/typechain-types/RewardManager.ts +172 -0
  118. package/typechain-types/SCYBase.ts +734 -0
  119. package/typechain-types/SCYBaseWithRewards.ts +819 -0
  120. package/typechain-types/UUPSUpgradeable.ts +197 -0
  121. package/typechain-types/common.ts +44 -0
  122. package/typechain-types/factories/BoringOwnableData__factory.ts +90 -0
  123. package/typechain-types/factories/BoringOwnableUpgData__factory.ts +94 -0
  124. package/typechain-types/factories/BoringOwnableUpg__factory.ts +139 -0
  125. package/typechain-types/factories/BoringOwnable__factory.ts +149 -0
  126. package/typechain-types/factories/ERC1967UpgradeUpgradeable__factory.ts +75 -0
  127. package/typechain-types/factories/ERC20__factory.ts +348 -0
  128. package/typechain-types/factories/IAToken__factory.ts +225 -0
  129. package/typechain-types/factories/IAavePool__factory.ts +99 -0
  130. package/typechain-types/factories/IAaveRewardsController__factory.ts +78 -0
  131. package/typechain-types/factories/IBeaconUpgradeable__factory.ts +39 -0
  132. package/typechain-types/factories/IBenQiComptroller__factory.ts +59 -0
  133. package/typechain-types/factories/IERC1822ProxiableUpgradeable__factory.ts +43 -0
  134. package/typechain-types/factories/IERC20Metadata__factory.ts +248 -0
  135. package/typechain-types/factories/IERC20__factory.ts +203 -0
  136. package/typechain-types/factories/IJoePair__factory.ts +674 -0
  137. package/typechain-types/factories/IJoeRouter01__factory.ts +772 -0
  138. package/typechain-types/factories/IPBaseToken__factory.ts +271 -0
  139. package/typechain-types/factories/IPFlashCallback__factory.ts +49 -0
  140. package/typechain-types/factories/IPGovernanceManager__factory.ts +39 -0
  141. package/typechain-types/factories/IPMarketAddRemoveCallback__factory.ts +86 -0
  142. package/typechain-types/factories/IPMarketFactory__factory.ts +58 -0
  143. package/typechain-types/factories/IPMarketSwapCallback__factory.ts +53 -0
  144. package/typechain-types/factories/IPMarket__factory.ts +559 -0
  145. package/typechain-types/factories/IPOwnershipToken__factory.ts +349 -0
  146. package/typechain-types/factories/IPRouterCore__factory.ts +516 -0
  147. package/typechain-types/factories/IPRouterYT__factory.ts +246 -0
  148. package/typechain-types/factories/IPYieldContractFactory__factory.ts +117 -0
  149. package/typechain-types/factories/IPYieldToken__factory.ts +383 -0
  150. package/typechain-types/factories/IPermissionsV2__factory.ts +39 -0
  151. package/typechain-types/factories/IQiErc20__factory.ts +270 -0
  152. package/typechain-types/factories/IQiToken__factory.ts +219 -0
  153. package/typechain-types/factories/IREDACTEDStaking__factory.ts +107 -0
  154. package/typechain-types/factories/ISuperComposableYield__factory.ts +438 -0
  155. package/typechain-types/factories/IWETH__factory.ts +261 -0
  156. package/typechain-types/factories/IWXBTRFLY__factory.ts +131 -0
  157. package/typechain-types/factories/IYearnVault__factory.ts +74 -0
  158. package/typechain-types/factories/PendleAaveV3SCY__factory.ts +727 -0
  159. package/typechain-types/factories/PendleBaseToken__factory.ts +386 -0
  160. package/typechain-types/factories/PendleBenQiErc20SCY__factory.ts +753 -0
  161. package/typechain-types/factories/PendleBtrflyScy__factory.ts +652 -0
  162. package/typechain-types/factories/PendleGovernanceManager__factory.ts +149 -0
  163. package/typechain-types/factories/PendleJoeSwapHelperUpg__factory.ts +56 -0
  164. package/typechain-types/factories/PendleMarketFactory__factory.ts +207 -0
  165. package/typechain-types/factories/PendleMarket__factory.ts +891 -0
  166. package/typechain-types/factories/PendleOwnershipToken__factory.ts +565 -0
  167. package/typechain-types/factories/PendleRouterCoreUpg__factory.ts +620 -0
  168. package/typechain-types/factories/PendleRouterProxy__factory.ts +316 -0
  169. package/typechain-types/factories/PendleRouterSCYAndForgeBaseUpg__factory.ts +56 -0
  170. package/typechain-types/factories/PendleRouterYTBaseUpg__factory.ts +66 -0
  171. package/typechain-types/factories/PendleRouterYTUpg__factory.ts +363 -0
  172. package/typechain-types/factories/PendleYearnVaultScy__factory.ts +630 -0
  173. package/typechain-types/factories/PendleYieldContractFactory__factory.ts +368 -0
  174. package/typechain-types/factories/PendleYieldToken__factory.ts +814 -0
  175. package/typechain-types/factories/PermissionsV2__factory.ts +36 -0
  176. package/typechain-types/factories/Proxy__factory.ts +28 -0
  177. package/typechain-types/factories/RewardManager__factory.ts +89 -0
  178. package/typechain-types/factories/SCYBaseWithRewards__factory.ts +535 -0
  179. package/typechain-types/factories/SCYBase__factory.ts +479 -0
  180. package/typechain-types/factories/UUPSUpgradeable__factory.ts +115 -0
  181. package/typechain-types/hardhat.d.ts +564 -0
  182. package/typechain-types/index.ts +122 -0
@@ -0,0 +1,64 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ pragma solidity 0.8.9;
3
+
4
+ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5
+ import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
6
+ import "../misc/BoringOwnableUpg.sol";
7
+ import "@openzeppelin/contracts/proxy/Proxy.sol";
8
+ import "../../interfaces/IPRouterCore.sol";
9
+ import "../../interfaces/IPRouterYT.sol";
10
+
11
+ /// @dev this contract will be deployed behind an ERC1967 proxy
12
+ /// calls to the ERC1967 proxy will be resolved at this contract, and proxied again to the
13
+ /// corresponding implementation contracts
14
+ contract PendleRouterProxy is Proxy, Initializable, UUPSUpgradeable, BoringOwnableUpg {
15
+ address public immutable PENDLE_ROUTER_CORE;
16
+ address public immutable PENDLE_ROUTER_YT;
17
+
18
+ constructor(address _PENDLE_ROUTER_CORE, address _PENDLE_ROUTER_YT) {
19
+ PENDLE_ROUTER_CORE = _PENDLE_ROUTER_CORE;
20
+ PENDLE_ROUTER_YT = _PENDLE_ROUTER_YT;
21
+ }
22
+
23
+ function initialize() external initializer {
24
+ __UUPSUpgradeable_init();
25
+ __BoringOwnable_init();
26
+ }
27
+
28
+ function getRouterImplementation(bytes4 sig) public view returns (address) {
29
+ if (
30
+ sig == IPRouterCore.mintScyFromRawToken.selector ||
31
+ sig == IPRouterCore.redeemScyToRawToken.selector ||
32
+ sig == IPRouterCore.mintYoFromRawToken.selector ||
33
+ sig == IPRouterCore.redeemYoToRawToken.selector ||
34
+ sig == IPRouterCore.addLiquidity.selector ||
35
+ sig == IPRouterCore.removeLiquidity.selector ||
36
+ sig == IPRouterCore.swapExactOtForScy.selector ||
37
+ sig == IPRouterCore.swapOtForExactScy.selector ||
38
+ sig == IPRouterCore.swapScyForExactOt.selector ||
39
+ sig == IPRouterCore.swapExactScyForOt.selector ||
40
+ sig == IPRouterCore.swapExactRawTokenForOt.selector ||
41
+ sig == IPRouterCore.swapExactOtForRawToken.selector
42
+ ) {
43
+ return PENDLE_ROUTER_CORE;
44
+ } else if (
45
+ sig == IPRouterYT.swapExactYtForScy.selector ||
46
+ sig == IPRouterYT.swapScyForExactYt.selector ||
47
+ sig == IPRouterYT.swapExactScyForYt.selector ||
48
+ sig == IPRouterYT.swapExactRawTokenForYt.selector ||
49
+ sig == IPRouterYT.swapExactYtForRawToken.selector
50
+ ) {
51
+ return PENDLE_ROUTER_YT;
52
+ } else if (sig == IPMarketSwapCallback.swapCallback.selector) {
53
+ // only ROUTER_YT is doing callback
54
+ return PENDLE_ROUTER_YT;
55
+ }
56
+ require(false, "invalid market sig");
57
+ }
58
+
59
+ function _implementation() internal view override returns (address) {
60
+ return getRouterImplementation(msg.sig);
61
+ }
62
+
63
+ function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
64
+ }
@@ -0,0 +1,134 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ pragma solidity 0.8.9;
3
+
4
+ import "./base/PendleRouterSCYAndForgeBaseUpg.sol";
5
+ import "./base/PendleRouterYTBaseUpg.sol";
6
+ import "../../interfaces/IPOwnershipToken.sol";
7
+ import "../../interfaces/IPYieldToken.sol";
8
+
9
+ contract PendleRouterYTUpg is PendleRouterSCYAndForgeBaseUpg, PendleRouterYTBaseUpg {
10
+ using MarketMathLib for MarketParameters;
11
+ using FixedPoint for uint256;
12
+ using FixedPoint for int256;
13
+
14
+ /// @dev since this contract will be proxied, it must not contains non-immutable variables
15
+ constructor(
16
+ address _joeRouter,
17
+ address _joeFactory,
18
+ address _marketFactory
19
+ )
20
+ PendleRouterSCYAndForgeBaseUpg(_joeRouter, _joeFactory)
21
+ PendleRouterYTBaseUpg(_marketFactory)
22
+ //solhint-disable-next-line no-empty-blocks
23
+ {
24
+
25
+ }
26
+
27
+ function swapExactYtForScy(
28
+ address receiver,
29
+ address market,
30
+ uint256 exactYtIn,
31
+ uint256 minScyOut
32
+ ) external returns (uint256) {
33
+ return _swapExactYtForScy(receiver, market, exactYtIn, minScyOut, true);
34
+ }
35
+
36
+ function swapScyForExactYt(
37
+ address receiver,
38
+ address market,
39
+ uint256 exactYtOut,
40
+ uint256 maxScyIn
41
+ ) external returns (uint256) {
42
+ return _swapScyForExactYt(receiver, market, exactYtOut, maxScyIn);
43
+ }
44
+
45
+ function swapExactScyForYt(
46
+ address receiver,
47
+ address market,
48
+ uint256 exactScyIn,
49
+ uint256 minYtOut,
50
+ uint256 netYtOutGuessMin,
51
+ uint256 netYtOutGuessMax
52
+ ) external returns (uint256) {
53
+ return
54
+ _swapExactScyForYt(
55
+ receiver,
56
+ market,
57
+ exactScyIn,
58
+ minYtOut,
59
+ netYtOutGuessMin,
60
+ netYtOutGuessMax,
61
+ true
62
+ );
63
+ }
64
+
65
+ /**
66
+ * @dev netYtOutGuessMin & Max can be used in the same way as RawTokenOT
67
+ * @param path the path to swap from rawToken to baseToken. path = [baseToken] if no swap is needed
68
+ * @dev inner working of this function:
69
+ - mintScyFromRawToken is invoked, except the YT contract will receive all the outcome SCY
70
+ - market.swap is called, which will transfer SCY to the YT contract, and callback is invoked
71
+ - callback will do call YT's mintYO, which will mint OT to the market & YT to the receiver
72
+ */
73
+ function swapExactRawTokenForYt(
74
+ uint256 exactRawTokenIn,
75
+ address receiver,
76
+ address[] calldata path,
77
+ address market,
78
+ uint256 minYtOut,
79
+ uint256 netYtOutGuessMin,
80
+ uint256 netYtOutGuessMax
81
+ ) external returns (uint256 netYtOut) {
82
+ (ISuperComposableYield SCY, , IPYieldToken YT) = IPMarket(market).readTokens();
83
+
84
+ uint256 netScyUsedToBuyYT = _mintScyFromRawToken(
85
+ exactRawTokenIn,
86
+ address(SCY),
87
+ 1,
88
+ address(YT),
89
+ path,
90
+ true
91
+ );
92
+
93
+ netYtOut = _swapExactScyForYt(
94
+ receiver,
95
+ market,
96
+ netScyUsedToBuyYT,
97
+ minYtOut,
98
+ netYtOutGuessMin,
99
+ netYtOutGuessMax,
100
+ false
101
+ );
102
+ }
103
+
104
+ /**
105
+ * @notice swap YT -> SCY -> baseToken -> rawToken
106
+ * @notice the algorithm to swap will guarantee to swap all the YT available
107
+ * @param path the path to swap from rawToken to baseToken. path = [baseToken] if no swap is needed
108
+ * @dev inner working of this function:
109
+ - YT is transferred to the YT contract
110
+ - market.swap is called, which will transfer OT directly to the YT contract, and callback is invoked
111
+ - callback will do call YT's redeemYO, which will redeem the outcome SCY to this router, then
112
+ all SCY owed to the market will be paid, the rest is used to feed redeemScyToRawToken
113
+ */
114
+ function swapExactYtForRawToken(
115
+ uint256 exactYtIn,
116
+ address receiver,
117
+ address[] calldata path,
118
+ address market,
119
+ uint256 minRawTokenOut
120
+ ) external returns (uint256 netRawTokenOut) {
121
+ (ISuperComposableYield SCY, , ) = IPMarket(market).readTokens();
122
+
123
+ uint256 netScyOut = _swapExactYtForScy(address(SCY), market, exactYtIn, 1, true);
124
+
125
+ netRawTokenOut = _redeemScyToRawToken(
126
+ address(SCY),
127
+ netScyOut,
128
+ minRawTokenOut,
129
+ receiver,
130
+ path,
131
+ false
132
+ );
133
+ }
134
+ }
@@ -0,0 +1,218 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ pragma solidity 0.8.9;
3
+
4
+ import "../../../interfaces/IPMarketFactory.sol";
5
+ import "../../../interfaces/IPMarket.sol";
6
+ import "../../../interfaces/IPMarketAddRemoveCallback.sol";
7
+ import "../../../interfaces/IPMarketSwapCallback.sol";
8
+ import "../../../libraries/math/MarketApproxLib.sol";
9
+ import "openzeppelin-solidity/contracts/token/ERC20/utils/SafeERC20.sol";
10
+
11
+ abstract contract PendleRouterOTBaseUpg {
12
+ using FixedPoint for uint256;
13
+ using FixedPoint for int256;
14
+ using MarketMathLib for MarketParameters;
15
+ using MarketApproxLib for MarketParameters;
16
+ using SafeERC20 for IERC20;
17
+
18
+ /// @dev since this contract will be proxied, it must not contains non-immutable variables
19
+ constructor() //solhint-disable-next-line no-empty-blocks
20
+ {
21
+
22
+ }
23
+
24
+ /**
25
+ * @notice addLiquidity to the market, using both SCY & OT, the receiver will receive LP before
26
+ msg.sender is required to pay SCY & OT
27
+ * @dev inner working of this function:
28
+ - market.addLiquidity is called
29
+ - LP is minted to the receiver, and this router's addLiquidityCallback is invoked
30
+ - the router will transfer the necessary scy & ot from msg.sender to the market, and finish the callback
31
+ */
32
+ function _addLiquidity(
33
+ address receiver,
34
+ address market,
35
+ uint256 scyDesired,
36
+ uint256 otDesired,
37
+ uint256 minLpOut,
38
+ bool doPull
39
+ )
40
+ internal
41
+ returns (
42
+ uint256 netLpOut,
43
+ uint256 scyUsed,
44
+ uint256 otUsed
45
+ )
46
+ {
47
+ (ISuperComposableYield SCY, IPOwnershipToken OT, ) = IPMarket(market).readTokens();
48
+
49
+ MarketParameters memory state = IPMarket(market).readState();
50
+ (, netLpOut, scyUsed, otUsed) = state.addLiquidity(
51
+ SCYIndexLib.newIndex(SCY),
52
+ scyDesired,
53
+ otDesired
54
+ );
55
+
56
+ require(netLpOut >= minLpOut, "insufficient lp out");
57
+
58
+ if (doPull) {
59
+ IERC20(SCY).safeTransferFrom(msg.sender, market, scyUsed);
60
+ IERC20(OT).safeTransferFrom(msg.sender, market, otUsed);
61
+ }
62
+
63
+ IPMarket(market).addLiquidity(receiver, otDesired, scyDesired, abi.encode());
64
+ }
65
+
66
+ /**
67
+ * @notice removeLiquidity from the market to receive both SCY & OT. The receiver will receive
68
+ SCY & OT before msg.sender is required to transfer in the necessary LP
69
+ * @dev inner working of this function:
70
+ - market.removeLiquidity is called
71
+ - SCY & OT is transferred to the receiver, and the router's callback is invoked
72
+ - the router will transfer the necessary LP from msg.sender to the market, and finish the callback
73
+ */
74
+ function _removeLiquidity(
75
+ address receiver,
76
+ address market,
77
+ uint256 lpToRemove,
78
+ uint256 scyOutMin,
79
+ uint256 otOutMin,
80
+ bool doPull
81
+ ) internal returns (uint256 netScyOut, uint256 netOtOut) {
82
+ MarketParameters memory state = IPMarket(market).readState();
83
+
84
+ (netScyOut, netOtOut) = state.removeLiquidity(lpToRemove);
85
+ require(netScyOut >= scyOutMin, "insufficient scy out");
86
+ require(netOtOut >= otOutMin, "insufficient ot out");
87
+
88
+ if (doPull) {
89
+ IERC20(market).safeTransferFrom(msg.sender, market, lpToRemove);
90
+ }
91
+
92
+ IPMarket(market).removeLiquidity(receiver, lpToRemove, abi.encode());
93
+ }
94
+
95
+ /**
96
+ * @notice swap exact OT for SCY, with receiver receiving SCY before msg.sender is required to
97
+ transfer the owed OT
98
+ * @dev inner working of this function:
99
+ - market.swap is called
100
+ - SCY is transferred to the receiver, and the router's callback is invoked
101
+ - the router will transfer the necessary OT from msg.sender to the market, and finish the callback
102
+ */
103
+ function _swapExactOtForScy(
104
+ address receiver,
105
+ address market,
106
+ uint256 exactOtIn,
107
+ uint256 minScyOut,
108
+ bool doPull
109
+ ) internal returns (uint256 netScyOut) {
110
+ if (doPull) {
111
+ address OT = IPMarket(market).OT();
112
+ IERC20(OT).safeTransferFrom(msg.sender, market, exactOtIn);
113
+ }
114
+
115
+ (netScyOut, ) = IPMarket(market).swapExactOtForScy(
116
+ receiver,
117
+ exactOtIn,
118
+ minScyOut,
119
+ abi.encode()
120
+ );
121
+
122
+ require(netScyOut >= minScyOut, "insufficient scy out");
123
+ }
124
+
125
+ function _swapOtForExactScy(
126
+ address receiver,
127
+ address market,
128
+ uint256 maxOtIn,
129
+ uint256 exactScyOut,
130
+ uint256 netOtInGuessMin,
131
+ uint256 netOtInGuessMax,
132
+ bool doPull
133
+ ) internal returns (uint256 netOtIn) {
134
+ MarketParameters memory state = IPMarket(market).readState();
135
+ (ISuperComposableYield SCY, IPOwnershipToken OT, ) = IPMarket(market).readTokens();
136
+
137
+ netOtIn = state.approxSwapOtForExactScy(
138
+ SCYIndexLib.newIndex(SCY),
139
+ exactScyOut,
140
+ block.timestamp,
141
+ netOtInGuessMin,
142
+ netOtInGuessMax
143
+ );
144
+
145
+ require(netOtIn <= maxOtIn, "ot in exceed limit");
146
+
147
+ if (doPull) {
148
+ IERC20(OT).safeTransferFrom(msg.sender, market, netOtIn);
149
+ }
150
+
151
+ IPMarket(market).swapExactOtForScy(receiver, netOtIn, exactScyOut, abi.encode());
152
+ }
153
+
154
+ /**
155
+ * @notice swap SCY for exact OT, with receiver receiving OT before msg.sender is required to
156
+ transfer the owed SCY
157
+ * @dev inner working of this function:
158
+ - market.swap is called
159
+ - OT is transferred to the receiver, and the router's callback is invoked
160
+ - the router will transfer the necessary SCY from msg.sender to the market, and finish the callback
161
+ */
162
+ function _swapScyForExactOt(
163
+ address receiver,
164
+ address market,
165
+ uint256 exactOtOut,
166
+ uint256 maxScyIn,
167
+ bool doPull
168
+ ) internal returns (uint256 netScyIn) {
169
+ MarketParameters memory state = IPMarket(market).readState();
170
+ address SCY = IPMarket(market).SCY();
171
+
172
+ (netScyIn, ) = state.swapScyForExactOt(
173
+ SCYIndexLib.newIndex(SCY),
174
+ exactOtOut,
175
+ block.timestamp
176
+ );
177
+ require(netScyIn <= maxScyIn, "exceed limit scy in");
178
+
179
+ if (doPull) {
180
+ IERC20(SCY).safeTransferFrom(msg.sender, market, netScyIn);
181
+ }
182
+
183
+ IPMarket(market).swapScyForExactOt(receiver, exactOtOut, maxScyIn, abi.encode());
184
+ }
185
+
186
+ function _swapExactScyForOt(
187
+ address receiver,
188
+ address market,
189
+ uint256 exactScyIn,
190
+ uint256 minOtOut,
191
+ uint256 netOtOutGuessMin,
192
+ uint256 netOtOutGuessMax,
193
+ bool doPull
194
+ ) internal returns (uint256 netOtOut) {
195
+ MarketParameters memory state = IPMarket(market).readState();
196
+ address SCY = IPMarket(market).SCY();
197
+
198
+ if (netOtOutGuessMax == type(uint256).max) {
199
+ netOtOutGuessMax = state.totalOt.Uint();
200
+ }
201
+
202
+ netOtOut = state.approxSwapExactScyForOt(
203
+ SCYIndexLib.newIndex(SCY),
204
+ exactScyIn,
205
+ block.timestamp,
206
+ netOtOutGuessMin,
207
+ netOtOutGuessMax
208
+ );
209
+
210
+ require(netOtOut >= minOtOut, "insufficient out");
211
+
212
+ if (doPull) {
213
+ IERC20(SCY).safeTransferFrom(msg.sender, market, exactScyIn);
214
+ }
215
+
216
+ IPMarket(market).swapScyForExactOt(receiver, netOtOut, exactScyIn, abi.encode());
217
+ }
218
+ }
@@ -0,0 +1,141 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ pragma solidity 0.8.9;
3
+
4
+ import "openzeppelin-solidity/contracts/token/ERC20/utils/SafeERC20.sol";
5
+ import "../../misc/PendleJoeSwapHelperUpg.sol";
6
+ import "../../../SuperComposableYield/ISuperComposableYield.sol";
7
+ import "../../../interfaces/IPYieldToken.sol";
8
+
9
+ abstract contract PendleRouterSCYAndForgeBaseUpg is PendleJoeSwapHelperUpg {
10
+ using SafeERC20 for IERC20;
11
+
12
+ /// @dev since this contract will be proxied, it must not contains non-immutable variables
13
+ constructor(address _joeRouter, address _joeFactory)
14
+ PendleJoeSwapHelperUpg(_joeRouter, _joeFactory)
15
+ // solhint-disable-next-line no-empty-blocks
16
+ {
17
+
18
+ }
19
+
20
+ /**
21
+ * @notice swap rawToken to baseToken -> baseToken to mint SCY
22
+ * @param path the path to swap from rawToken to baseToken. path = [baseToken] if no swap is needed
23
+ * @dev inner working of this function:
24
+ - if [rawToken == baseToken], rawToken is transferred to SCY contract
25
+ else, it is transferred to the first pair of path, swap is called, and the output token is transferred
26
+ to SCY contract
27
+ - SCY.mint is called, minting SCY directly to receiver
28
+ */
29
+ function _mintScyFromRawToken(
30
+ uint256 netRawTokenIn,
31
+ address SCY,
32
+ uint256 minScyOut,
33
+ address receiver,
34
+ address[] calldata path,
35
+ bool doPull
36
+ ) internal returns (uint256 netScyOut) {
37
+ if (doPull) {
38
+ if (path.length == 1) {
39
+ IERC20(path[0]).safeTransferFrom(msg.sender, SCY, netRawTokenIn);
40
+ } else {
41
+ IERC20(path[0]).safeTransferFrom(msg.sender, _getFirstPair(path), netRawTokenIn);
42
+ _swapExactIn(path, netRawTokenIn, SCY);
43
+ }
44
+ }
45
+
46
+ address baseToken = path[path.length - 1];
47
+ netScyOut = ISuperComposableYield(SCY).mint(receiver, baseToken, minScyOut);
48
+ }
49
+
50
+ /**
51
+ * @notice redeem SCY to baseToken -> swap baseToken to rawToken
52
+ * @dev path[0] will be the baseToken that SCY is redeemed to, and path[path.length-1] is the
53
+ final rawToken output
54
+ * @param path the path to swap from rawToken to baseToken. path = [baseToken] if no swap is needed
55
+ * @dev inner working of this function:
56
+ - SCY is transferred to SCY contract
57
+ - if [rawToken == baseToken], SCY.redeem is called & directly redeem tokens to the receiver
58
+ else, SCY.redeem is called with receiver = first pair in the path,
59
+ and swap is called, and the output token is transferred to receiver
60
+ */
61
+ function _redeemScyToRawToken(
62
+ address SCY,
63
+ uint256 netScyIn,
64
+ uint256 minRawTokenOut,
65
+ address receiver,
66
+ address[] memory path,
67
+ bool doPull
68
+ ) internal returns (uint256 netRawTokenOut) {
69
+ if (doPull) {
70
+ IERC20(SCY).safeTransferFrom(msg.sender, SCY, netScyIn);
71
+ }
72
+
73
+ address baseToken = path[0];
74
+ if (path.length == 1) {
75
+ netRawTokenOut = ISuperComposableYield(SCY).redeem(
76
+ receiver,
77
+ baseToken,
78
+ minRawTokenOut
79
+ );
80
+ } else {
81
+ uint256 netBaseTokenOut = ISuperComposableYield(SCY).redeem(
82
+ _getFirstPair(path),
83
+ baseToken,
84
+ 1
85
+ );
86
+ netRawTokenOut = _swapExactIn(path, netBaseTokenOut, receiver);
87
+ require(netRawTokenOut >= minRawTokenOut, "insufficient out");
88
+ }
89
+ }
90
+
91
+ /**
92
+ * @notice swap rawToken to baseToken -> convert to SCY -> convert to OT + YT
93
+ * @param path the path to swap from rawToken to baseToken. path = [baseToken] if no swap is needed
94
+ * @dev inner working of this function:
95
+ - same as mintScyFromRawToken, except the receiver of SCY will be the YT contract, then mintYO
96
+ will be called, minting OT + YT directly to receiver
97
+ */
98
+ function _mintYoFromRawToken(
99
+ uint256 netRawTokenIn,
100
+ address YT,
101
+ uint256 minYoOut,
102
+ address receiver,
103
+ address[] calldata path,
104
+ bool doPull
105
+ ) internal returns (uint256 netYoOut) {
106
+ address SCY = IPYieldToken(YT).SCY();
107
+ _mintScyFromRawToken(netRawTokenIn, SCY, 1, YT, path, doPull);
108
+ netYoOut = IPYieldToken(YT).mintYO(receiver, receiver);
109
+ require(netYoOut >= minYoOut, "insufficient YO out");
110
+ }
111
+
112
+ /**
113
+ * @notice redeem OT + YT to SCY -> redeem SCY to baseToken -> swap baseToken to rawToken
114
+ * @param path the path to swap from rawToken to baseToken. path = [baseToken] if no swap is needed
115
+ * @dev inner working of this function:
116
+ - OT (+ YT if not expired) is transferred to the YT contract
117
+ - redeemYO is called, redeem all outcome SCY to the SCY contract
118
+ - The rest is the same as redeemScyToRawToken (except the first SCY transfer is skipped)
119
+ */
120
+ function _redeemYoToRawToken(
121
+ address YT,
122
+ uint256 netYoIn,
123
+ uint256 minRawTokenOut,
124
+ address receiver,
125
+ address[] memory path,
126
+ bool doPull
127
+ ) internal returns (uint256 netRawTokenOut) {
128
+ address OT = IPYieldToken(YT).OT();
129
+ address SCY = IPYieldToken(YT).SCY();
130
+
131
+ if (doPull) {
132
+ bool isNeedToBurnYt = (IPBaseToken(YT).isExpired() == false);
133
+ IERC20(OT).safeTransferFrom(msg.sender, YT, netYoIn);
134
+ if (isNeedToBurnYt) IERC20(YT).safeTransferFrom(msg.sender, YT, netYoIn);
135
+ }
136
+
137
+ IPYieldToken(YT).redeemYO(SCY);
138
+
139
+ netRawTokenOut = _redeemScyToRawToken(SCY, 0, minRawTokenOut, receiver, path, false);
140
+ }
141
+ }