@pendle/core-v2 0.5.1-beta-5 → 0.6.2

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 (54) hide show
  1. package/contracts/SuperComposableYield/ISuperComposableYield.sol +2 -0
  2. package/contracts/SuperComposableYield/implementations/RewardManager.sol +35 -20
  3. package/contracts/SuperComposableYield/implementations/SCYBase.sol +39 -19
  4. package/contracts/SuperComposableYield/implementations/SCYBaseWithRewards.sol +26 -14
  5. package/contracts/core/PendleBaseToken.sol +2 -2
  6. package/contracts/core/PendleMarket.sol +145 -61
  7. package/contracts/core/PendleMarketFactory.sol +30 -19
  8. package/contracts/core/{PendleOwnershipToken.sol → PendlePrincipalToken.sol} +14 -2
  9. package/contracts/core/PendleRouter.sol +23 -9
  10. package/contracts/core/PendleSCYImpl/AaveV3/PendleAaveV3SCY.sol +21 -20
  11. package/contracts/core/PendleSCYImpl/PendleBenQiErc20SCY.sol +22 -16
  12. package/contracts/core/PendleSCYImpl/PendleBtrflySCY.sol +13 -13
  13. package/contracts/core/PendleSCYImpl/PendleStETHSCY.sol +107 -0
  14. package/contracts/core/PendleSCYImpl/PendleYearnVaultSCY.sol +14 -15
  15. package/contracts/core/PendleYieldContractFactory.sol +29 -14
  16. package/contracts/core/PendleYieldToken.sol +130 -76
  17. package/contracts/core/RouterStatic.sol +51 -51
  18. package/contracts/core/actions/ActionCallback.sol +36 -18
  19. package/contracts/core/actions/ActionCore.sol +41 -88
  20. package/contracts/core/actions/ActionRedeem.sol +36 -0
  21. package/contracts/core/actions/ActionYT.sol +41 -59
  22. package/contracts/core/actions/base/{ActionSCYAndOTBase.sol → ActionSCYAndPTBase.sol} +59 -45
  23. package/contracts/core/actions/base/{ActionSCYAndYOBase.sol → ActionSCYAndPYBase.sol} +57 -19
  24. package/contracts/core/actions/base/ActionSCYAndYTBase.sol +31 -21
  25. package/contracts/interfaces/IPActionCore.sol +21 -28
  26. package/contracts/interfaces/IPActionRedeem.sol +17 -0
  27. package/contracts/interfaces/IPActionYT.sol +5 -12
  28. package/contracts/interfaces/IPAllAction.sol +2 -2
  29. package/contracts/interfaces/IPMarket.sol +33 -10
  30. package/contracts/interfaces/IPMarketAddRemoveCallback.sol +2 -2
  31. package/contracts/interfaces/IPMarketFactory.sol +3 -1
  32. package/contracts/interfaces/IPMarketSwapCallback.sol +1 -1
  33. package/contracts/interfaces/{IPOwnershipToken.sol → IPPrincipalToken.sol} +1 -1
  34. package/contracts/interfaces/IPRouterStatic.sol +19 -19
  35. package/contracts/interfaces/IPYieldContractFactory.sol +10 -2
  36. package/contracts/interfaces/IPYieldToken.sol +14 -5
  37. package/contracts/interfaces/IWstETH.sol +10 -0
  38. package/contracts/libraries/JoeLibrary.sol +1 -1
  39. package/contracts/libraries/math/LogExpMath.sol +1 -1
  40. package/contracts/libraries/math/MarketApproxLib.sol +128 -88
  41. package/contracts/libraries/math/MarketMathAux.sol +13 -13
  42. package/contracts/libraries/math/MarketMathCore.sol +62 -93
  43. package/contracts/libraries/math/Math.sol +14 -2
  44. package/contracts/periphery/PendleGovernanceManager.sol +5 -3
  45. package/package.json +3 -2
  46. package/typechain-types/IPRouterStatic.ts +480 -0
  47. package/typechain-types/RouterStatic.ts +484 -4
  48. package/typechain-types/factories/IPRouterStatic__factory.ts +616 -0
  49. package/typechain-types/factories/PendleRouter__factory.ts +1 -1
  50. package/typechain-types/factories/RouterStatic__factory.ts +619 -3
  51. package/typechain-types/ActionSCYAndYOBase.ts +0 -223
  52. package/typechain-types/PendleRouterRedeemUpg.ts +0 -125
  53. package/typechain-types/factories/ActionSCYAndYOBase__factory.ts +0 -200
  54. package/typechain-types/factories/PendleRouterRedeemUpg__factory.ts +0 -112
@@ -1,6 +1,5 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-or-later
2
2
  pragma solidity 0.8.9;
3
- pragma abicoder v2;
4
3
  import "../../../SuperComposableYield/implementations/SCYBaseWithRewards.sol";
5
4
  import "../../../interfaces/IAToken.sol";
6
5
  import "../../../interfaces/IAavePool.sol";
@@ -8,6 +7,7 @@ import "../../../interfaces/IAaveRewardsController.sol";
8
7
  import "./WadRayMath.sol";
9
8
 
10
9
  contract PendleAaveV3SCY is SCYBaseWithRewards {
10
+ using Math for uint256;
11
11
  using WadRayMath for uint256;
12
12
  using SafeERC20 for IERC20;
13
13
 
@@ -17,24 +17,24 @@ contract PendleAaveV3SCY is SCYBaseWithRewards {
17
17
  address public immutable aToken;
18
18
 
19
19
  uint256 public lastScyIndex;
20
+ uint256 public constant PRECISION_INDEX = 1e9;
20
21
 
21
- // WIP: Aave reward controller can config to have more rewardsToken,
22
- // hence rewardsLength should not be immutable
23
22
  constructor(
24
23
  string memory _name,
25
24
  string memory _symbol,
26
25
  uint8 __scydecimals,
27
26
  uint8 __assetDecimals,
27
+ bytes32 __assetId,
28
28
  address _aavePool,
29
29
  address _underlying,
30
30
  address _aToken,
31
31
  address _rewardsController
32
- ) SCYBaseWithRewards(_name, _symbol, __scydecimals, __assetDecimals) {
32
+ ) SCYBaseWithRewards(_name, _symbol, __scydecimals, __assetDecimals, __assetId) {
33
33
  aToken = _aToken;
34
34
  pool = _aavePool;
35
35
  underlying = _underlying;
36
36
  rewardsController = _rewardsController;
37
- IERC20(underlying).safeIncreaseAllowance(aToken, type(uint256).max);
37
+ IERC20(underlying).safeIncreaseAllowance(pool, type(uint256).max);
38
38
  }
39
39
 
40
40
  /*///////////////////////////////////////////////////////////////
@@ -49,7 +49,7 @@ contract PendleAaveV3SCY is SCYBaseWithRewards {
49
49
  {
50
50
  // aTokenScaled -> scy is 1:1
51
51
  if (token == aToken) {
52
- amountScyOut = amountBase.rayDiv(scyIndexCurrent());
52
+ amountScyOut = amountBase;
53
53
  } else {
54
54
  IAavePool(pool).supply(underlying, amountBase, address(this), 0);
55
55
  _afterSendToken(underlying);
@@ -64,9 +64,9 @@ contract PendleAaveV3SCY is SCYBaseWithRewards {
64
64
  returns (uint256 amountBaseOut)
65
65
  {
66
66
  if (token == aToken) {
67
- amountBaseOut = amountScy.rayMul(scyIndexCurrent());
67
+ amountBaseOut = amountScy.rayMul(aaveIndexCurrent());
68
68
  } else {
69
- uint256 amountBaseExpected = amountScy.rayMul(scyIndexCurrent());
69
+ uint256 amountBaseExpected = amountScy.rayMul(aaveIndexCurrent());
70
70
  IAavePool(pool).withdraw(underlying, amountBaseExpected, address(this));
71
71
  _afterSendToken(aToken);
72
72
  amountBaseOut = _afterReceiveToken(token);
@@ -78,9 +78,14 @@ contract PendleAaveV3SCY is SCYBaseWithRewards {
78
78
  //////////////////////////////////////////////////////////////*/
79
79
 
80
80
  function scyIndexCurrent() public virtual override returns (uint256 res) {
81
+ aaveIndexCurrent();
82
+ res = lastScyIndex;
83
+ emit UpdateScyIndex(lastScyIndex);
84
+ }
85
+
86
+ function aaveIndexCurrent() public returns (uint256 res) {
81
87
  res = IAavePool(pool).getReserveNormalizedIncome(underlying);
82
- lastScyIndex = res;
83
- return res;
88
+ lastScyIndex = res / PRECISION_INDEX;
84
89
  }
85
90
 
86
91
  function scyIndexStored() public view override returns (uint256 res) {
@@ -88,7 +93,7 @@ contract PendleAaveV3SCY is SCYBaseWithRewards {
88
93
  }
89
94
 
90
95
  function getRewardTokens() public view override returns (address[] memory res) {
91
- return IAaveRewardsController(rewardsController).getRewardsByAsset(aToken);
96
+ res = IAaveRewardsController(rewardsController).getRewardsByAsset(aToken);
92
97
  }
93
98
 
94
99
  /*///////////////////////////////////////////////////////////////
@@ -118,15 +123,11 @@ contract PendleAaveV3SCY is SCYBaseWithRewards {
118
123
 
119
124
  /// @dev balance of aToken is saved by scaledBalanceOf instead
120
125
  function _afterReceiveToken(address token) internal virtual override returns (uint256 res) {
121
- if (token == aToken) {
122
- uint256 curBalance = IAToken(aToken).scaledBalanceOf(address(this));
123
- res = (curBalance - lastBalanceOf[token]).rayMul(scyIndexCurrent());
124
- lastBalanceOf[token] = curBalance;
125
- } else {
126
- uint256 curBalance = IERC20(token).balanceOf(address(this));
127
- res = curBalance - lastBalanceOf[token];
128
- lastBalanceOf[token] = curBalance;
129
- }
126
+ uint256 curBalance = (token == aToken)
127
+ ? IAToken(aToken).scaledBalanceOf(address(this))
128
+ : IERC20(token).balanceOf(address(this));
129
+ res = curBalance - lastBalanceOf[token];
130
+ lastBalanceOf[token] = curBalance;
130
131
  }
131
132
 
132
133
  function _afterSendToken(address token) internal virtual override {
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-or-later
2
2
  pragma solidity 0.8.9;
3
- pragma abicoder v2;
3
+
4
4
  import "../../SuperComposableYield/implementations/SCYBaseWithRewards.sol";
5
5
  import "../../interfaces/IQiErc20.sol";
6
6
  import "../../interfaces/IBenQiComptroller.sol";
@@ -15,24 +15,32 @@ contract PendleBenQiErc20SCY is SCYBaseWithRewards {
15
15
  address public immutable comptroller;
16
16
  address public immutable qiToken;
17
17
 
18
- uint256 public lastScyIndex;
18
+ uint256 public override scyIndexStored;
19
19
 
20
20
  constructor(
21
21
  string memory _name,
22
22
  string memory _symbol,
23
23
  uint8 __scydecimals,
24
24
  uint8 __assetDecimals,
25
+ bytes32 __assetId,
25
26
  address _underlying,
26
27
  address _qiToken,
27
28
  address _comptroller,
28
29
  address _QI,
29
30
  address _WAVAX
30
- ) SCYBaseWithRewards(_name, _symbol, __scydecimals, __assetDecimals) {
31
- underlying = _underlying;
31
+ ) SCYBaseWithRewards(_name, _symbol, __scydecimals, __assetDecimals, __assetId) {
32
+ require(
33
+ _qiToken != address(0) &&
34
+ _QI != address(0) &&
35
+ _WAVAX != address(0) &&
36
+ _comptroller != address(0),
37
+ "zero address"
38
+ );
32
39
  qiToken = _qiToken;
33
40
  QI = _QI;
34
41
  WAVAX = _WAVAX;
35
42
  comptroller = _comptroller;
43
+ underlying = _underlying;
36
44
  IERC20(underlying).safeIncreaseAllowance(qiToken, type(uint256).max);
37
45
  }
38
46
 
@@ -53,7 +61,8 @@ contract PendleBenQiErc20SCY is SCYBaseWithRewards {
53
61
  if (token == qiToken) {
54
62
  amountScyOut = amountBase;
55
63
  } else {
56
- IQiErc20(qiToken).mint(amountBase);
64
+ uint256 errCode = IQiErc20(qiToken).mint(amountBase);
65
+ require(errCode == 0, "mint failed");
57
66
  _afterSendToken(underlying);
58
67
  amountScyOut = _afterReceiveToken(qiToken);
59
68
  }
@@ -69,7 +78,8 @@ contract PendleBenQiErc20SCY is SCYBaseWithRewards {
69
78
  amountBaseOut = amountScy;
70
79
  } else {
71
80
  // must be underlying
72
- IQiErc20(qiToken).redeem(amountScy);
81
+ uint256 errCode = IQiErc20(qiToken).redeem(amountScy);
82
+ require(errCode == 0, "redeem failed");
73
83
  _afterSendToken(qiToken);
74
84
  amountBaseOut = _afterReceiveToken(underlying);
75
85
  }
@@ -79,14 +89,10 @@ contract PendleBenQiErc20SCY is SCYBaseWithRewards {
79
89
  SCY-INDEX
80
90
  //////////////////////////////////////////////////////////////*/
81
91
 
82
- function scyIndexCurrent() public virtual override returns (uint256 res) {
83
- res = Math.max(lastScyIndex, IQiToken(qiToken).exchangeRateCurrent());
84
- lastScyIndex = res;
85
- return res;
86
- }
87
-
88
- function scyIndexStored() public view override returns (uint256 res) {
89
- res = lastScyIndex;
92
+ function scyIndexCurrent() public virtual override returns (uint256) {
93
+ scyIndexStored = IQiToken(qiToken).exchangeRateCurrent();
94
+ emit UpdateScyIndex(scyIndexStored);
95
+ return scyIndexStored;
90
96
  }
91
97
 
92
98
  function getRewardTokens() public view override returns (address[] memory res) {
@@ -105,8 +111,8 @@ contract PendleBenQiErc20SCY is SCYBaseWithRewards {
105
111
  res[1] = underlying;
106
112
  }
107
113
 
108
- function isValidBaseToken(address token) public view virtual override returns (bool res) {
109
- res = (token == underlying || token == qiToken);
114
+ function isValidBaseToken(address token) public view virtual override returns (bool) {
115
+ return token == underlying || token == qiToken;
110
116
  }
111
117
 
112
118
  /*///////////////////////////////////////////////////////////////
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-or-later
2
2
  pragma solidity 0.8.9;
3
- pragma abicoder v2;
3
+
4
4
  import "../../SuperComposableYield/implementations/SCYBase.sol";
5
5
  import "../../interfaces/IWXBTRFLY.sol";
6
6
  import "../../interfaces/IREDACTEDStaking.sol";
@@ -12,17 +12,19 @@ contract PendleBtrflyScy is SCYBase {
12
12
  address public immutable xBTRFLY;
13
13
  address public immutable wxBTRFLY;
14
14
 
15
- uint256 public lastScyIndex;
15
+ uint256 public override scyIndexStored;
16
16
 
17
17
  constructor(
18
18
  string memory _name,
19
19
  string memory _symbol,
20
20
  uint8 __scydecimals,
21
21
  uint8 __assetDecimals,
22
+ bytes32 __assetId,
22
23
  address _BTRFLY,
23
24
  address _xBTRFLY,
24
25
  address _wxBTRFLY
25
- ) SCYBase(_name, _symbol, __scydecimals, __assetDecimals) {
26
+ ) SCYBase(_name, _symbol, __scydecimals, __assetDecimals, __assetId) {
27
+ require(_wxBTRFLY != address(0), "zero address");
26
28
  BTRFLY = _BTRFLY;
27
29
  xBTRFLY = _xBTRFLY;
28
30
  wxBTRFLY = _wxBTRFLY;
@@ -42,9 +44,11 @@ contract PendleBtrflyScy is SCYBase {
42
44
  if (token == BTRFLY) {
43
45
  amountScyOut = IWXBTRFLY(wxBTRFLY).wrapFromBTRFLY(amountBase);
44
46
  _afterSendToken(BTRFLY);
47
+ _afterReceiveToken(wxBTRFLY);
45
48
  } else if (token == xBTRFLY) {
46
49
  amountScyOut = IWXBTRFLY(wxBTRFLY).wrapFromxBTRFLY(amountBase);
47
50
  _afterSendToken(xBTRFLY);
51
+ _afterReceiveToken(wxBTRFLY);
48
52
  } else {
49
53
  // 1 wxBTRFLY = 1 SCY
50
54
  amountScyOut = amountBase;
@@ -73,14 +77,10 @@ contract PendleBtrflyScy is SCYBase {
73
77
  SCY-INDEX
74
78
  //////////////////////////////////////////////////////////////*/
75
79
 
76
- function scyIndexCurrent() public virtual override returns (uint256 res) {
77
- res = Math.max(lastScyIndex, IWXBTRFLY(wxBTRFLY).xBTRFLYValue(Math.ONE));
78
- lastScyIndex = res;
79
- return res;
80
- }
81
-
82
- function scyIndexStored() public view override returns (uint256 res) {
83
- res = lastScyIndex;
80
+ function scyIndexCurrent() public virtual override returns (uint256) {
81
+ scyIndexStored = IWXBTRFLY(wxBTRFLY).xBTRFLYValue(Math.ONE);
82
+ emit UpdateScyIndex(scyIndexStored);
83
+ return scyIndexStored;
84
84
  }
85
85
 
86
86
  /*///////////////////////////////////////////////////////////////
@@ -94,8 +94,8 @@ contract PendleBtrflyScy is SCYBase {
94
94
  res[2] = wxBTRFLY;
95
95
  }
96
96
 
97
- function isValidBaseToken(address token) public view virtual override returns (bool res) {
98
- res = (token == BTRFLY || token == xBTRFLY || token == wxBTRFLY);
97
+ function isValidBaseToken(address token) public view virtual override returns (bool) {
98
+ return token == BTRFLY || token == xBTRFLY || token == wxBTRFLY;
99
99
  }
100
100
 
101
101
  /*///////////////////////////////////////////////////////////////
@@ -0,0 +1,107 @@
1
+ // SPDX-License-Identifier: GPL-3.0-or-later
2
+ pragma solidity 0.8.9;
3
+ import "../../SuperComposableYield/implementations/SCYBase.sol";
4
+ import "../../interfaces/IWstETH.sol";
5
+
6
+ contract PendleStEthSCY is SCYBase {
7
+ using SafeERC20 for IERC20;
8
+
9
+ address public immutable stETH;
10
+ address public immutable wstETH;
11
+
12
+ uint256 public override scyIndexStored;
13
+
14
+ constructor(
15
+ string memory _name,
16
+ string memory _symbol,
17
+ uint8 __scydecimals,
18
+ uint8 __assetDecimals,
19
+ address _stETH,
20
+ address _wstETH,
21
+ bytes32 __assetId
22
+ ) SCYBase(_name, _symbol, __scydecimals, __assetDecimals, __assetId) {
23
+ require(_wstETH != address(0), "zero address");
24
+ stETH = _stETH;
25
+ wstETH = _wstETH;
26
+ IERC20(stETH).safeIncreaseAllowance(wstETH, type(uint256).max);
27
+ }
28
+
29
+ /*///////////////////////////////////////////////////////////////
30
+ DEPOSIT/REDEEM USING BASE TOKENS
31
+ //////////////////////////////////////////////////////////////*/
32
+ function _deposit(address token, uint256 amountBase)
33
+ internal
34
+ virtual
35
+ override
36
+ returns (uint256 amountScyOut)
37
+ {
38
+ if (token == stETH) {
39
+ amountScyOut = IWstETH(wstETH).wrap(amountBase);
40
+ _afterSendToken(stETH);
41
+ _afterReceiveToken(wstETH);
42
+ } else {
43
+ // 1 wstETH = 1 SCY
44
+ amountScyOut = amountBase;
45
+ }
46
+ }
47
+
48
+ function _redeem(address token, uint256 amountScy)
49
+ internal
50
+ virtual
51
+ override
52
+ returns (uint256 amountBaseOut)
53
+ {
54
+ if (token == stETH) {
55
+ amountBaseOut = IWstETH(wstETH).unwrap(amountScy);
56
+ _afterSendToken(wstETH);
57
+ _afterReceiveToken(stETH);
58
+ } else {
59
+ // 1 wstETH = 1 SCY
60
+ amountBaseOut = amountScy;
61
+ }
62
+ }
63
+
64
+ /*///////////////////////////////////////////////////////////////
65
+ SCY-INDEX
66
+ //////////////////////////////////////////////////////////////*/
67
+
68
+ function scyIndexCurrent() public virtual override returns (uint256) {
69
+ scyIndexStored = IWstETH(wstETH).stEthPerToken();
70
+ emit UpdateScyIndex(scyIndexStored);
71
+ return scyIndexStored;
72
+ }
73
+
74
+ /*///////////////////////////////////////////////////////////////
75
+ MISC FUNCTIONS FOR METADATA
76
+ //////////////////////////////////////////////////////////////*/
77
+
78
+ function getBaseTokens() public view virtual override returns (address[] memory res) {
79
+ res = new address[](2);
80
+ res[0] = stETH;
81
+ res[1] = wstETH;
82
+ }
83
+
84
+ function isValidBaseToken(address token) public view virtual override returns (bool) {
85
+ return token == stETH || token == wstETH;
86
+ }
87
+
88
+ /*///////////////////////////////////////////////////////////////
89
+ REWARDS-RELATED
90
+ //////////////////////////////////////////////////////////////*/
91
+
92
+ //solhint-disable-next-line no-empty-blocks
93
+ function redeemReward(address user) public virtual override returns (uint256[] memory) {}
94
+
95
+ //solhint-disable-next-line no-empty-blocks
96
+ function updateGlobalReward() public virtual override {}
97
+
98
+ //solhint-disable-next-line no-empty-blocks
99
+ function updateUserReward(address user) public virtual override {}
100
+
101
+ function getRewardTokens() public view virtual returns (address[] memory res) {
102
+ res = new address[](0);
103
+ }
104
+
105
+ //solhint-disable-next-line no-empty-blocks
106
+ function _redeemExternalReward() internal virtual {}
107
+ }
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-or-later
2
2
  pragma solidity 0.8.9;
3
- pragma abicoder v2;
3
+
4
4
  import "../../SuperComposableYield/implementations/SCYBase.sol";
5
5
  import "../../interfaces/IYearnVault.sol";
6
6
 
@@ -10,16 +10,18 @@ contract PendleYearnVaultScy is SCYBase {
10
10
  address public immutable underlying;
11
11
  address public immutable yvToken;
12
12
 
13
- uint256 public lastScyIndex;
13
+ uint256 public override scyIndexStored;
14
14
 
15
15
  constructor(
16
16
  string memory _name,
17
17
  string memory _symbol,
18
18
  uint8 __scydecimals,
19
19
  uint8 __assetDecimals,
20
+ bytes32 __assetId,
20
21
  address _underlying,
21
22
  address _yvToken
22
- ) SCYBase(_name, _symbol, __scydecimals, __assetDecimals) {
23
+ ) SCYBase(_name, _symbol, __scydecimals, __assetDecimals, __assetId) {
24
+ require(_yvToken != address(0), "zero address");
23
25
  yvToken = _yvToken;
24
26
  underlying = _underlying;
25
27
  IERC20(underlying).safeIncreaseAllowance(yvToken, type(uint256).max);
@@ -39,7 +41,7 @@ contract PendleYearnVaultScy is SCYBase {
39
41
  amountScyOut = amountBase;
40
42
  } else {
41
43
  // must be underlying
42
- IYearnVault(yvToken).deposit(amountBase);
44
+ IYearnVault(yvToken).deposit(amountBase); // ignore return
43
45
  _afterSendToken(underlying);
44
46
  amountScyOut = _afterReceiveToken(yvToken);
45
47
  }
@@ -55,7 +57,7 @@ contract PendleYearnVaultScy is SCYBase {
55
57
  amountBaseOut = amountScy;
56
58
  } else {
57
59
  // must be underlying
58
- IYearnVault(yvToken).withdraw(amountScy);
60
+ IYearnVault(yvToken).withdraw(amountScy); // ignore return
59
61
  _afterSendToken(yvToken);
60
62
  amountBaseOut = _afterReceiveToken(underlying);
61
63
  }
@@ -66,13 +68,9 @@ contract PendleYearnVaultScy is SCYBase {
66
68
  //////////////////////////////////////////////////////////////*/
67
69
 
68
70
  function scyIndexCurrent() public virtual override returns (uint256 res) {
69
- res = Math.max(lastScyIndex, IYearnVault(yvToken).pricePerShare());
70
- lastScyIndex = res;
71
- return res;
72
- }
73
-
74
- function scyIndexStored() public view override returns (uint256 res) {
75
- res = lastScyIndex;
71
+ scyIndexStored = IYearnVault(yvToken).pricePerShare();
72
+ emit UpdateScyIndex(scyIndexStored);
73
+ return scyIndexStored;
76
74
  }
77
75
 
78
76
  /*///////////////////////////////////////////////////////////////
@@ -80,12 +78,13 @@ contract PendleYearnVaultScy is SCYBase {
80
78
  //////////////////////////////////////////////////////////////*/
81
79
 
82
80
  function getBaseTokens() public view virtual override returns (address[] memory res) {
83
- res = new address[](1);
81
+ res = new address[](2);
84
82
  res[0] = underlying;
83
+ res[1] = yvToken;
85
84
  }
86
85
 
87
- function isValidBaseToken(address token) public view virtual override returns (bool res) {
88
- res = (token == underlying);
86
+ function isValidBaseToken(address token) public view virtual override returns (bool) {
87
+ return token == underlying || token == yvToken;
89
88
  }
90
89
 
91
90
  /*///////////////////////////////////////////////////////////////
@@ -29,13 +29,13 @@ import "../libraries/helpers/ExpiryUtilsLib.sol";
29
29
  import "../periphery/PermissionsV2Upg.sol";
30
30
  import "../interfaces/IPYieldContractFactory.sol";
31
31
 
32
- import "./PendleOwnershipToken.sol";
32
+ import "./PendlePrincipalToken.sol";
33
33
  import "./PendleYieldToken.sol";
34
34
 
35
35
  contract PendleYieldContractFactory is PermissionsV2Upg, IPYieldContractFactory {
36
36
  using ExpiryUtils for string;
37
37
 
38
- string public constant OT_PREFIX = "OT";
38
+ string public constant PT_PREFIX = "PT";
39
39
  string public constant YT_PREFIX = "YT";
40
40
 
41
41
  uint256 public expiryDivisor;
@@ -43,9 +43,9 @@ contract PendleYieldContractFactory is PermissionsV2Upg, IPYieldContractFactory
43
43
  address public treasury;
44
44
 
45
45
  // SCY => expiry => address
46
- mapping(address => mapping(uint256 => address)) public getOT;
46
+ mapping(address => mapping(uint256 => address)) public getPT;
47
47
  mapping(address => mapping(uint256 => address)) public getYT;
48
- mapping(address => bool) public isOT;
48
+ mapping(address => bool) public isPT;
49
49
  mapping(address => bool) public isYT;
50
50
 
51
51
  constructor(
@@ -54,28 +54,36 @@ contract PendleYieldContractFactory is PermissionsV2Upg, IPYieldContractFactory
54
54
  address _treasury,
55
55
  address _governanceManager
56
56
  ) PermissionsV2Upg(_governanceManager) {
57
+ require(_expiryDivisor != 0, "zero value");
58
+ require(_treasury != address(0), "zero address");
59
+
57
60
  expiryDivisor = _expiryDivisor;
58
61
  interestFeeRate = _interestFeeRate;
59
62
  treasury = _treasury;
60
63
  }
61
64
 
65
+ /**
66
+ * @notice Create a pair of (PT, YT) from any SCY and valid expiry. Anyone can create a yield contract
67
+ */
62
68
  function createYieldContract(address SCY, uint256 expiry)
63
69
  external
64
- returns (address OT, address YT)
70
+ returns (address PT, address YT)
65
71
  {
72
+ require(expiry > block.timestamp, "invalid expiry");
73
+
66
74
  require(expiry % expiryDivisor == 0, "must be multiple of divisor");
67
75
 
68
- require(getOT[SCY][expiry] == address(0), "OT_EXISTED");
76
+ require(getPT[SCY][expiry] == address(0), "PT_EXISTED");
69
77
 
70
78
  ISuperComposableYield _SCY = ISuperComposableYield(SCY);
71
79
 
72
80
  uint8 assetDecimals = _SCY.assetDecimals();
73
81
 
74
- OT = address(
75
- new PendleOwnershipToken(
82
+ PT = address(
83
+ new PendlePrincipalToken(
76
84
  SCY,
77
- OT_PREFIX.concat(_SCY.name(), expiry, " "),
78
- OT_PREFIX.concat(_SCY.symbol(), expiry, "-"),
85
+ PT_PREFIX.concat(_SCY.name(), expiry, " "),
86
+ PT_PREFIX.concat(_SCY.symbol(), expiry, "-"),
79
87
  assetDecimals,
80
88
  expiry
81
89
  )
@@ -84,7 +92,7 @@ contract PendleYieldContractFactory is PermissionsV2Upg, IPYieldContractFactory
84
92
  YT = address(
85
93
  new PendleYieldToken(
86
94
  SCY,
87
- OT,
95
+ PT,
88
96
  YT_PREFIX.concat(_SCY.name(), expiry, " "),
89
97
  YT_PREFIX.concat(_SCY.symbol(), expiry, "-"),
90
98
  assetDecimals,
@@ -92,23 +100,30 @@ contract PendleYieldContractFactory is PermissionsV2Upg, IPYieldContractFactory
92
100
  )
93
101
  );
94
102
 
95
- IPOwnershipToken(OT).initialize(YT);
103
+ IPPrincipalToken(PT).initialize(YT);
96
104
 
97
- getOT[SCY][expiry] = OT;
105
+ getPT[SCY][expiry] = PT;
98
106
  getYT[SCY][expiry] = YT;
99
- isOT[OT] = true;
107
+ isPT[PT] = true;
100
108
  isYT[YT] = true;
109
+
110
+ emit CreateYieldContract(SCY, PT, YT, expiry);
101
111
  }
102
112
 
103
113
  function setExpiryDivisor(uint256 newExpiryDivisor) external onlyGovernance {
114
+ require(newExpiryDivisor != 0, "zero value");
104
115
  expiryDivisor = newExpiryDivisor;
116
+ emit SetExpiryDivisor(newExpiryDivisor);
105
117
  }
106
118
 
107
119
  function setInterestFeeRate(uint256 newInterestFeeRate) external onlyGovernance {
108
120
  interestFeeRate = newInterestFeeRate;
121
+ emit SetInterestFeeRate(newInterestFeeRate);
109
122
  }
110
123
 
111
124
  function setTreasury(address newTreasury) external onlyGovernance {
125
+ require(newTreasury != address(0), "zero address");
112
126
  treasury = newTreasury;
127
+ emit SetTreasury(treasury);
113
128
  }
114
129
  }