@pendle/core-v2 0.5.1-beta-4 → 0.6.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.
- package/contracts/SuperComposableYield/ISuperComposableYield.sol +2 -0
- package/contracts/SuperComposableYield/implementations/RewardManager.sol +35 -20
- package/contracts/SuperComposableYield/implementations/SCYBase.sol +39 -19
- package/contracts/SuperComposableYield/implementations/SCYBaseWithRewards.sol +26 -14
- package/contracts/core/PendleBaseToken.sol +2 -2
- package/contracts/core/PendleMarket.sol +145 -61
- package/contracts/core/PendleMarketFactory.sol +30 -19
- package/contracts/core/{PendleOwnershipToken.sol → PendlePrincipalToken.sol} +14 -2
- package/contracts/core/PendleRouter.sol +23 -9
- package/contracts/core/PendleSCYImpl/AaveV3/PendleAaveV3SCY.sol +21 -20
- package/contracts/core/PendleSCYImpl/PendleBenQiErc20SCY.sol +22 -16
- package/contracts/core/PendleSCYImpl/PendleBtrflySCY.sol +13 -13
- package/contracts/core/PendleSCYImpl/PendleStETHSCY.sol +107 -0
- package/contracts/core/PendleSCYImpl/PendleYearnVaultSCY.sol +14 -15
- package/contracts/core/PendleYieldContractFactory.sol +29 -14
- package/contracts/core/PendleYieldToken.sol +130 -76
- package/contracts/core/RouterStatic.sol +16 -157
- package/contracts/core/actions/ActionCallback.sol +36 -18
- package/contracts/core/actions/ActionCore.sol +41 -88
- package/contracts/core/actions/ActionRedeem.sol +36 -0
- package/contracts/core/actions/ActionYT.sol +41 -59
- package/contracts/core/actions/base/{ActionSCYAndOTBase.sol → ActionSCYAndPTBase.sol} +59 -45
- package/contracts/core/actions/base/{ActionSCYAndYOBase.sol → ActionSCYAndPYBase.sol} +57 -19
- package/contracts/core/actions/base/ActionSCYAndYTBase.sol +31 -21
- package/contracts/interfaces/IPActionCore.sol +21 -28
- package/contracts/interfaces/IPActionRedeem.sol +17 -0
- package/contracts/interfaces/IPActionYT.sol +5 -12
- package/contracts/interfaces/IPAllAction.sol +2 -2
- package/contracts/interfaces/IPMarket.sol +33 -10
- package/contracts/interfaces/IPMarketAddRemoveCallback.sol +2 -2
- package/contracts/interfaces/IPMarketFactory.sol +3 -1
- package/contracts/interfaces/IPMarketSwapCallback.sol +1 -1
- package/contracts/interfaces/{IPOwnershipToken.sol → IPPrincipalToken.sol} +1 -1
- package/contracts/interfaces/IPRouterStatic.sol +7 -82
- package/contracts/interfaces/IPYieldContractFactory.sol +10 -2
- package/contracts/interfaces/IPYieldToken.sol +14 -5
- package/contracts/interfaces/IWstETH.sol +10 -0
- package/contracts/libraries/JoeLibrary.sol +1 -1
- package/contracts/libraries/math/LogExpMath.sol +1 -1
- package/contracts/libraries/math/MarketApproxLib.sol +128 -88
- package/contracts/libraries/math/MarketMathAux.sol +13 -13
- package/contracts/libraries/math/MarketMathCore.sol +62 -93
- package/contracts/libraries/math/Math.sol +14 -2
- package/contracts/periphery/PendleGovernanceManager.sol +5 -3
- package/package.json +3 -2
- package/typechain-types/ActionCallback.ts +5 -5
- package/typechain-types/ActionCore.ts +312 -234
- package/typechain-types/ActionRedeem.ts +125 -0
- package/typechain-types/ActionSCYAndPYBase.ts +223 -0
- package/typechain-types/ActionSCYAndYOBase.ts +129 -3
- package/typechain-types/ActionSCYAndYTBase.ts +149 -3
- package/typechain-types/ActionYT.ts +192 -94
- package/typechain-types/IPActionCore.ts +183 -231
- package/typechain-types/IPActionRedeem.ts +125 -0
- package/typechain-types/IPActionYT.ts +43 -91
- package/typechain-types/IPAllAction.ts +258 -321
- package/typechain-types/IPMarket.ts +150 -50
- package/typechain-types/IPMarketAddRemoveCallback.ts +10 -10
- package/typechain-types/IPMarketFactory.ts +28 -6
- package/typechain-types/IPMarketSwapCallback.ts +5 -5
- package/typechain-types/{IPOwnershipToken.ts → IPPrincipalToken.ts} +5 -5
- package/typechain-types/IPRouterStatic.ts +50 -530
- package/typechain-types/IPYieldContractFactory.ts +85 -19
- package/typechain-types/IPYieldToken.ts +138 -37
- package/typechain-types/ISuperComposableYield.ts +13 -0
- package/typechain-types/IWstETH.ts +149 -0
- package/typechain-types/PendleAaveV3SCY.ts +110 -0
- package/typechain-types/PendleBaseToken.ts +1 -1
- package/typechain-types/PendleBenQiErc20SCY.ts +55 -12
- package/typechain-types/PendleBtrflyScy.ts +27 -23
- package/typechain-types/PendleGovernanceManager.ts +5 -5
- package/typechain-types/PendleMarket.ts +197 -100
- package/typechain-types/PendleMarketFactory.ts +96 -34
- package/typechain-types/{PendleOwnershipToken.ts → PendlePrincipalToken.ts} +15 -6
- package/typechain-types/PendleRouter.ts +19 -0
- package/typechain-types/PendleRouterRedeemUpg.ts +125 -0
- package/typechain-types/PendleStEthSCY.ts +872 -0
- package/typechain-types/PendleYearnVaultScy.ts +27 -23
- package/typechain-types/PendleYieldContractFactory.ts +94 -28
- package/typechain-types/PendleYieldToken.ts +142 -57
- package/typechain-types/RewardManager.ts +21 -0
- package/typechain-types/RouterStatic.ts +50 -530
- package/typechain-types/SCYBase.ts +25 -0
- package/typechain-types/SCYBaseWithRewards.ts +64 -0
- package/typechain-types/factories/ActionCallback__factory.ts +2 -2
- package/typechain-types/factories/ActionCore__factory.ts +263 -79
- package/typechain-types/factories/ActionRedeem__factory.ts +105 -0
- package/typechain-types/factories/ActionSCYAndPYBase__factory.ts +200 -0
- package/typechain-types/factories/ActionSCYAndYOBase__factory.ts +148 -0
- package/typechain-types/factories/ActionSCYAndYTBase__factory.ts +173 -0
- package/typechain-types/factories/ActionYT__factory.ts +265 -56
- package/typechain-types/factories/IPActionCore__factory.ts +114 -78
- package/typechain-types/factories/IPActionRedeem__factory.ts +70 -0
- package/typechain-types/factories/IPActionYT__factory.ts +90 -54
- package/typechain-types/factories/IPAllAction__factory.ts +254 -138
- package/typechain-types/factories/IPMarketAddRemoveCallback__factory.ts +2 -2
- package/typechain-types/factories/IPMarketFactory__factory.ts +26 -1
- package/typechain-types/factories/IPMarketSwapCallback__factory.ts +1 -1
- package/typechain-types/factories/IPMarket__factory.ts +125 -13
- package/typechain-types/factories/{IPOwnershipToken__factory.ts → IPPrincipalToken__factory.ts} +8 -8
- package/typechain-types/factories/IPRouterStatic__factory.ts +12 -628
- package/typechain-types/factories/IPYieldContractFactory__factory.ts +72 -2
- package/typechain-types/factories/IPYieldToken__factory.ts +93 -7
- package/typechain-types/factories/ISuperComposableYield__factory.ts +13 -0
- package/typechain-types/factories/IWstETH__factory.ts +74 -0
- package/typechain-types/factories/PendleAaveV3SCY__factory.ts +97 -3
- package/typechain-types/factories/PendleBaseToken__factory.ts +1 -1
- package/typechain-types/factories/PendleBenQiErc20SCY__factory.ts +62 -7
- package/typechain-types/factories/PendleBtrflyScy__factory.ts +42 -19
- package/typechain-types/factories/PendleGovernanceManager__factory.ts +2 -2
- package/typechain-types/factories/PendleMarketFactory__factory.ts +66 -15
- package/typechain-types/factories/PendleMarket__factory.ts +170 -53
- package/typechain-types/factories/PendlePrincipalToken__factory.ts +540 -0
- package/typechain-types/factories/PendleRouterRedeemUpg__factory.ts +112 -0
- package/typechain-types/factories/PendleRouter__factory.ts +23 -1
- package/typechain-types/factories/PendleStEthSCY__factory.ts +716 -0
- package/typechain-types/factories/PendleYearnVaultScy__factory.ts +41 -18
- package/typechain-types/factories/PendleYieldContractFactory__factory.ts +75 -5
- package/typechain-types/factories/PendleYieldToken__factory.ts +102 -33
- package/typechain-types/factories/RewardManager__factory.ts +13 -0
- package/typechain-types/factories/RouterStatic__factory.ts +13 -629
- package/typechain-types/factories/SCYBaseWithRewards__factory.ts +60 -2
- package/typechain-types/factories/SCYBase__factory.ts +28 -2
- package/typechain-types/hardhat.d.ts +52 -16
- package/typechain-types/index.ts +14 -6
- package/typechain-types/factories/PendleOwnershipToken__factory.ts +0 -527
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
pragma solidity 0.8.9;
|
|
3
3
|
|
|
4
4
|
import "./PendleBaseToken.sol";
|
|
5
|
-
import "../interfaces/
|
|
5
|
+
import "../interfaces/IPPrincipalToken.sol";
|
|
6
6
|
import "../SuperComposableYield/ISuperComposableYield.sol";
|
|
7
7
|
import "../interfaces/IPMarket.sol";
|
|
8
8
|
import "../interfaces/IPMarketFactory.sol";
|
|
@@ -14,10 +14,9 @@ import "../libraries/math/Math.sol";
|
|
|
14
14
|
import "../libraries/math/MarketMathAux.sol";
|
|
15
15
|
|
|
16
16
|
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
17
|
-
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
|
|
18
17
|
|
|
19
18
|
// solhint-disable reason-string
|
|
20
|
-
contract PendleMarket is PendleBaseToken, IPMarket
|
|
19
|
+
contract PendleMarket is PendleBaseToken, IPMarket {
|
|
21
20
|
using Math for uint256;
|
|
22
21
|
using Math for int256;
|
|
23
22
|
using Math for uint128;
|
|
@@ -26,34 +25,72 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
|
|
|
26
25
|
using MarketMathCore for MarketState;
|
|
27
26
|
using SafeERC20 for IERC20;
|
|
28
27
|
|
|
28
|
+
struct MarketStorage {
|
|
29
|
+
int128 totalPt;
|
|
30
|
+
int128 totalScy;
|
|
31
|
+
// 1 SLOT = 256 bits
|
|
32
|
+
uint96 lastLnImpliedRate;
|
|
33
|
+
uint96 oracleRate;
|
|
34
|
+
uint32 lastTradeTime;
|
|
35
|
+
uint8 _reentrancyStatus;
|
|
36
|
+
// 1 SLOT = 232 bits
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
uint8 private constant _NOT_ENTERED = 1;
|
|
40
|
+
uint8 private constant _ENTERED = 2;
|
|
41
|
+
|
|
29
42
|
string private constant NAME = "Pendle Market";
|
|
30
43
|
string private constant SYMBOL = "PENDLE-LPT";
|
|
31
44
|
|
|
32
|
-
address public immutable
|
|
45
|
+
address public immutable PT;
|
|
33
46
|
address public immutable SCY;
|
|
34
47
|
address public immutable YT;
|
|
35
48
|
|
|
36
49
|
int256 public immutable scalarRoot;
|
|
37
50
|
int256 public immutable initialAnchor;
|
|
38
51
|
|
|
39
|
-
MarketStorage public
|
|
52
|
+
MarketStorage public _storage;
|
|
53
|
+
|
|
54
|
+
modifier nonReentrant() {
|
|
55
|
+
// On the first call to nonReentrant, _notEntered will be true
|
|
56
|
+
require(_storage._reentrancyStatus != _ENTERED, "ReentrancyGuard: reentrant call");
|
|
57
|
+
|
|
58
|
+
// Any calls to nonReentrant after this point will fail
|
|
59
|
+
_storage._reentrancyStatus = _ENTERED;
|
|
60
|
+
|
|
61
|
+
_;
|
|
62
|
+
|
|
63
|
+
// By storing the original value once again, a refund is triggered (see
|
|
64
|
+
// https://eips.ethereum.org/EIPS/eip-2200)
|
|
65
|
+
_storage._reentrancyStatus = _NOT_ENTERED;
|
|
66
|
+
}
|
|
40
67
|
|
|
41
68
|
constructor(
|
|
42
|
-
address
|
|
69
|
+
address _PT,
|
|
43
70
|
int256 _scalarRoot,
|
|
44
71
|
int256 _initialAnchor
|
|
45
|
-
) PendleBaseToken(NAME, SYMBOL, 18,
|
|
46
|
-
|
|
47
|
-
SCY =
|
|
48
|
-
YT =
|
|
72
|
+
) PendleBaseToken(NAME, SYMBOL, 18, IPPrincipalToken(_PT).expiry()) {
|
|
73
|
+
PT = _PT;
|
|
74
|
+
SCY = IPPrincipalToken(_PT).SCY();
|
|
75
|
+
YT = IPPrincipalToken(_PT).YT();
|
|
49
76
|
scalarRoot = _scalarRoot;
|
|
50
77
|
initialAnchor = _initialAnchor;
|
|
78
|
+
_storage._reentrancyStatus = _NOT_ENTERED;
|
|
51
79
|
}
|
|
52
80
|
|
|
81
|
+
/**
|
|
82
|
+
* @notice PendleMarket allows users to provide in PT & SCY in exchange for LPs, which
|
|
83
|
+
* will grant LP holders more exchange fee over time
|
|
84
|
+
* @dev steps working of this function:
|
|
85
|
+
- Releases the proportional amount of LP to receiver
|
|
86
|
+
- Callback to msg.sender if data.length > 0
|
|
87
|
+
- Ensure that the corresponding amount of SCY & PT have been transferred to this address
|
|
88
|
+
* @param data bytes data to be sent in the callback
|
|
89
|
+
*/
|
|
53
90
|
function addLiquidity(
|
|
54
91
|
address receiver,
|
|
55
92
|
uint256 scyDesired,
|
|
56
|
-
uint256
|
|
93
|
+
uint256 ptDesired,
|
|
57
94
|
bytes calldata data
|
|
58
95
|
)
|
|
59
96
|
external
|
|
@@ -61,23 +98,23 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
|
|
|
61
98
|
returns (
|
|
62
99
|
uint256 lpToAccount,
|
|
63
100
|
uint256 scyUsed,
|
|
64
|
-
uint256
|
|
101
|
+
uint256 ptUsed
|
|
65
102
|
)
|
|
66
103
|
{
|
|
67
104
|
MarketState memory market = readState(true);
|
|
68
105
|
SCYIndex index = SCYIndexLib.newIndex(SCY);
|
|
69
106
|
|
|
70
107
|
uint256 lpToReserve;
|
|
71
|
-
(lpToReserve, lpToAccount, scyUsed,
|
|
108
|
+
(lpToReserve, lpToAccount, scyUsed, ptUsed) = market.addLiquidity(
|
|
72
109
|
index,
|
|
73
110
|
scyDesired,
|
|
74
|
-
|
|
111
|
+
ptDesired,
|
|
75
112
|
true
|
|
76
113
|
);
|
|
77
114
|
|
|
78
115
|
// initializing the market
|
|
79
116
|
if (lpToReserve != 0) {
|
|
80
|
-
market.
|
|
117
|
+
market.setInitialLnImpliedRate(index, initialAnchor, block.timestamp);
|
|
81
118
|
_mint(address(1), lpToReserve);
|
|
82
119
|
}
|
|
83
120
|
|
|
@@ -87,34 +124,45 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
|
|
|
87
124
|
IPMarketAddRemoveCallback(msg.sender).addLiquidityCallback(
|
|
88
125
|
lpToAccount,
|
|
89
126
|
scyUsed,
|
|
90
|
-
|
|
127
|
+
ptUsed,
|
|
91
128
|
data
|
|
92
129
|
);
|
|
93
130
|
}
|
|
94
131
|
|
|
95
|
-
require(market.
|
|
132
|
+
require(market.totalPt.Uint() <= IERC20(PT).balanceOf(address(this)));
|
|
96
133
|
require(market.totalScy.Uint() <= IERC20(SCY).balanceOf(address(this)));
|
|
97
134
|
|
|
98
135
|
_writeState(market);
|
|
136
|
+
|
|
137
|
+
emit AddLiquidity(receiver, lpToAccount, scyUsed, ptUsed);
|
|
99
138
|
}
|
|
100
139
|
|
|
140
|
+
/**
|
|
141
|
+
* @notice LP Holders can burn their LP to receive back SCY & PT proportionally
|
|
142
|
+
* to their share of market
|
|
143
|
+
* @dev steps working of this contract
|
|
144
|
+
- SCY & PT will be first transferred out to receiver
|
|
145
|
+
- Callback to msg.sender if data.length > 0
|
|
146
|
+
- Ensure the corresponding amount of LP has been transferred to this contract
|
|
147
|
+
* @param data bytes data to be sent in the callback
|
|
148
|
+
*/
|
|
101
149
|
function removeLiquidity(
|
|
102
150
|
address receiver,
|
|
103
151
|
uint256 lpToRemove,
|
|
104
152
|
bytes calldata data
|
|
105
|
-
) external nonReentrant returns (uint256 scyToAccount, uint256
|
|
153
|
+
) external nonReentrant returns (uint256 scyToAccount, uint256 ptToAccount) {
|
|
106
154
|
MarketState memory market = readState(true);
|
|
107
155
|
|
|
108
|
-
(scyToAccount,
|
|
156
|
+
(scyToAccount, ptToAccount) = market.removeLiquidity(lpToRemove, true);
|
|
109
157
|
|
|
110
158
|
IERC20(SCY).safeTransfer(receiver, scyToAccount);
|
|
111
|
-
IERC20(
|
|
159
|
+
IERC20(PT).safeTransfer(receiver, ptToAccount);
|
|
112
160
|
|
|
113
161
|
if (data.length > 0) {
|
|
114
162
|
IPMarketAddRemoveCallback(msg.sender).removeLiquidityCallback(
|
|
115
163
|
lpToRemove,
|
|
116
164
|
scyToAccount,
|
|
117
|
-
|
|
165
|
+
ptToAccount,
|
|
118
166
|
data
|
|
119
167
|
);
|
|
120
168
|
}
|
|
@@ -122,11 +170,22 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
|
|
|
122
170
|
_burn(address(this), lpToRemove);
|
|
123
171
|
|
|
124
172
|
_writeState(market);
|
|
173
|
+
emit RemoveLiquidity(receiver, lpToRemove, scyToAccount, ptToAccount);
|
|
125
174
|
}
|
|
126
175
|
|
|
127
|
-
|
|
176
|
+
/**
|
|
177
|
+
* @notice Pendle Market allows swaps between PT & SCY it is holding. This function
|
|
178
|
+
* aims to swap an exact amount of PT to SCY.
|
|
179
|
+
* @dev steps working of this contract
|
|
180
|
+
- The outcome amount of SCY will be precomputed by MarketMathLib
|
|
181
|
+
- Release the calculated amount of SCY to receiver
|
|
182
|
+
- Callback to msg.sender if data.length > 0
|
|
183
|
+
- Ensure exactPtIn amount of PT has been transferred to this address
|
|
184
|
+
* @param data bytes data to be sent in the callback
|
|
185
|
+
*/
|
|
186
|
+
function swapExactPtForScy(
|
|
128
187
|
address receiver,
|
|
129
|
-
uint256
|
|
188
|
+
uint256 exactPtIn,
|
|
130
189
|
uint256 minScyOut,
|
|
131
190
|
bytes calldata data
|
|
132
191
|
) external nonReentrant returns (uint256 netScyOut, uint256 netScyToReserve) {
|
|
@@ -134,28 +193,40 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
|
|
|
134
193
|
|
|
135
194
|
MarketState memory market = readState(true);
|
|
136
195
|
|
|
137
|
-
(netScyOut, netScyToReserve) = market.
|
|
196
|
+
(netScyOut, netScyToReserve) = market.swapExactPtForScy(
|
|
138
197
|
SCYIndexLib.newIndex(SCY),
|
|
139
|
-
|
|
198
|
+
exactPtIn,
|
|
140
199
|
block.timestamp,
|
|
141
200
|
true
|
|
142
201
|
);
|
|
143
202
|
require(netScyOut >= minScyOut, "insufficient scy out");
|
|
203
|
+
|
|
144
204
|
IERC20(SCY).safeTransfer(receiver, netScyOut);
|
|
145
205
|
IERC20(SCY).safeTransfer(market.treasury, netScyToReserve);
|
|
146
206
|
|
|
147
207
|
if (data.length > 0) {
|
|
148
|
-
IPMarketSwapCallback(msg.sender).swapCallback(
|
|
208
|
+
IPMarketSwapCallback(msg.sender).swapCallback(exactPtIn.neg(), netScyOut.Int(), data);
|
|
149
209
|
}
|
|
150
210
|
|
|
151
|
-
// have received enough
|
|
152
|
-
require(market.
|
|
211
|
+
// have received enough PT
|
|
212
|
+
require(market.totalPt.Uint() <= IERC20(PT).balanceOf(address(this)));
|
|
153
213
|
_writeState(market);
|
|
214
|
+
|
|
215
|
+
emit Swap(receiver, exactPtIn.neg(), netScyOut.Int(), netScyToReserve);
|
|
154
216
|
}
|
|
155
217
|
|
|
156
|
-
|
|
218
|
+
/**
|
|
219
|
+
* @notice Pendle Market allows swaps between PT & SCY it is holding. This function
|
|
220
|
+
* aims to swap an exact amount of SCY to PT.
|
|
221
|
+
* @dev steps working of this function
|
|
222
|
+
- The exact outcome amount of PT will be transferred to receiver
|
|
223
|
+
- Callback to msg.sender if data.length > 0
|
|
224
|
+
- Ensure the calculated required amount of SCY is transferred to this address
|
|
225
|
+
* @param data bytes data to be sent in the callback
|
|
226
|
+
*/
|
|
227
|
+
function swapScyForExactPt(
|
|
157
228
|
address receiver,
|
|
158
|
-
uint256
|
|
229
|
+
uint256 exactPtOut,
|
|
159
230
|
uint256 maxScyIn,
|
|
160
231
|
bytes calldata data
|
|
161
232
|
) external nonReentrant returns (uint256 netScyIn, uint256 netScyToReserve) {
|
|
@@ -163,41 +234,64 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
|
|
|
163
234
|
|
|
164
235
|
MarketState memory market = readState(true);
|
|
165
236
|
|
|
166
|
-
(netScyIn, netScyToReserve) = market.
|
|
237
|
+
(netScyIn, netScyToReserve) = market.swapScyForExactPt(
|
|
167
238
|
SCYIndexLib.newIndex(SCY),
|
|
168
|
-
|
|
239
|
+
exactPtOut,
|
|
169
240
|
block.timestamp,
|
|
170
241
|
true
|
|
171
242
|
);
|
|
172
243
|
require(netScyIn <= maxScyIn, "scy in exceed limit");
|
|
173
|
-
|
|
244
|
+
|
|
245
|
+
IERC20(PT).safeTransfer(receiver, exactPtOut);
|
|
174
246
|
IERC20(SCY).safeTransfer(market.treasury, netScyToReserve);
|
|
175
247
|
|
|
176
248
|
if (data.length > 0) {
|
|
177
|
-
IPMarketSwapCallback(msg.sender).swapCallback(
|
|
249
|
+
IPMarketSwapCallback(msg.sender).swapCallback(exactPtOut.Int(), netScyIn.neg(), data);
|
|
178
250
|
}
|
|
179
251
|
|
|
180
252
|
// have received enough SCY
|
|
181
253
|
require(market.totalScy.Uint() <= IERC20(SCY).balanceOf(address(this)));
|
|
182
254
|
_writeState(market);
|
|
255
|
+
|
|
256
|
+
emit Swap(receiver, exactPtOut.Int(), netScyIn.neg(), netScyToReserve);
|
|
183
257
|
}
|
|
184
258
|
|
|
185
259
|
/// @dev this function is just a place holder. Later on the rewards will be transferred to the liquidity minining
|
|
186
260
|
/// instead
|
|
187
261
|
function redeemScyReward() external returns (uint256[] memory outAmounts) {
|
|
188
262
|
outAmounts = ISuperComposableYield(SCY).redeemReward(address(this));
|
|
263
|
+
address[] memory rewardTokens = ISuperComposableYield(SCY).getRewardTokens();
|
|
264
|
+
address treasury = IPMarketFactory(factory).treasury();
|
|
265
|
+
for (uint256 i = 0; i < rewardTokens.length; i++) {
|
|
266
|
+
IERC20(rewardTokens[i]).safeTransfer(treasury, outAmounts[i]);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function readTokens()
|
|
271
|
+
external
|
|
272
|
+
view
|
|
273
|
+
returns (
|
|
274
|
+
ISuperComposableYield _SCY,
|
|
275
|
+
IPPrincipalToken _PT,
|
|
276
|
+
IPYieldToken _YT
|
|
277
|
+
)
|
|
278
|
+
{
|
|
279
|
+
_SCY = ISuperComposableYield(SCY);
|
|
280
|
+
_PT = IPPrincipalToken(PT);
|
|
281
|
+
_YT = IPYieldToken(YT);
|
|
189
282
|
}
|
|
190
283
|
|
|
191
284
|
function readState(bool updateRateOracle) public view returns (MarketState memory market) {
|
|
192
|
-
MarketStorage
|
|
193
|
-
|
|
194
|
-
market.
|
|
285
|
+
MarketStorage memory local = _storage;
|
|
286
|
+
|
|
287
|
+
market.totalPt = local.totalPt;
|
|
288
|
+
market.totalScy = local.totalScy;
|
|
195
289
|
market.totalLp = totalSupply().Int();
|
|
196
|
-
market.oracleRate =
|
|
290
|
+
market.oracleRate = local.oracleRate;
|
|
197
291
|
|
|
198
292
|
(
|
|
199
293
|
market.treasury,
|
|
200
|
-
market.
|
|
294
|
+
market.lnFeeRateRoot,
|
|
201
295
|
market.rateOracleTimeWindow,
|
|
202
296
|
market.reserveFeePercent
|
|
203
297
|
) = IPMarketFactory(factory).marketConfig();
|
|
@@ -205,35 +299,25 @@ contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
|
|
|
205
299
|
market.scalarRoot = scalarRoot;
|
|
206
300
|
market.expiry = expiry;
|
|
207
301
|
|
|
208
|
-
market.
|
|
209
|
-
market.lastTradeTime =
|
|
302
|
+
market.lastLnImpliedRate = local.lastLnImpliedRate;
|
|
303
|
+
market.lastTradeTime = local.lastTradeTime;
|
|
210
304
|
|
|
211
305
|
if (updateRateOracle) {
|
|
212
|
-
market.
|
|
306
|
+
market.oracleRate = market.getNewRateOracle(block.timestamp);
|
|
213
307
|
}
|
|
214
308
|
}
|
|
215
309
|
|
|
216
310
|
function _writeState(MarketState memory market) internal {
|
|
217
|
-
MarketStorage
|
|
311
|
+
MarketStorage memory tempStore;
|
|
218
312
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
313
|
+
tempStore.totalPt = market.totalPt.Int128();
|
|
314
|
+
tempStore.totalScy = market.totalScy.Int128();
|
|
315
|
+
tempStore.lastLnImpliedRate = market.lastLnImpliedRate.Uint96();
|
|
316
|
+
tempStore.oracleRate = market.oracleRate.Uint96();
|
|
317
|
+
tempStore.lastTradeTime = market.lastTradeTime.Uint32();
|
|
225
318
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
returns (
|
|
230
|
-
ISuperComposableYield _SCY,
|
|
231
|
-
IPOwnershipToken _OT,
|
|
232
|
-
IPYieldToken _YT
|
|
233
|
-
)
|
|
234
|
-
{
|
|
235
|
-
_SCY = ISuperComposableYield(SCY);
|
|
236
|
-
_OT = IPOwnershipToken(OT);
|
|
237
|
-
_YT = IPYieldToken(YT);
|
|
319
|
+
_storage = tempStore;
|
|
320
|
+
|
|
321
|
+
emit UpdateImpliedRate(block.timestamp, market.lastLnImpliedRate);
|
|
238
322
|
}
|
|
239
323
|
}
|
|
@@ -11,16 +11,19 @@ contract PendleMarketFactory is PermissionsV2Upg, IPMarketFactory {
|
|
|
11
11
|
using EnumerableSet for EnumerableSet.AddressSet;
|
|
12
12
|
|
|
13
13
|
struct MarketConfig {
|
|
14
|
-
address treasury;
|
|
15
|
-
uint96
|
|
16
|
-
// 1 SLOT
|
|
14
|
+
address treasury;
|
|
15
|
+
uint96 lnFeeRateRoot;
|
|
16
|
+
// 1 SLOT = 256 bits
|
|
17
17
|
uint32 rateOracleTimeWindow;
|
|
18
18
|
uint8 reserveFeePercent;
|
|
19
|
+
// 1 SLOT = 40 bits
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
mapping(address => EnumerableSet.AddressSet) internal markets;
|
|
22
23
|
|
|
23
24
|
address public immutable yieldContractFactory;
|
|
25
|
+
uint256 public immutable maxLnFeeRateRoot;
|
|
26
|
+
uint256 public constant minRateOracleTimeWindow = 300 seconds;
|
|
24
27
|
|
|
25
28
|
MarketConfig public marketConfig;
|
|
26
29
|
|
|
@@ -28,38 +31,46 @@ contract PendleMarketFactory is PermissionsV2Upg, IPMarketFactory {
|
|
|
28
31
|
address _governanceManager,
|
|
29
32
|
address _yieldContractFactory,
|
|
30
33
|
address _treasury,
|
|
31
|
-
uint96
|
|
34
|
+
uint96 _lnFeeRateRoot,
|
|
32
35
|
uint32 _rateOracleTimeWindow,
|
|
33
36
|
uint8 _reserveFeePercent
|
|
34
37
|
) PermissionsV2Upg(_governanceManager) {
|
|
38
|
+
require(_yieldContractFactory != address(0), "zero address");
|
|
35
39
|
yieldContractFactory = _yieldContractFactory;
|
|
40
|
+
maxLnFeeRateRoot = uint256(LogExpMath.ln(int256((105 * Math.IONE) / 100))); // ln(1.05)
|
|
36
41
|
|
|
37
42
|
setTreasury(_treasury);
|
|
38
|
-
|
|
43
|
+
setlnFeeRateRoot(_lnFeeRateRoot);
|
|
39
44
|
setRateOracleTimeWindow(_rateOracleTimeWindow);
|
|
40
45
|
setReserveFeePercent(_reserveFeePercent);
|
|
41
46
|
}
|
|
42
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @notice Create a market between PT and its corresponding SCY
|
|
50
|
+
* with scalar & anchor config. Anyone is allowed to create a market on their own.
|
|
51
|
+
*/
|
|
43
52
|
function createNewMarket(
|
|
44
|
-
address
|
|
53
|
+
address PT,
|
|
45
54
|
int256 scalarRoot,
|
|
46
55
|
int256 initialAnchor
|
|
47
56
|
) external returns (address market) {
|
|
48
|
-
address SCY =
|
|
49
|
-
uint256 expiry =
|
|
57
|
+
address SCY = IPPrincipalToken(PT).SCY();
|
|
58
|
+
uint256 expiry = IPPrincipalToken(PT).expiry();
|
|
50
59
|
|
|
51
60
|
require(
|
|
52
|
-
IPYieldContractFactory(yieldContractFactory).
|
|
53
|
-
"
|
|
61
|
+
IPYieldContractFactory(yieldContractFactory).getPT(SCY, expiry) == PT,
|
|
62
|
+
"INVALID_PT"
|
|
54
63
|
);
|
|
55
64
|
|
|
56
|
-
market = address(new PendleMarket(
|
|
57
|
-
markets[
|
|
65
|
+
market = address(new PendleMarket(PT, scalarRoot, initialAnchor));
|
|
66
|
+
require(markets[PT].add(market), "market add failed");
|
|
67
|
+
|
|
68
|
+
emit CreateNewMarket(PT, scalarRoot, initialAnchor);
|
|
58
69
|
}
|
|
59
70
|
|
|
60
71
|
function isValidMarket(address market) external view returns (bool) {
|
|
61
|
-
address
|
|
62
|
-
return markets[
|
|
72
|
+
address PT = IPMarket(market).PT();
|
|
73
|
+
return markets[PT].contains(market);
|
|
63
74
|
}
|
|
64
75
|
|
|
65
76
|
function treasury() external view returns (address) {
|
|
@@ -71,18 +82,18 @@ contract PendleMarketFactory is PermissionsV2Upg, IPMarketFactory {
|
|
|
71
82
|
marketConfig.treasury = newTreasury;
|
|
72
83
|
}
|
|
73
84
|
|
|
74
|
-
function
|
|
75
|
-
|
|
76
|
-
marketConfig.
|
|
85
|
+
function setlnFeeRateRoot(uint96 newlnFeeRateRoot) public onlyGovernance {
|
|
86
|
+
require(newlnFeeRateRoot <= maxLnFeeRateRoot, "invalid fee rate root");
|
|
87
|
+
marketConfig.lnFeeRateRoot = newlnFeeRateRoot;
|
|
77
88
|
}
|
|
78
89
|
|
|
79
90
|
function setRateOracleTimeWindow(uint32 newRateOracleTimeWindow) public onlyGovernance {
|
|
80
|
-
|
|
91
|
+
require(newRateOracleTimeWindow >= minRateOracleTimeWindow, "invalid time window");
|
|
81
92
|
marketConfig.rateOracleTimeWindow = newRateOracleTimeWindow;
|
|
82
93
|
}
|
|
83
94
|
|
|
84
95
|
function setReserveFeePercent(uint8 newReserveFeePercent) public onlyGovernance {
|
|
85
|
-
require(newReserveFeePercent <= 100, "invalid fee
|
|
96
|
+
require(newReserveFeePercent <= 100, "invalid reserve fee percent");
|
|
86
97
|
marketConfig.reserveFeePercent = newReserveFeePercent;
|
|
87
98
|
}
|
|
88
99
|
}
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
pragma solidity 0.8.9;
|
|
3
3
|
|
|
4
4
|
import "./PendleBaseToken.sol";
|
|
5
|
-
import "../interfaces/
|
|
5
|
+
import "../interfaces/IPPrincipalToken.sol";
|
|
6
|
+
import "../interfaces/IPYieldToken.sol";
|
|
6
7
|
|
|
7
|
-
contract
|
|
8
|
+
contract PendlePrincipalToken is PendleBaseToken, IPPrincipalToken {
|
|
8
9
|
address public immutable SCY;
|
|
9
10
|
address public YT;
|
|
10
11
|
|
|
12
|
+
event YTSet(address indexed YT);
|
|
13
|
+
|
|
11
14
|
modifier onlyYT() {
|
|
12
15
|
require(msg.sender == address(YT), "ONLY_YT");
|
|
13
16
|
_;
|
|
@@ -25,17 +28,26 @@ contract PendleOwnershipToken is PendleBaseToken, IPOwnershipToken {
|
|
|
25
28
|
uint8 __decimals,
|
|
26
29
|
uint256 _expiry
|
|
27
30
|
) PendleBaseToken(_name, _symbol, __decimals, _expiry) {
|
|
31
|
+
require(_SCY != address(0), "zero address");
|
|
28
32
|
SCY = _SCY;
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
function initialize(address _YT) external onlyFactory {
|
|
36
|
+
require(IPYieldToken(_YT).PT() == address(this), "invalid YT");
|
|
32
37
|
YT = _YT;
|
|
38
|
+
emit YTSet(_YT);
|
|
33
39
|
}
|
|
34
40
|
|
|
41
|
+
/**
|
|
42
|
+
* @dev only callable by the YT correspond to this OT
|
|
43
|
+
*/
|
|
35
44
|
function burnByYT(address user, uint256 amount) external onlyYT {
|
|
36
45
|
_burn(user, amount);
|
|
37
46
|
}
|
|
38
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @dev only callable by the YT correspond to this OT
|
|
50
|
+
*/
|
|
39
51
|
function mintByYT(address user, uint256 amount) external onlyYT {
|
|
40
52
|
_mint(user, amount);
|
|
41
53
|
}
|
|
@@ -8,6 +8,7 @@ import "../interfaces/IPActionCore.sol";
|
|
|
8
8
|
import "../interfaces/IPActionYT.sol";
|
|
9
9
|
import "../interfaces/IPRouterStatic.sol";
|
|
10
10
|
import "../interfaces/IPMarketSwapCallback.sol";
|
|
11
|
+
import "../interfaces/IPActionRedeem.sol";
|
|
11
12
|
import "../periphery/PermissionsV2Upg.sol";
|
|
12
13
|
|
|
13
14
|
/// @dev this contract will be deployed behind an ERC1967 proxy
|
|
@@ -19,16 +20,26 @@ contract PendleRouter is Proxy, Initializable, UUPSUpgradeable, PermissionsV2Upg
|
|
|
19
20
|
address public immutable ACTION_CORE;
|
|
20
21
|
address public immutable ACTION_YT;
|
|
21
22
|
address public immutable ACTION_CALLBACK;
|
|
23
|
+
address public immutable ACTION_REDEEM;
|
|
22
24
|
|
|
23
25
|
constructor(
|
|
24
26
|
address _ACTION_CORE,
|
|
25
27
|
address _ACTION_YT,
|
|
26
28
|
address _ACTION_CALLBACK,
|
|
29
|
+
address _ACTION_REDEEM,
|
|
27
30
|
address _governanceManager
|
|
28
31
|
) PermissionsV2Upg(_governanceManager) initializer {
|
|
32
|
+
require(
|
|
33
|
+
_ACTION_CORE != address(0) &&
|
|
34
|
+
_ACTION_YT != address(0) &&
|
|
35
|
+
_ACTION_CALLBACK != address(0) &&
|
|
36
|
+
_ACTION_REDEEM != address(0),
|
|
37
|
+
"zero address"
|
|
38
|
+
);
|
|
29
39
|
ACTION_CORE = _ACTION_CORE;
|
|
30
40
|
ACTION_YT = _ACTION_YT;
|
|
31
41
|
ACTION_CALLBACK = _ACTION_CALLBACK;
|
|
42
|
+
ACTION_REDEEM = _ACTION_REDEEM;
|
|
32
43
|
}
|
|
33
44
|
|
|
34
45
|
function initialize() external initializer {
|
|
@@ -40,16 +51,16 @@ contract PendleRouter is Proxy, Initializable, UUPSUpgradeable, PermissionsV2Upg
|
|
|
40
51
|
if (
|
|
41
52
|
sig == IPActionCore.mintScyFromRawToken.selector ||
|
|
42
53
|
sig == IPActionCore.redeemScyToRawToken.selector ||
|
|
43
|
-
sig == IPActionCore.
|
|
44
|
-
sig == IPActionCore.
|
|
54
|
+
sig == IPActionCore.mintPyFromRawToken.selector ||
|
|
55
|
+
sig == IPActionCore.redeemPyToRawToken.selector ||
|
|
45
56
|
sig == IPActionCore.addLiquidity.selector ||
|
|
46
57
|
sig == IPActionCore.removeLiquidity.selector ||
|
|
47
|
-
sig == IPActionCore.
|
|
48
|
-
sig == IPActionCore.
|
|
49
|
-
sig == IPActionCore.
|
|
50
|
-
sig == IPActionCore.
|
|
51
|
-
sig == IPActionCore.
|
|
52
|
-
sig == IPActionCore.
|
|
58
|
+
sig == IPActionCore.swapExactPtForScy.selector ||
|
|
59
|
+
sig == IPActionCore.swapPtForExactScy.selector ||
|
|
60
|
+
sig == IPActionCore.swapScyForExactPt.selector ||
|
|
61
|
+
sig == IPActionCore.swapExactScyForPt.selector ||
|
|
62
|
+
sig == IPActionCore.swapExactRawTokenForPt.selector ||
|
|
63
|
+
sig == IPActionCore.swapExactPtForRawToken.selector
|
|
53
64
|
) {
|
|
54
65
|
return ACTION_CORE;
|
|
55
66
|
} else if (
|
|
@@ -57,9 +68,12 @@ contract PendleRouter is Proxy, Initializable, UUPSUpgradeable, PermissionsV2Upg
|
|
|
57
68
|
sig == IPActionYT.swapScyForExactYt.selector ||
|
|
58
69
|
sig == IPActionYT.swapExactScyForYt.selector ||
|
|
59
70
|
sig == IPActionYT.swapExactRawTokenForYt.selector ||
|
|
60
|
-
sig == IPActionYT.swapExactYtForRawToken.selector
|
|
71
|
+
sig == IPActionYT.swapExactYtForRawToken.selector ||
|
|
72
|
+
sig == IPActionYT.swapYtForExactScy.selector
|
|
61
73
|
) {
|
|
62
74
|
return ACTION_YT;
|
|
75
|
+
} else if (sig == IPActionRedeem.redeemDueIncome.selector) {
|
|
76
|
+
return ACTION_REDEEM;
|
|
63
77
|
} else if (sig == IPMarketSwapCallback.swapCallback.selector) {
|
|
64
78
|
return ACTION_CALLBACK;
|
|
65
79
|
}
|