@pendle/core-v2 0.4.0 → 0.5.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 (96) hide show
  1. package/contracts/SuperComposableYield/implementations/IRewardManager.sol +16 -0
  2. package/contracts/SuperComposableYield/implementations/RewardManager.sol +24 -5
  3. package/contracts/core/PendleMarket.sol +10 -18
  4. package/contracts/core/PendleMarketFactory.sol +49 -22
  5. package/contracts/core/PendleRouter.sol +74 -0
  6. package/contracts/core/PendleYieldToken.sol +20 -12
  7. package/contracts/core/{router/PendleRouterStaticUpg.sol → RouterStatic.sol} +6 -6
  8. package/contracts/core/actions/ActionCallback.sol +101 -0
  9. package/contracts/core/{router/PendleRouterCoreUpg.sol → actions/ActionCore.sol} +6 -10
  10. package/contracts/core/{router/PendleRouterYTUpg.sol → actions/ActionYT.sol} +6 -11
  11. package/contracts/core/{router/base/PendleRouterOTBaseUpg.sol → actions/base/ActionSCYAndOTBase.sol} +1 -5
  12. package/contracts/core/{router/base/PendleRouterSCYAndForgeBaseUpg.sol → actions/base/ActionSCYAndYOBase.sol} +3 -5
  13. package/contracts/core/{router/base/PendleRouterYTBaseUpg.sol → actions/base/ActionSCYAndYTBase.sol} +7 -99
  14. package/contracts/core/actions/base/ActionType.sol +11 -0
  15. package/contracts/interfaces/{IPRouterCore.sol → IPActionCore.sol} +1 -1
  16. package/contracts/interfaces/{IPRouterYT.sol → IPActionYT.sol} +1 -3
  17. package/contracts/interfaces/IPAllAction.sol +9 -0
  18. package/contracts/interfaces/IPMarketFactory.sol +11 -0
  19. package/contracts/interfaces/IPYieldToken.sol +21 -3
  20. package/contracts/libraries/math/MarketMathCore.sol +3 -2
  21. package/package.json +1 -1
  22. package/typechain-types/{PendleRouterYTBaseUpg.ts → ActionCallback.ts} +5 -5
  23. package/typechain-types/{PendleRouterCoreUpg.ts → ActionCore.ts} +5 -5
  24. package/typechain-types/{PendleRouterSCYAndForgeBaseUpg.ts → ActionSCYAndYOBase.ts} +5 -6
  25. package/typechain-types/{BoringOwnableData.ts → ActionSCYAndYTBase.ts} +21 -24
  26. package/typechain-types/{PendleRouterStaticUpg.ts → ActionStatic.ts} +5 -5
  27. package/typechain-types/{IPRouterYT.ts → ActionYT.ts} +27 -42
  28. package/typechain-types/IPActionAll.ts +1431 -0
  29. package/typechain-types/{IPRouterCore.ts → IPActionCore.ts} +5 -5
  30. package/typechain-types/{IPRouterView.ts → IPActionStatic.ts} +57 -5
  31. package/typechain-types/{PendleRouterYTUpg.ts → IPActionYT.ts} +5 -97
  32. package/typechain-types/IPAllAction.ts +1431 -0
  33. package/typechain-types/IPMarket.ts +3 -0
  34. package/typechain-types/IPMarketFactory.ts +46 -0
  35. package/typechain-types/IPYieldToken.ts +342 -14
  36. package/typechain-types/IRewardManager.ts +178 -0
  37. package/typechain-types/PendleAaveV3SCY.ts +70 -64
  38. package/typechain-types/PendleBenQiErc20SCY.ts +70 -64
  39. package/typechain-types/PendleMarket.ts +3 -59
  40. package/typechain-types/PendleMarketFactory.ts +150 -24
  41. package/typechain-types/{PendleRouterProxy.ts → PendleRouter.ts} +29 -39
  42. package/typechain-types/PendleYieldToken.ts +116 -101
  43. package/typechain-types/RewardManager.ts +48 -42
  44. package/typechain-types/RouterStatic.ts +828 -0
  45. package/typechain-types/SCYBaseWithRewards.ts +70 -64
  46. package/typechain-types/factories/ActionCallback__factory.ts +116 -0
  47. package/typechain-types/factories/ActionCore__factory.ts +632 -0
  48. package/typechain-types/factories/{PendleRouterSCYAndForgeBaseUpg__factory.ts → ActionSCYAndYOBase__factory.ts} +8 -12
  49. package/typechain-types/factories/ActionSCYAndYTBase__factory.ts +52 -0
  50. package/typechain-types/factories/ActionStatic__factory.ts +308 -0
  51. package/typechain-types/factories/ActionYT__factory.ts +370 -0
  52. package/typechain-types/factories/IPActionAll__factory.ts +983 -0
  53. package/typechain-types/factories/{IPRouterCore__factory.ts → IPActionCore__factory.ts} +6 -6
  54. package/typechain-types/factories/{IPRouterView__factory.ts → IPActionStatic__factory.ts} +38 -6
  55. package/typechain-types/factories/{IPRouterYT__factory.ts → IPActionYT__factory.ts} +6 -29
  56. package/typechain-types/factories/IPAllAction__factory.ts +983 -0
  57. package/typechain-types/factories/IPMarketFactory__factory.ts +28 -0
  58. package/typechain-types/factories/IPMarket__factory.ts +7 -2
  59. package/typechain-types/factories/IPYieldToken__factory.ts +158 -1
  60. package/typechain-types/factories/IRewardManager__factory.ts +92 -0
  61. package/typechain-types/factories/PendleAaveV3SCY__factory.ts +34 -34
  62. package/typechain-types/factories/PendleBenQiErc20SCY__factory.ts +34 -34
  63. package/typechain-types/factories/PendleBtrflyScy__factory.ts +1 -1
  64. package/typechain-types/factories/PendleMarketFactory__factory.ts +112 -17
  65. package/typechain-types/factories/PendleMarket__factory.ts +8 -69
  66. package/typechain-types/factories/PendleRouter__factory.ts +282 -0
  67. package/typechain-types/factories/PendleYearnVaultScy__factory.ts +1 -1
  68. package/typechain-types/factories/PendleYieldContractFactory__factory.ts +1 -1
  69. package/typechain-types/factories/PendleYieldToken__factory.ts +58 -58
  70. package/typechain-types/factories/RewardManager__factory.ts +18 -18
  71. package/typechain-types/factories/RouterStatic__factory.ts +883 -0
  72. package/typechain-types/factories/SCYBaseWithRewards__factory.ts +33 -33
  73. package/typechain-types/hardhat.d.ts +93 -75
  74. package/typechain-types/index.ts +22 -18
  75. package/contracts/core/router/PendleRouterProxy.sol +0 -84
  76. package/contracts/interfaces/IPFlashCallBack.sol +0 -10
  77. package/typechain-types/BoringOwnable.ts +0 -194
  78. package/typechain-types/BoringOwnableUpg.ts +0 -194
  79. package/typechain-types/BoringOwnableUpgData.ts +0 -100
  80. package/typechain-types/IPFlashCallback.ts +0 -115
  81. package/typechain-types/IPermissionsV2.ts +0 -87
  82. package/typechain-types/PendleRouterViewUpg.ts +0 -307
  83. package/typechain-types/PermissionsV2.ts +0 -87
  84. package/typechain-types/factories/BoringOwnableData__factory.ts +0 -90
  85. package/typechain-types/factories/BoringOwnableUpgData__factory.ts +0 -94
  86. package/typechain-types/factories/BoringOwnableUpg__factory.ts +0 -139
  87. package/typechain-types/factories/BoringOwnable__factory.ts +0 -149
  88. package/typechain-types/factories/IPFlashCallback__factory.ts +0 -49
  89. package/typechain-types/factories/IPermissionsV2__factory.ts +0 -39
  90. package/typechain-types/factories/PendleRouterCoreUpg__factory.ts +0 -635
  91. package/typechain-types/factories/PendleRouterProxy__factory.ts +0 -285
  92. package/typechain-types/factories/PendleRouterStaticUpg__factory.ts +0 -315
  93. package/typechain-types/factories/PendleRouterViewUpg__factory.ts +0 -265
  94. package/typechain-types/factories/PendleRouterYTBaseUpg__factory.ts +0 -66
  95. package/typechain-types/factories/PendleRouterYTUpg__factory.ts +0 -422
  96. package/typechain-types/factories/PermissionsV2__factory.ts +0 -36
@@ -0,0 +1,16 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ pragma solidity 0.8.9;
3
+
4
+ interface IRewardManager {
5
+ function getGlobalReward(address rewardToken)
6
+ external
7
+ view
8
+ returns (uint256 index, uint256 lastBalance);
9
+
10
+ function getUserReward(address user, address rewardToken)
11
+ external
12
+ view
13
+ returns (uint256 lastIndex, uint256 accruedReward);
14
+
15
+ function getRewardTokens() external view returns (address[] memory);
16
+ }
@@ -1,10 +1,11 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-or-later
2
2
  pragma solidity 0.8.9;
3
3
  import "../ISuperComposableYield.sol";
4
+ import "./IRewardManager.sol";
4
5
  import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
5
6
  import "../../libraries/math/Math.sol";
6
7
 
7
- abstract contract RewardManager {
8
+ abstract contract RewardManager is IRewardManager {
8
9
  using SafeERC20 for IERC20;
9
10
  using Math for uint256;
10
11
 
@@ -20,8 +21,28 @@ abstract contract RewardManager {
20
21
 
21
22
  uint256 internal constant INITIAL_REWARD_INDEX = 1;
22
23
 
23
- mapping(address => GlobalReward) public globalReward;
24
- mapping(address => mapping(address => UserReward)) public userReward;
24
+ mapping(address => GlobalReward) internal globalReward;
25
+ mapping(address => mapping(address => UserReward)) internal userReward;
26
+
27
+ function getGlobalReward(address rewardToken)
28
+ external
29
+ view
30
+ returns (uint256 index, uint256 lastBalance)
31
+ {
32
+ GlobalReward memory reward = globalReward[rewardToken];
33
+ return (reward.index, reward.lastBalance);
34
+ }
35
+
36
+ function getUserReward(address user, address rewardToken)
37
+ external
38
+ view
39
+ returns (uint256 lastIndex, uint256 accruedReward)
40
+ {
41
+ UserReward memory reward = userReward[user][rewardToken];
42
+ return (reward.lastIndex, reward.accruedReward);
43
+ }
44
+
45
+ function getRewardTokens() public view virtual override returns (address[] memory);
25
46
 
26
47
  function _doTransferOutRewardsForUser(address user, address receiver)
27
48
  internal
@@ -111,7 +132,5 @@ abstract contract RewardManager {
111
132
  }
112
133
  }
113
134
 
114
- function getRewardTokens() public view virtual returns (address[] memory);
115
-
116
135
  function _redeemExternalReward() internal virtual;
117
136
  }
@@ -34,31 +34,19 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
34
34
  address public immutable YT;
35
35
 
36
36
  int256 public immutable scalarRoot;
37
- uint256 public immutable feeRateRoot; // allow fee to be changable?
38
37
  int256 public immutable initialAnchor;
39
38
 
40
- uint256 public immutable rateOracleTimeWindow;
41
- int8 public immutable reserveFeePercent;
42
-
43
39
  MarketStorage public marketStorage;
44
40
 
45
41
  constructor(
46
42
  address _OT,
47
- uint256 _rateOracleTimeWindow,
48
- uint256 _feeRateRoot,
49
43
  int256 _scalarRoot,
50
- int256 _initialAnchor,
51
- uint8 _reserveFeePercent
44
+ int256 _initialAnchor
52
45
  ) PendleBaseToken(NAME, SYMBOL, 18, IPOwnershipToken(_OT).expiry()) {
53
46
  OT = _OT;
54
47
  SCY = IPOwnershipToken(_OT).SCY();
55
48
  YT = IPOwnershipToken(_OT).YT();
56
- feeRateRoot = _feeRateRoot;
57
49
  scalarRoot = _scalarRoot;
58
- rateOracleTimeWindow = _rateOracleTimeWindow;
59
-
60
- require(_reserveFeePercent <= 100, "invalid fee rate");
61
- reserveFeePercent = int8(_reserveFeePercent);
62
50
  initialAnchor = _initialAnchor;
63
51
  }
64
52
 
@@ -154,7 +142,7 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
154
142
  );
155
143
  require(netScyOut >= minScyOut, "insufficient scy out");
156
144
  IERC20(SCY).safeTransfer(receiver, netScyOut);
157
- IERC20(SCY).safeTransfer(IPMarketFactory(factory).treasury(), netScyToReserve);
145
+ IERC20(SCY).safeTransfer(market.treasury, netScyToReserve);
158
146
 
159
147
  if (data.length > 0) {
160
148
  IPMarketSwapCallback(msg.sender).swapCallback(exactOtIn.neg(), netScyOut.Int(), data);
@@ -183,7 +171,7 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
183
171
  );
184
172
  require(netScyIn <= maxScyIn, "scy in exceed limit");
185
173
  IERC20(OT).safeTransfer(receiver, exactOtOut);
186
- IERC20(SCY).safeTransfer(IPMarketFactory(factory).treasury(), netScyToReserve);
174
+ IERC20(SCY).safeTransfer(market.treasury, netScyToReserve);
187
175
 
188
176
  if (data.length > 0) {
189
177
  IPMarketSwapCallback(msg.sender).swapCallback(exactOtOut.Int(), netScyIn.neg(), data);
@@ -206,11 +194,15 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
206
194
  market.totalScy = store.totalScy;
207
195
  market.totalLp = totalSupply().Int();
208
196
  market.oracleRate = store.oracleRate;
209
- market.reserveFeePercent = reserveFeePercent;
197
+
198
+ (
199
+ market.treasury,
200
+ market.feeRateRoot,
201
+ market.rateOracleTimeWindow,
202
+ market.reserveFeePercent
203
+ ) = IPMarketFactory(factory).marketConfig();
210
204
 
211
205
  market.scalarRoot = scalarRoot;
212
- market.feeRateRoot = feeRateRoot;
213
- market.rateOracleTimeWindow = rateOracleTimeWindow;
214
206
  market.expiry = expiry;
215
207
 
216
208
  market.lastImpliedRate = store.lastImpliedRate;
@@ -10,24 +10,40 @@ import "./PendleMarket.sol";
10
10
  contract PendleMarketFactory is PermissionsV2Upg, IPMarketFactory {
11
11
  using EnumerableSet for EnumerableSet.AddressSet;
12
12
 
13
+ struct MarketConfig {
14
+ address treasury; // 160 bit
15
+ uint96 feeRateRoot; // 96 bit
16
+ // 1 SLOT
17
+ uint32 rateOracleTimeWindow;
18
+ uint8 reserveFeePercent;
19
+ }
20
+
13
21
  mapping(address => EnumerableSet.AddressSet) internal markets;
14
22
 
15
23
  address public immutable yieldContractFactory;
16
- address public treasury;
17
24
 
18
- constructor(address _governanceManager, address _yieldContractFactory)
19
- PermissionsV2Upg(_governanceManager)
20
- {
25
+ MarketConfig public marketConfig;
26
+
27
+ constructor(
28
+ address _governanceManager,
29
+ address _yieldContractFactory,
30
+ address _treasury,
31
+ uint96 _feeRateRoot,
32
+ uint32 _rateOracleTimeWindow,
33
+ uint8 _reserveFeePercent
34
+ ) PermissionsV2Upg(_governanceManager) {
21
35
  yieldContractFactory = _yieldContractFactory;
36
+
37
+ setTreasury(_treasury);
38
+ setFeeRateRoot(_feeRateRoot);
39
+ setRateOracleTimeWindow(_rateOracleTimeWindow);
40
+ setReserveFeePercent(_reserveFeePercent);
22
41
  }
23
42
 
24
43
  function createNewMarket(
25
44
  address OT,
26
- uint256 feeRateRoot,
27
45
  int256 scalarRoot,
28
- int256 initialAnchor,
29
- uint8 reserveFeePercent,
30
- uint256 rateOracleTimeWindow
46
+ int256 initialAnchor
31
47
  ) external returns (address market) {
32
48
  address SCY = IPOwnershipToken(OT).SCY();
33
49
  uint256 expiry = IPOwnershipToken(OT).expiry();
@@ -37,25 +53,36 @@ contract PendleMarketFactory is PermissionsV2Upg, IPMarketFactory {
37
53
  "INVALID_OT"
38
54
  );
39
55
 
40
- market = address(
41
- new PendleMarket(
42
- OT,
43
- rateOracleTimeWindow,
44
- feeRateRoot,
45
- scalarRoot,
46
- initialAnchor,
47
- reserveFeePercent
48
- )
49
- );
56
+ market = address(new PendleMarket(OT, scalarRoot, initialAnchor));
50
57
  markets[OT].add(market);
51
58
  }
52
59
 
53
- function setTreasury(address newTreasury) external onlyGovernance {
54
- treasury = newTreasury;
55
- }
56
-
57
60
  function isValidMarket(address market) external view returns (bool) {
58
61
  address OT = IPMarket(market).OT();
59
62
  return markets[OT].contains(market);
60
63
  }
64
+
65
+ function treasury() external view returns (address) {
66
+ return marketConfig.treasury;
67
+ }
68
+
69
+ function setTreasury(address newTreasury) public onlyGovernance {
70
+ require(newTreasury != address(0), "zero address");
71
+ marketConfig.treasury = newTreasury;
72
+ }
73
+
74
+ function setFeeRateRoot(uint96 newFeeRateRoot) public onlyGovernance {
75
+ // TODO: hard cap on the fee
76
+ marketConfig.feeRateRoot = newFeeRateRoot;
77
+ }
78
+
79
+ function setRateOracleTimeWindow(uint32 newRateOracleTimeWindow) public onlyGovernance {
80
+ // TODO: hard min for the time window
81
+ marketConfig.rateOracleTimeWindow = newRateOracleTimeWindow;
82
+ }
83
+
84
+ function setReserveFeePercent(uint8 newReserveFeePercent) public onlyGovernance {
85
+ require(newReserveFeePercent <= 100, "invalid fee rate");
86
+ marketConfig.reserveFeePercent = newReserveFeePercent;
87
+ }
61
88
  }
@@ -0,0 +1,74 @@
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 "@openzeppelin/contracts/proxy/Proxy.sol";
7
+ import "../interfaces/IPActionCore.sol";
8
+ import "../interfaces/IPActionYT.sol";
9
+ import "../interfaces/IPRouterStatic.sol";
10
+ import "../interfaces/IPMarketSwapCallback.sol";
11
+ import "../periphery/PermissionsV2Upg.sol";
12
+
13
+ /// @dev this contract will be deployed behind an ERC1967 proxy
14
+ /// calls to the ERC1967 proxy will be resolved at this contract, and proxied again to the
15
+ /// corresponding implementation contracts
16
+
17
+ // solhint-disable no-empty-blocks
18
+ contract PendleRouter is Proxy, Initializable, UUPSUpgradeable, PermissionsV2Upg {
19
+ address public immutable ACTION_CORE;
20
+ address public immutable ACTION_YT;
21
+ address public immutable ACTION_CALLBACK;
22
+
23
+ constructor(
24
+ address _ACTION_CORE,
25
+ address _ACTION_YT,
26
+ address _ACTION_CALLBACK,
27
+ address _governanceManager
28
+ ) PermissionsV2Upg(_governanceManager) initializer {
29
+ ACTION_CORE = _ACTION_CORE;
30
+ ACTION_YT = _ACTION_YT;
31
+ ACTION_CALLBACK = _ACTION_CALLBACK;
32
+ }
33
+
34
+ function initialize() external initializer {
35
+ __UUPSUpgradeable_init();
36
+ // no need to initialize PermissionsV2Upg
37
+ }
38
+
39
+ function getRouterImplementation(bytes4 sig) public view returns (address) {
40
+ if (
41
+ sig == IPActionCore.mintScyFromRawToken.selector ||
42
+ sig == IPActionCore.redeemScyToRawToken.selector ||
43
+ sig == IPActionCore.mintYoFromRawToken.selector ||
44
+ sig == IPActionCore.redeemYoToRawToken.selector ||
45
+ sig == IPActionCore.addLiquidity.selector ||
46
+ sig == IPActionCore.removeLiquidity.selector ||
47
+ sig == IPActionCore.swapExactOtForScy.selector ||
48
+ sig == IPActionCore.swapOtForExactScy.selector ||
49
+ sig == IPActionCore.swapScyForExactOt.selector ||
50
+ sig == IPActionCore.swapExactScyForOt.selector ||
51
+ sig == IPActionCore.swapExactRawTokenForOt.selector ||
52
+ sig == IPActionCore.swapExactOtForRawToken.selector
53
+ ) {
54
+ return ACTION_CORE;
55
+ } else if (
56
+ sig == IPActionYT.swapExactYtForScy.selector ||
57
+ sig == IPActionYT.swapScyForExactYt.selector ||
58
+ sig == IPActionYT.swapExactScyForYt.selector ||
59
+ sig == IPActionYT.swapExactRawTokenForYt.selector ||
60
+ sig == IPActionYT.swapExactYtForRawToken.selector
61
+ ) {
62
+ return ACTION_YT;
63
+ } else if (sig == IPMarketSwapCallback.swapCallback.selector) {
64
+ return ACTION_CALLBACK;
65
+ }
66
+ require(false, "invalid market sig");
67
+ }
68
+
69
+ function _implementation() internal view override returns (address) {
70
+ return getRouterImplementation(msg.sig);
71
+ }
72
+
73
+ function _authorizeUpgrade(address newImplementation) internal override onlyGovernance {}
74
+ }
@@ -19,11 +19,11 @@ It has been proven and tested that impliedScyBalance will not change over time,
19
19
 
20
20
  Due to this, it is required to update users' accruedReward STRICTLY BEFORE redeeming their interest.
21
21
  */
22
- contract PendleYieldToken is PendleBaseToken, IPYieldToken, RewardManager {
22
+ contract PendleYieldToken is PendleBaseToken, RewardManager, IPYieldToken {
23
23
  using Math for uint256;
24
24
  using SafeERC20 for IERC20;
25
25
 
26
- struct UserData {
26
+ struct InterestData {
27
27
  uint256 lastScyIndex;
28
28
  uint256 dueInterest;
29
29
  }
@@ -40,7 +40,7 @@ contract PendleYieldToken is PendleBaseToken, IPYieldToken, RewardManager {
40
40
  mapping(address => uint256) public totalRewardsPostExpiry;
41
41
  uint256 public totalProtocolFee;
42
42
 
43
- mapping(address => UserData) public data;
43
+ mapping(address => InterestData) internal interestData;
44
44
 
45
45
  constructor(
46
46
  address _SCY,
@@ -118,13 +118,13 @@ contract PendleYieldToken is PendleBaseToken, IPYieldToken, RewardManager {
118
118
  }
119
119
 
120
120
  function updateUserInterest(address user) public {
121
- uint256 prevIndex = data[user].lastScyIndex;
121
+ uint256 prevIndex = interestData[user].lastScyIndex;
122
122
 
123
123
  uint256 currentIndex = getScyIndexBeforeExpiry();
124
124
 
125
125
  if (prevIndex == currentIndex) return;
126
126
  if (prevIndex == 0) {
127
- data[user].lastScyIndex = currentIndex;
127
+ interestData[user].lastScyIndex = currentIndex;
128
128
  return;
129
129
  }
130
130
 
@@ -134,8 +134,16 @@ contract PendleYieldToken is PendleBaseToken, IPYieldToken, RewardManager {
134
134
  prevIndex * currentIndex
135
135
  );
136
136
 
137
- data[user].dueInterest += interestFromYT;
138
- data[user].lastScyIndex = currentIndex;
137
+ interestData[user].dueInterest += interestFromYT;
138
+ interestData[user].lastScyIndex = currentIndex;
139
+ }
140
+
141
+ function getInterestData(address user)
142
+ external
143
+ view
144
+ returns (uint256 lastScyIndex, uint256 dueInterest)
145
+ {
146
+ return (interestData[user].lastScyIndex, interestData[user].dueInterest);
139
147
  }
140
148
 
141
149
  function _updateGlobalReward(address[] memory rewardTokens, uint256 totalSupply)
@@ -165,8 +173,8 @@ contract PendleYieldToken is PendleBaseToken, IPYieldToken, RewardManager {
165
173
  }
166
174
 
167
175
  function _doTransferOutDueInterest(address user) internal returns (uint256 interestOut) {
168
- uint256 interestPreFee = data[user].dueInterest;
169
- data[user].dueInterest = 0;
176
+ uint256 interestPreFee = interestData[user].dueInterest;
177
+ interestData[user].dueInterest = 0;
170
178
 
171
179
  uint256 feeRate = IPYieldContractFactory(factory).interestFeeRate();
172
180
  uint256 feeAmount = interestPreFee.mulDown(feeRate);
@@ -185,7 +193,7 @@ contract PendleYieldToken is PendleBaseToken, IPYieldToken, RewardManager {
185
193
  public
186
194
  view
187
195
  virtual
188
- override(RewardManager)
196
+ override(RewardManager, IRewardManager)
189
197
  returns (address[] memory)
190
198
  {
191
199
  return ISuperComposableYield(SCY).getRewardTokens();
@@ -247,9 +255,9 @@ contract PendleYieldToken is PendleBaseToken, IPYieldToken, RewardManager {
247
255
  }
248
256
 
249
257
  function getImpliedScyBalance(address user) public view returns (uint256) {
250
- uint256 scyIndex = data[user].lastScyIndex;
258
+ uint256 scyIndex = interestData[user].lastScyIndex;
251
259
  if (scyIndex == 0) return 0;
252
- return SCYUtils.assetToScy(scyIndex, balanceOf(user)) + data[user].dueInterest;
260
+ return SCYUtils.assetToScy(scyIndex, balanceOf(user)) + interestData[user].dueInterest;
253
261
  }
254
262
 
255
263
  function _beforeTokenTransfer(
@@ -1,15 +1,15 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-or-later
2
2
  pragma solidity 0.8.9;
3
3
 
4
- import "../../interfaces/IPRouterStatic.sol";
5
- import "../../interfaces/IPMarket.sol";
6
- import "../../interfaces/IPYieldContractFactory.sol";
7
- import "../../interfaces/IPMarketFactory.sol";
8
- import "../../libraries/math/MarketMathAux.sol";
4
+ import "../interfaces/IPRouterStatic.sol";
5
+ import "../interfaces/IPMarket.sol";
6
+ import "../interfaces/IPYieldContractFactory.sol";
7
+ import "../interfaces/IPMarketFactory.sol";
8
+ import "../libraries/math/MarketMathAux.sol";
9
9
  import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
10
10
  import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
11
11
 
12
- contract PendleRouterStaticUpg is IPRouterStatic {
12
+ contract RouterStatic is IPRouterStatic {
13
13
  using MarketMathCore for MarketState;
14
14
  using MarketMathAux for MarketState;
15
15
  using Math for uint256;
@@ -0,0 +1,101 @@
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 "../../SuperComposableYield/SCYUtils.sol";
9
+ import "../../libraries/math/MarketApproxLib.sol";
10
+ import "../../libraries/math/MarketMathAux.sol";
11
+ import "./base/ActionSCYAndYOBase.sol";
12
+ import "./base/ActionType.sol";
13
+ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
14
+
15
+ contract ActionCallback is IPMarketSwapCallback, ActionType {
16
+ address public immutable marketFactory;
17
+ using Math for int256;
18
+ using Math for uint256;
19
+ using SafeERC20 for ISuperComposableYield;
20
+ using SafeERC20 for IPYieldToken;
21
+
22
+ modifier onlyPendleMarket(address market) {
23
+ require(IPMarketFactory(marketFactory).isValidMarket(market), "INVALID_MARKET");
24
+ _;
25
+ }
26
+
27
+ /// @dev since this contract will be proxied, it must not contains non-immutable variables
28
+ constructor(address _marketFactory) {
29
+ marketFactory = _marketFactory;
30
+ }
31
+
32
+ function swapCallback(
33
+ int256 otToAccount,
34
+ int256 scyToAccount,
35
+ bytes calldata data
36
+ ) external override onlyPendleMarket(msg.sender) {
37
+ (ACTION_TYPE swapType, ) = abi.decode(data, (ACTION_TYPE, bytes));
38
+
39
+ if (swapType == ACTION_TYPE.SwapExactScyForYt) {
40
+ _swapExactScyForYt_callback(msg.sender, data);
41
+ } else if (swapType == ACTION_TYPE.SwapSCYForExactYt) {
42
+ _swapScyForExactYt_callback(msg.sender, otToAccount, scyToAccount, data);
43
+ } else if (
44
+ swapType == ACTION_TYPE.SwapYtForExactScy || swapType == ACTION_TYPE.SwapExactYtForScy
45
+ ) {
46
+ _swapYtForScy_callback(msg.sender, scyToAccount, data);
47
+ } else {
48
+ require(false, "unknown swapType");
49
+ }
50
+ }
51
+
52
+ function _swapExactScyForYt_callback(address market, bytes calldata data) internal {
53
+ (, , IPYieldToken YT) = IPMarket(market).readTokens();
54
+ (, address receiver) = abi.decode(data, (ACTION_TYPE, address));
55
+
56
+ YT.mintYO(market, receiver);
57
+ }
58
+
59
+ function _swapScyForExactYt_callback(
60
+ address market,
61
+ int256 otToAccount,
62
+ int256 scyToAccount,
63
+ bytes calldata data
64
+ ) internal {
65
+ (, address payer, address receiver) = abi.decode(data, (ACTION_TYPE, address, address));
66
+ (ISuperComposableYield SCY, , IPYieldToken YT) = IPMarket(market).readTokens();
67
+
68
+ uint256 otOwed = otToAccount.neg().Uint();
69
+ uint256 scyReceived = scyToAccount.Uint();
70
+
71
+ // otOwed = totalAsset
72
+ uint256 scyNeedTotal = SCYUtils.assetToScy(SCY.scyIndexCurrent(), otOwed);
73
+
74
+ uint256 netScyToPull = scyNeedTotal.subMax0(scyReceived);
75
+ SCY.safeTransferFrom(payer, address(YT), netScyToPull);
76
+
77
+ YT.mintYO(market, receiver);
78
+ }
79
+
80
+ /**
81
+ @dev receive OT -> pair with YT to redeem SCY -> payback SCY
82
+ */
83
+ function _swapYtForScy_callback(
84
+ address market,
85
+ int256 scyToAccount,
86
+ bytes calldata data
87
+ ) internal {
88
+ (, address receiver) = abi.decode(data, (ACTION_TYPE, address));
89
+ (ISuperComposableYield SCY, , IPYieldToken YT) = IPMarket(market).readTokens();
90
+
91
+ uint256 scyOwed = scyToAccount.neg().Uint();
92
+
93
+ uint256 netScyReceived = YT.redeemYO(address(this));
94
+
95
+ SCY.safeTransfer(market, scyOwed);
96
+
97
+ if (receiver != address(this)) {
98
+ SCY.safeTransfer(receiver, netScyReceived - scyOwed);
99
+ }
100
+ }
101
+ }
@@ -1,18 +1,14 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-or-later
2
2
  pragma solidity 0.8.9;
3
3
 
4
- import "./base/PendleRouterSCYAndForgeBaseUpg.sol";
5
- import "./base/PendleRouterOTBaseUpg.sol";
4
+ import "./base/ActionSCYAndOTBase.sol";
5
+ import "./base/ActionSCYAndYOBase.sol";
6
6
  import "../../interfaces/IPOwnershipToken.sol";
7
7
  import "../../interfaces/IPYieldToken.sol";
8
- import "../../interfaces/IPRouterCore.sol";
8
+ import "../../interfaces/IPActionCore.sol";
9
9
  import "../../libraries/math/MarketMathAux.sol";
10
10
 
11
- contract PendleRouterCoreUpg is
12
- IPRouterCore,
13
- PendleRouterSCYAndForgeBaseUpg,
14
- PendleRouterOTBaseUpg
15
- {
11
+ contract ActionCore is IPActionCore, ActionSCYAndOTBase, ActionSCYAndYOBase {
16
12
  using MarketMathCore for MarketState;
17
13
  using MarketMathAux for MarketState;
18
14
  using Math for uint256;
@@ -24,8 +20,8 @@ contract PendleRouterCoreUpg is
24
20
  address _joeFactory,
25
21
  address _marketFactory
26
22
  )
27
- PendleRouterSCYAndForgeBaseUpg(_joeRouter, _joeFactory)
28
- PendleRouterOTBaseUpg()
23
+ ActionSCYAndYOBase(_joeRouter, _joeFactory)
24
+ ActionSCYAndOTBase()
29
25
  //solhint-disable-next-line no-empty-blocks
30
26
  {
31
27
 
@@ -1,27 +1,22 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-or-later
2
2
  pragma solidity 0.8.9;
3
3
 
4
- import "./base/PendleRouterSCYAndForgeBaseUpg.sol";
5
- import "./base/PendleRouterYTBaseUpg.sol";
4
+ import "./base/ActionSCYAndYTBase.sol";
6
5
  import "../../interfaces/IPOwnershipToken.sol";
7
6
  import "../../interfaces/IPYieldToken.sol";
8
- import "../../interfaces/IPRouterYT.sol";
7
+ import "../../interfaces/IPActionYT.sol";
9
8
  import "../../libraries/math/MarketMathAux.sol";
10
9
 
11
- contract PendleRouterYTUpg is IPRouterYT, PendleRouterSCYAndForgeBaseUpg, PendleRouterYTBaseUpg {
10
+ contract ActionYT is IPActionYT, ActionSCYAndYTBase {
12
11
  using MarketMathCore for MarketState;
13
12
  using MarketMathAux for MarketState;
14
13
  using Math for uint256;
15
14
  using Math for int256;
16
15
 
17
16
  /// @dev since this contract will be proxied, it must not contains non-immutable variables
18
- constructor(
19
- address _joeRouter,
20
- address _joeFactory,
21
- address _marketFactory
22
- )
23
- PendleRouterSCYAndForgeBaseUpg(_joeRouter, _joeFactory)
24
- PendleRouterYTBaseUpg(_marketFactory)
17
+ constructor(address _joeRouter, address _joeFactory)
18
+ ActionSCYAndYOBase(_joeRouter, _joeFactory)
19
+ ActionSCYAndYTBase()
25
20
  //solhint-disable-next-line no-empty-blocks
26
21
  {
27
22
 
@@ -9,7 +9,7 @@ import "../../../libraries/math/MarketApproxLib.sol";
9
9
  import "../../../libraries/math/MarketMathAux.sol";
10
10
  import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
11
11
 
12
- abstract contract PendleRouterOTBaseUpg {
12
+ abstract contract ActionSCYAndOTBase {
13
13
  using Math for uint256;
14
14
  using Math for int256;
15
15
  using MarketMathCore for MarketState;
@@ -18,10 +18,6 @@ abstract contract PendleRouterOTBaseUpg {
18
18
  using SafeERC20 for IERC20;
19
19
 
20
20
  /// @dev since this contract will be proxied, it must not contains non-immutable variables
21
- constructor() //solhint-disable-next-line no-empty-blocks
22
- {
23
-
24
- }
25
21
 
26
22
  /**
27
23
  * @notice addLiquidity to the market, using both SCY & OT, the receiver will receive LP before
@@ -6,16 +6,14 @@ import "../../../periphery/PendleJoeSwapHelperUpg.sol";
6
6
  import "../../../SuperComposableYield/ISuperComposableYield.sol";
7
7
  import "../../../interfaces/IPYieldToken.sol";
8
8
 
9
- abstract contract PendleRouterSCYAndForgeBaseUpg is PendleJoeSwapHelperUpg {
9
+ // solhint-disable no-empty-blocks
10
+ abstract contract ActionSCYAndYOBase is PendleJoeSwapHelperUpg {
10
11
  using SafeERC20 for IERC20;
11
12
 
12
13
  /// @dev since this contract will be proxied, it must not contains non-immutable variables
13
14
  constructor(address _joeRouter, address _joeFactory)
14
15
  PendleJoeSwapHelperUpg(_joeRouter, _joeFactory)
15
- // solhint-disable-next-line no-empty-blocks
16
- {
17
-
18
- }
16
+ {}
19
17
 
20
18
  /**
21
19
  * @notice swap rawToken to baseToken -> baseToken to mint SCY