@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.
- package/LICENSE +100 -0
- package/contracts/SuperComposableYield/ISuperComposableYield.sol +68 -0
- package/contracts/SuperComposableYield/SCYUtils.sol +14 -0
- package/contracts/SuperComposableYield/implementations/RewardManager.sol +117 -0
- package/contracts/SuperComposableYield/implementations/SCYBase.sol +126 -0
- package/contracts/SuperComposableYield/implementations/SCYBaseWithRewards.sol +79 -0
- package/contracts/core/PendleBaseToken.sol +39 -0
- package/contracts/core/PendleMarket.sol +248 -0
- package/contracts/core/PendleMarketFactory.sol +60 -0
- package/contracts/core/PendleOwnershipToken.sol +44 -0
- package/contracts/core/PendleSCYImpl/AaveV3/PendleAaveV3SCY.sol +139 -0
- package/contracts/core/PendleSCYImpl/AaveV3/WadRayMath.sol +126 -0
- package/contracts/core/PendleSCYImpl/PendleBenQiErc20SCY.sol +127 -0
- package/contracts/core/PendleSCYImpl/PendleBtrflySCY.sol +125 -0
- package/contracts/core/PendleSCYImpl/PendleYearnVaultSCY.sol +115 -0
- package/contracts/core/PendleYieldContractFactory.sol +109 -0
- package/contracts/core/PendleYieldToken.sol +240 -0
- package/contracts/core/misc/BoringOwnable.sol +62 -0
- package/contracts/core/misc/BoringOwnableUpg.sol +64 -0
- package/contracts/core/misc/PendleJoeSwapHelperUpg.sol +82 -0
- package/contracts/core/router/PendleRouterCoreUpg.sol +219 -0
- package/contracts/core/router/PendleRouterProxy.sol +64 -0
- package/contracts/core/router/PendleRouterYTUpg.sol +134 -0
- package/contracts/core/router/base/PendleRouterOTBaseUpg.sol +218 -0
- package/contracts/core/router/base/PendleRouterSCYAndForgeBaseUpg.sol +141 -0
- package/contracts/core/router/base/PendleRouterYTBaseUpg.sol +212 -0
- package/contracts/interfaces/IAToken.sol +34 -0
- package/contracts/interfaces/IAavePool.sol +41 -0
- package/contracts/interfaces/IAaveRewardsController.sol +32 -0
- package/contracts/interfaces/IBenQiComptroller.sol +33 -0
- package/contracts/interfaces/IJoePair.sol +98 -0
- package/contracts/interfaces/IJoeRouter01.sol +162 -0
- package/contracts/interfaces/IPBaseToken.sol +9 -0
- package/contracts/interfaces/IPFlashCallBack.sol +10 -0
- package/contracts/interfaces/IPGovernanceManager.sol +28 -0
- package/contracts/interfaces/IPMarket.sol +57 -0
- package/contracts/interfaces/IPMarketAddRemoveCallback.sol +18 -0
- package/contracts/interfaces/IPMarketFactory.sol +8 -0
- package/contracts/interfaces/IPMarketSwapCallback.sol +10 -0
- package/contracts/interfaces/IPOwnershipToken.sol +15 -0
- package/contracts/interfaces/IPPermissionsV2.sol +28 -0
- package/contracts/interfaces/IPRouterCore.sol +108 -0
- package/contracts/interfaces/IPRouterYT.sol +47 -0
- package/contracts/interfaces/IPYieldContractFactory.sol +36 -0
- package/contracts/interfaces/IPYieldToken.sol +19 -0
- package/contracts/interfaces/IQiErc20.sol +35 -0
- package/contracts/interfaces/IQiToken.sol +29 -0
- package/contracts/interfaces/IREDACTEDStaking.sol +35 -0
- package/contracts/interfaces/IWETH.sol +34 -0
- package/contracts/interfaces/IWXBTRFLY.sol +37 -0
- package/contracts/interfaces/IYearnVault.sol +32 -0
- package/contracts/libraries/JoeLibrary.sol +121 -0
- package/contracts/libraries/SCYIndex.sol +55 -0
- package/contracts/libraries/helpers/ExpiryUtilsLib.sol +166 -0
- package/contracts/libraries/math/FixedPoint.sol +208 -0
- package/contracts/libraries/math/LogExpMath.sol +515 -0
- package/contracts/libraries/math/MarketApproxLib.sol +140 -0
- package/contracts/libraries/math/MarketMathLib.sol +606 -0
- package/contracts/periphery/PendleGovernanceManager.sol +36 -0
- package/contracts/periphery/PermissionsV2.sol +23 -0
- package/package.json +76 -0
- package/typechain-types/BoringOwnable.ts +194 -0
- package/typechain-types/BoringOwnableData.ts +100 -0
- package/typechain-types/BoringOwnableUpg.ts +194 -0
- package/typechain-types/BoringOwnableUpgData.ts +100 -0
- package/typechain-types/ERC1967UpgradeUpgradeable.ts +97 -0
- package/typechain-types/ERC20.ts +417 -0
- package/typechain-types/IAToken.ts +331 -0
- package/typechain-types/IAavePool.ts +192 -0
- package/typechain-types/IAaveRewardsController.ts +148 -0
- package/typechain-types/IBeaconUpgradeable.ts +87 -0
- package/typechain-types/IBenQiComptroller.ts +125 -0
- package/typechain-types/IERC1822ProxiableUpgradeable.ts +87 -0
- package/typechain-types/IERC20.ts +300 -0
- package/typechain-types/IERC20Metadata.ts +339 -0
- package/typechain-types/IJoePair.ts +888 -0
- package/typechain-types/IJoeRouter01.ts +1107 -0
- package/typechain-types/IPBaseToken.ts +365 -0
- package/typechain-types/IPFlashCallback.ts +115 -0
- package/typechain-types/IPGovernanceManager.ts +84 -0
- package/typechain-types/IPMarket.ts +701 -0
- package/typechain-types/IPMarketAddRemoveCallback.ts +169 -0
- package/typechain-types/IPMarketFactory.ts +109 -0
- package/typechain-types/IPMarketSwapCallback.ts +115 -0
- package/typechain-types/IPOwnershipToken.ts +488 -0
- package/typechain-types/IPRouterCore.ts +759 -0
- package/typechain-types/IPRouterYT.ts +405 -0
- package/typechain-types/IPYieldContractFactory.ts +192 -0
- package/typechain-types/IPYieldToken.ts +525 -0
- package/typechain-types/IPermissionsV2.ts +87 -0
- package/typechain-types/IQiErc20.ts +402 -0
- package/typechain-types/IQiToken.ts +327 -0
- package/typechain-types/IREDACTEDStaking.ts +216 -0
- package/typechain-types/ISuperComposableYield.ts +652 -0
- package/typechain-types/IWETH.ts +380 -0
- package/typechain-types/IWXBTRFLY.ts +254 -0
- package/typechain-types/IYearnVault.ts +152 -0
- package/typechain-types/PendleAaveV3SCY.ts +901 -0
- package/typechain-types/PendleBaseToken.ts +505 -0
- package/typechain-types/PendleBenQiErc20SCY.ts +914 -0
- package/typechain-types/PendleBtrflyScy.ts +794 -0
- package/typechain-types/PendleGovernanceManager.ts +187 -0
- package/typechain-types/PendleJoeSwapHelperUpg.ts +97 -0
- package/typechain-types/PendleMarket.ts +1008 -0
- package/typechain-types/PendleMarketFactory.ts +246 -0
- package/typechain-types/PendleOwnershipToken.ts +628 -0
- package/typechain-types/PendleRouterCoreUpg.ts +780 -0
- package/typechain-types/PendleRouterProxy.ts +417 -0
- package/typechain-types/PendleRouterSCYAndForgeBaseUpg.ts +98 -0
- package/typechain-types/PendleRouterYTBaseUpg.ts +134 -0
- package/typechain-types/PendleRouterYTUpg.ts +453 -0
- package/typechain-types/PendleYearnVaultScy.ts +784 -0
- package/typechain-types/PendleYieldContractFactory.ts +479 -0
- package/typechain-types/PendleYieldToken.ts +1030 -0
- package/typechain-types/PermissionsV2.ts +87 -0
- package/typechain-types/Proxy.ts +57 -0
- package/typechain-types/RewardManager.ts +172 -0
- package/typechain-types/SCYBase.ts +734 -0
- package/typechain-types/SCYBaseWithRewards.ts +819 -0
- package/typechain-types/UUPSUpgradeable.ts +197 -0
- package/typechain-types/common.ts +44 -0
- package/typechain-types/factories/BoringOwnableData__factory.ts +90 -0
- package/typechain-types/factories/BoringOwnableUpgData__factory.ts +94 -0
- package/typechain-types/factories/BoringOwnableUpg__factory.ts +139 -0
- package/typechain-types/factories/BoringOwnable__factory.ts +149 -0
- package/typechain-types/factories/ERC1967UpgradeUpgradeable__factory.ts +75 -0
- package/typechain-types/factories/ERC20__factory.ts +348 -0
- package/typechain-types/factories/IAToken__factory.ts +225 -0
- package/typechain-types/factories/IAavePool__factory.ts +99 -0
- package/typechain-types/factories/IAaveRewardsController__factory.ts +78 -0
- package/typechain-types/factories/IBeaconUpgradeable__factory.ts +39 -0
- package/typechain-types/factories/IBenQiComptroller__factory.ts +59 -0
- package/typechain-types/factories/IERC1822ProxiableUpgradeable__factory.ts +43 -0
- package/typechain-types/factories/IERC20Metadata__factory.ts +248 -0
- package/typechain-types/factories/IERC20__factory.ts +203 -0
- package/typechain-types/factories/IJoePair__factory.ts +674 -0
- package/typechain-types/factories/IJoeRouter01__factory.ts +772 -0
- package/typechain-types/factories/IPBaseToken__factory.ts +271 -0
- package/typechain-types/factories/IPFlashCallback__factory.ts +49 -0
- package/typechain-types/factories/IPGovernanceManager__factory.ts +39 -0
- package/typechain-types/factories/IPMarketAddRemoveCallback__factory.ts +86 -0
- package/typechain-types/factories/IPMarketFactory__factory.ts +58 -0
- package/typechain-types/factories/IPMarketSwapCallback__factory.ts +53 -0
- package/typechain-types/factories/IPMarket__factory.ts +559 -0
- package/typechain-types/factories/IPOwnershipToken__factory.ts +349 -0
- package/typechain-types/factories/IPRouterCore__factory.ts +516 -0
- package/typechain-types/factories/IPRouterYT__factory.ts +246 -0
- package/typechain-types/factories/IPYieldContractFactory__factory.ts +117 -0
- package/typechain-types/factories/IPYieldToken__factory.ts +383 -0
- package/typechain-types/factories/IPermissionsV2__factory.ts +39 -0
- package/typechain-types/factories/IQiErc20__factory.ts +270 -0
- package/typechain-types/factories/IQiToken__factory.ts +219 -0
- package/typechain-types/factories/IREDACTEDStaking__factory.ts +107 -0
- package/typechain-types/factories/ISuperComposableYield__factory.ts +438 -0
- package/typechain-types/factories/IWETH__factory.ts +261 -0
- package/typechain-types/factories/IWXBTRFLY__factory.ts +131 -0
- package/typechain-types/factories/IYearnVault__factory.ts +74 -0
- package/typechain-types/factories/PendleAaveV3SCY__factory.ts +727 -0
- package/typechain-types/factories/PendleBaseToken__factory.ts +386 -0
- package/typechain-types/factories/PendleBenQiErc20SCY__factory.ts +753 -0
- package/typechain-types/factories/PendleBtrflyScy__factory.ts +652 -0
- package/typechain-types/factories/PendleGovernanceManager__factory.ts +149 -0
- package/typechain-types/factories/PendleJoeSwapHelperUpg__factory.ts +56 -0
- package/typechain-types/factories/PendleMarketFactory__factory.ts +207 -0
- package/typechain-types/factories/PendleMarket__factory.ts +891 -0
- package/typechain-types/factories/PendleOwnershipToken__factory.ts +565 -0
- package/typechain-types/factories/PendleRouterCoreUpg__factory.ts +620 -0
- package/typechain-types/factories/PendleRouterProxy__factory.ts +316 -0
- package/typechain-types/factories/PendleRouterSCYAndForgeBaseUpg__factory.ts +56 -0
- package/typechain-types/factories/PendleRouterYTBaseUpg__factory.ts +66 -0
- package/typechain-types/factories/PendleRouterYTUpg__factory.ts +363 -0
- package/typechain-types/factories/PendleYearnVaultScy__factory.ts +630 -0
- package/typechain-types/factories/PendleYieldContractFactory__factory.ts +368 -0
- package/typechain-types/factories/PendleYieldToken__factory.ts +814 -0
- package/typechain-types/factories/PermissionsV2__factory.ts +36 -0
- package/typechain-types/factories/Proxy__factory.ts +28 -0
- package/typechain-types/factories/RewardManager__factory.ts +89 -0
- package/typechain-types/factories/SCYBaseWithRewards__factory.ts +535 -0
- package/typechain-types/factories/SCYBase__factory.ts +479 -0
- package/typechain-types/factories/UUPSUpgradeable__factory.ts +115 -0
- package/typechain-types/hardhat.d.ts +564 -0
- package/typechain-types/index.ts +122 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
pragma solidity 0.8.9;
|
|
3
|
+
|
|
4
|
+
import "./PendleBaseToken.sol";
|
|
5
|
+
import "../interfaces/IPOwnershipToken.sol";
|
|
6
|
+
import "../SuperComposableYield/ISuperComposableYield.sol";
|
|
7
|
+
import "../interfaces/IPMarket.sol";
|
|
8
|
+
import "../interfaces/IPMarketFactory.sol";
|
|
9
|
+
import "../interfaces/IPMarketSwapCallback.sol";
|
|
10
|
+
import "../interfaces/IPMarketAddRemoveCallback.sol";
|
|
11
|
+
|
|
12
|
+
import "../libraries/math/LogExpMath.sol";
|
|
13
|
+
import "../libraries/math/FixedPoint.sol";
|
|
14
|
+
import "../libraries/math/MarketMathLib.sol";
|
|
15
|
+
|
|
16
|
+
import "openzeppelin-solidity/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
17
|
+
import "openzeppelin-solidity/contracts/security/ReentrancyGuard.sol";
|
|
18
|
+
|
|
19
|
+
// solhint-disable reason-string
|
|
20
|
+
contract PendleMarket is PendleBaseToken, IPMarket, ReentrancyGuard {
|
|
21
|
+
using FixedPoint for uint256;
|
|
22
|
+
using FixedPoint for int256;
|
|
23
|
+
using FixedPoint for uint128;
|
|
24
|
+
using LogExpMath for uint256;
|
|
25
|
+
using MarketMathLib for MarketParameters;
|
|
26
|
+
using SafeERC20 for IERC20;
|
|
27
|
+
|
|
28
|
+
string private constant NAME = "Pendle Market";
|
|
29
|
+
string private constant SYMBOL = "PENDLE-LPT";
|
|
30
|
+
uint256 private constant MINIMUM_LIQUIDITY = 10**3;
|
|
31
|
+
uint8 private constant DECIMALS = 18;
|
|
32
|
+
int256 internal constant RATE_PRECISION = 1e9;
|
|
33
|
+
|
|
34
|
+
address public immutable OT;
|
|
35
|
+
address public immutable SCY;
|
|
36
|
+
address public immutable YT;
|
|
37
|
+
|
|
38
|
+
int256 public immutable scalarRoot;
|
|
39
|
+
uint256 public immutable feeRateRoot; // allow fee to be changable?
|
|
40
|
+
int256 public immutable anchorRoot;
|
|
41
|
+
|
|
42
|
+
uint256 public immutable rateOracleTimeWindow;
|
|
43
|
+
int8 public immutable reserveFeePercent;
|
|
44
|
+
|
|
45
|
+
MarketStorage public marketStorage;
|
|
46
|
+
|
|
47
|
+
constructor(
|
|
48
|
+
address _OT,
|
|
49
|
+
uint256 _rateOracleTimeWindow,
|
|
50
|
+
uint256 _feeRateRoot,
|
|
51
|
+
int256 _scalarRoot,
|
|
52
|
+
int256 _anchorRoot,
|
|
53
|
+
uint8 _reserveFeePercent
|
|
54
|
+
) PendleBaseToken(NAME, SYMBOL, 18, IPOwnershipToken(_OT).expiry()) {
|
|
55
|
+
OT = _OT;
|
|
56
|
+
SCY = IPOwnershipToken(_OT).SCY();
|
|
57
|
+
YT = IPOwnershipToken(_OT).YT();
|
|
58
|
+
feeRateRoot = _feeRateRoot;
|
|
59
|
+
scalarRoot = _scalarRoot;
|
|
60
|
+
rateOracleTimeWindow = _rateOracleTimeWindow;
|
|
61
|
+
|
|
62
|
+
require(_reserveFeePercent <= 100, "invalid fee rate");
|
|
63
|
+
reserveFeePercent = int8(_reserveFeePercent);
|
|
64
|
+
anchorRoot = _anchorRoot;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function addLiquidity(
|
|
68
|
+
address receiver,
|
|
69
|
+
uint256 scyDesired,
|
|
70
|
+
uint256 otDesired,
|
|
71
|
+
bytes calldata data
|
|
72
|
+
)
|
|
73
|
+
external
|
|
74
|
+
nonReentrant
|
|
75
|
+
returns (
|
|
76
|
+
uint256 lpToAccount,
|
|
77
|
+
uint256 scyUsed,
|
|
78
|
+
uint256 otUsed
|
|
79
|
+
)
|
|
80
|
+
{
|
|
81
|
+
MarketParameters memory market = readState();
|
|
82
|
+
SCYIndex index = SCYIndexLib.newIndex(SCY);
|
|
83
|
+
|
|
84
|
+
uint256 lpToReserve;
|
|
85
|
+
(lpToReserve, lpToAccount, scyUsed, otUsed) = market.addLiquidity(
|
|
86
|
+
index,
|
|
87
|
+
scyDesired,
|
|
88
|
+
otDesired
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// initializing the market
|
|
92
|
+
if (lpToReserve != 0) {
|
|
93
|
+
market.setInitialImpliedRate(index, anchorRoot, block.timestamp);
|
|
94
|
+
_mint(address(1), lpToReserve);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_mint(receiver, lpToAccount);
|
|
98
|
+
|
|
99
|
+
if (data.length > 0) {
|
|
100
|
+
IPMarketAddRemoveCallback(msg.sender).addLiquidityCallback(
|
|
101
|
+
lpToAccount,
|
|
102
|
+
scyUsed,
|
|
103
|
+
otUsed,
|
|
104
|
+
data
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
require(market.totalOt.Uint() <= IERC20(OT).balanceOf(address(this)));
|
|
109
|
+
require(market.totalScy.Uint() <= IERC20(SCY).balanceOf(address(this)));
|
|
110
|
+
|
|
111
|
+
_writeState(market);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function removeLiquidity(
|
|
115
|
+
address receiver,
|
|
116
|
+
uint256 lpToRemove,
|
|
117
|
+
bytes calldata data
|
|
118
|
+
) external nonReentrant returns (uint256 scyToAccount, uint256 otToAccount) {
|
|
119
|
+
MarketParameters memory market = readState();
|
|
120
|
+
|
|
121
|
+
(scyToAccount, otToAccount) = market.removeLiquidity(lpToRemove);
|
|
122
|
+
|
|
123
|
+
IERC20(SCY).safeTransfer(receiver, scyToAccount);
|
|
124
|
+
IERC20(OT).safeTransfer(receiver, otToAccount);
|
|
125
|
+
|
|
126
|
+
if (data.length > 0) {
|
|
127
|
+
IPMarketAddRemoveCallback(msg.sender).removeLiquidityCallback(
|
|
128
|
+
lpToRemove,
|
|
129
|
+
scyToAccount,
|
|
130
|
+
otToAccount,
|
|
131
|
+
data
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
_burn(address(this), lpToRemove);
|
|
136
|
+
|
|
137
|
+
_writeState(market);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function swapExactOtForScy(
|
|
141
|
+
address receiver,
|
|
142
|
+
uint256 exactOtIn,
|
|
143
|
+
uint256 minScyOut,
|
|
144
|
+
bytes calldata data
|
|
145
|
+
) external nonReentrant returns (uint256 netScyOut, uint256 netScyToReserve) {
|
|
146
|
+
require(block.timestamp < expiry, "MARKET_EXPIRED");
|
|
147
|
+
|
|
148
|
+
MarketParameters memory market = readState();
|
|
149
|
+
|
|
150
|
+
(netScyOut, netScyToReserve) = market.swapExactOtForScy(
|
|
151
|
+
SCYIndexLib.newIndex(SCY),
|
|
152
|
+
exactOtIn,
|
|
153
|
+
block.timestamp
|
|
154
|
+
);
|
|
155
|
+
require(netScyOut >= minScyOut, "insufficient scy out");
|
|
156
|
+
IERC20(SCY).safeTransfer(receiver, netScyOut);
|
|
157
|
+
IERC20(SCY).safeTransfer(IPMarketFactory(factory).treasury(), netScyToReserve);
|
|
158
|
+
|
|
159
|
+
if (data.length > 0) {
|
|
160
|
+
IPMarketSwapCallback(msg.sender).swapCallback(exactOtIn.neg(), netScyOut.Int(), data);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// have received enough OT
|
|
164
|
+
require(market.totalOt.Uint() <= IERC20(OT).balanceOf(address(this)));
|
|
165
|
+
_writeState(market);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function swapScyForExactOt(
|
|
169
|
+
address receiver,
|
|
170
|
+
uint256 exactOtOut,
|
|
171
|
+
uint256 maxScyIn,
|
|
172
|
+
bytes calldata data
|
|
173
|
+
) external nonReentrant returns (uint256 netScyIn, uint256 netScyToReserve) {
|
|
174
|
+
require(block.timestamp < expiry, "MARKET_EXPIRED");
|
|
175
|
+
|
|
176
|
+
MarketParameters memory market = readState();
|
|
177
|
+
|
|
178
|
+
(netScyIn, netScyToReserve) = market.swapScyForExactOt(
|
|
179
|
+
SCYIndexLib.newIndex(SCY),
|
|
180
|
+
exactOtOut,
|
|
181
|
+
block.timestamp
|
|
182
|
+
);
|
|
183
|
+
require(netScyIn <= maxScyIn, "scy in exceed limit");
|
|
184
|
+
IERC20(OT).safeTransfer(receiver, exactOtOut);
|
|
185
|
+
IERC20(SCY).safeTransfer(IPMarketFactory(factory).treasury(), netScyToReserve);
|
|
186
|
+
|
|
187
|
+
if (data.length > 0) {
|
|
188
|
+
IPMarketSwapCallback(msg.sender).swapCallback(exactOtOut.Int(), netScyIn.neg(), data);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// have received enough SCY
|
|
192
|
+
require(market.totalScy.Uint() <= IERC20(SCY).balanceOf(address(this)));
|
|
193
|
+
_writeState(market);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/// @dev this function is just a place holder. Later on the rewards will be transferred to the liquidity minining
|
|
197
|
+
/// instead
|
|
198
|
+
function redeemScyReward() external returns (uint256[] memory outAmounts) {
|
|
199
|
+
outAmounts = ISuperComposableYield(SCY).redeemReward(
|
|
200
|
+
address(this),
|
|
201
|
+
IPMarketFactory(factory).treasury()
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/// the only non-view part in this function is the ISuperComposableYield(SCY).scyIndexCurrent()
|
|
206
|
+
function readState() public view returns (MarketParameters memory market) {
|
|
207
|
+
MarketStorage storage store = marketStorage;
|
|
208
|
+
market.totalOt = store.totalOt;
|
|
209
|
+
market.totalScy = store.totalScy;
|
|
210
|
+
market.totalLp = totalSupply().Int();
|
|
211
|
+
market.oracleRate = store.oracleRate;
|
|
212
|
+
market.reserveFeePercent = reserveFeePercent;
|
|
213
|
+
|
|
214
|
+
market.scalarRoot = scalarRoot;
|
|
215
|
+
market.feeRateRoot = feeRateRoot;
|
|
216
|
+
market.rateOracleTimeWindow = rateOracleTimeWindow;
|
|
217
|
+
market.expiry = expiry;
|
|
218
|
+
|
|
219
|
+
market.lastImpliedRate = store.lastImpliedRate;
|
|
220
|
+
market.lastTradeTime = store.lastTradeTime;
|
|
221
|
+
|
|
222
|
+
market.updateNewRateOracle(block.timestamp);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function _writeState(MarketParameters memory market) internal {
|
|
226
|
+
MarketStorage storage store = marketStorage;
|
|
227
|
+
|
|
228
|
+
store.totalOt = market.totalOt.Int128();
|
|
229
|
+
store.totalScy = market.totalScy.Int128();
|
|
230
|
+
store.lastImpliedRate = market.lastImpliedRate.Uint112();
|
|
231
|
+
store.oracleRate = market.oracleRate.Uint112();
|
|
232
|
+
store.lastTradeTime = market.lastTradeTime.Uint32();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function readTokens()
|
|
236
|
+
external
|
|
237
|
+
view
|
|
238
|
+
returns (
|
|
239
|
+
ISuperComposableYield _SCY,
|
|
240
|
+
IPOwnershipToken _OT,
|
|
241
|
+
IPYieldToken _YT
|
|
242
|
+
)
|
|
243
|
+
{
|
|
244
|
+
_SCY = ISuperComposableYield(SCY);
|
|
245
|
+
_OT = IPOwnershipToken(OT);
|
|
246
|
+
_YT = IPYieldToken(YT);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
pragma solidity 0.8.9;
|
|
3
|
+
import "openzeppelin-solidity/contracts/utils/structs/EnumerableSet.sol";
|
|
4
|
+
import "../interfaces/IPMarket.sol";
|
|
5
|
+
import "../interfaces/IPYieldContractFactory.sol";
|
|
6
|
+
import "../interfaces/IPMarketFactory.sol";
|
|
7
|
+
import "../periphery/PermissionsV2.sol";
|
|
8
|
+
import "./PendleMarket.sol";
|
|
9
|
+
|
|
10
|
+
contract PendleMarketFactory is PermissionsV2, IPMarketFactory {
|
|
11
|
+
using EnumerableSet for EnumerableSet.AddressSet;
|
|
12
|
+
|
|
13
|
+
mapping(address => EnumerableSet.AddressSet) internal otMarkets;
|
|
14
|
+
address public immutable yieldContractFactory;
|
|
15
|
+
address public treasury;
|
|
16
|
+
|
|
17
|
+
constructor(address _governanceManager, address _yieldContractFactory)
|
|
18
|
+
PermissionsV2(_governanceManager)
|
|
19
|
+
{
|
|
20
|
+
yieldContractFactory = _yieldContractFactory;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function createNewMarket(
|
|
24
|
+
address OT,
|
|
25
|
+
uint256 feeRateRoot,
|
|
26
|
+
int256 scalarRoot,
|
|
27
|
+
int256 anchorRoot,
|
|
28
|
+
uint8 reserveFeePercent,
|
|
29
|
+
uint256 rateOracleTimeWindow
|
|
30
|
+
) external returns (address market) {
|
|
31
|
+
address SCY = IPOwnershipToken(OT).SCY();
|
|
32
|
+
uint256 expiry = IPOwnershipToken(OT).expiry();
|
|
33
|
+
|
|
34
|
+
require(
|
|
35
|
+
IPYieldContractFactory(yieldContractFactory).getOT(SCY, expiry) == OT,
|
|
36
|
+
"INVALID_OT"
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
market = address(
|
|
40
|
+
new PendleMarket(
|
|
41
|
+
OT,
|
|
42
|
+
rateOracleTimeWindow,
|
|
43
|
+
feeRateRoot,
|
|
44
|
+
scalarRoot,
|
|
45
|
+
anchorRoot,
|
|
46
|
+
reserveFeePercent
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
otMarkets[address(OT)].add(market);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function setTreasury(address newTreasury) external onlyGovernance {
|
|
53
|
+
treasury = newTreasury;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function isValidMarket(address market) external view returns (bool) {
|
|
57
|
+
address OT = IPMarket(market).OT();
|
|
58
|
+
return otMarkets[OT].contains(market);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
pragma solidity 0.8.9;
|
|
3
|
+
|
|
4
|
+
import "./PendleBaseToken.sol";
|
|
5
|
+
import "../interfaces/IPOwnershipToken.sol";
|
|
6
|
+
|
|
7
|
+
contract PendleOwnershipToken is PendleBaseToken, IPOwnershipToken {
|
|
8
|
+
address public immutable SCY;
|
|
9
|
+
address public YT;
|
|
10
|
+
|
|
11
|
+
modifier onlyYT() {
|
|
12
|
+
require(msg.sender == address(YT), "ONLY_YT");
|
|
13
|
+
_;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
modifier onlyFactory() {
|
|
17
|
+
require(msg.sender == factory, "ONLY_FACTORY");
|
|
18
|
+
_;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
constructor(
|
|
22
|
+
address _SCY,
|
|
23
|
+
string memory _name,
|
|
24
|
+
string memory _symbol,
|
|
25
|
+
uint8 __decimals,
|
|
26
|
+
uint256 _expiry
|
|
27
|
+
) PendleBaseToken(_name, _symbol, __decimals, _expiry) {
|
|
28
|
+
SCY = _SCY;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function initialize(address _YT) external onlyFactory {
|
|
32
|
+
YT = _YT;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function burnByYT(address user, uint256 amount) external onlyYT {
|
|
36
|
+
_burn(user, amount);
|
|
37
|
+
emit Burn(user, amount);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function mintByYT(address user, uint256 amount) external onlyYT {
|
|
41
|
+
_mint(user, amount);
|
|
42
|
+
emit Mint(user, amount);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
pragma solidity 0.8.9;
|
|
3
|
+
pragma abicoder v2;
|
|
4
|
+
import "../../../SuperComposableYield/implementations/SCYBaseWithRewards.sol";
|
|
5
|
+
import "../../../interfaces/IAToken.sol";
|
|
6
|
+
import "../../../interfaces/IAavePool.sol";
|
|
7
|
+
import "../../../interfaces/IAaveRewardsController.sol";
|
|
8
|
+
import "./WadRayMath.sol";
|
|
9
|
+
|
|
10
|
+
contract PendleAaveV3SCY is SCYBaseWithRewards {
|
|
11
|
+
using WadRayMath for uint256;
|
|
12
|
+
using SafeERC20 for IERC20;
|
|
13
|
+
|
|
14
|
+
address public immutable underlying;
|
|
15
|
+
address public immutable pool;
|
|
16
|
+
address public immutable rewardsController;
|
|
17
|
+
address public immutable aToken;
|
|
18
|
+
|
|
19
|
+
uint256 public lastScyIndex;
|
|
20
|
+
|
|
21
|
+
// WIP: Aave reward controller can config to have more rewardsToken,
|
|
22
|
+
// hence rewardsLength should not be immutable
|
|
23
|
+
constructor(
|
|
24
|
+
string memory _name,
|
|
25
|
+
string memory _symbol,
|
|
26
|
+
uint8 __scydecimals,
|
|
27
|
+
uint8 __assetDecimals,
|
|
28
|
+
address _aavePool,
|
|
29
|
+
address _underlying,
|
|
30
|
+
address _aToken,
|
|
31
|
+
address _rewardsController
|
|
32
|
+
) SCYBaseWithRewards(_name, _symbol, __scydecimals, __assetDecimals) {
|
|
33
|
+
aToken = _aToken;
|
|
34
|
+
pool = _aavePool;
|
|
35
|
+
underlying = _underlying;
|
|
36
|
+
rewardsController = _rewardsController;
|
|
37
|
+
IERC20(underlying).safeIncreaseAllowance(aToken, type(uint256).max);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/*///////////////////////////////////////////////////////////////
|
|
41
|
+
DEPOSIT/REDEEM USING BASE TOKENS
|
|
42
|
+
//////////////////////////////////////////////////////////////*/
|
|
43
|
+
|
|
44
|
+
function _deposit(address token, uint256 amountBase)
|
|
45
|
+
internal
|
|
46
|
+
virtual
|
|
47
|
+
override
|
|
48
|
+
returns (uint256 amountScyOut)
|
|
49
|
+
{
|
|
50
|
+
// aTokenScaled -> scy is 1:1
|
|
51
|
+
if (token == aToken) {
|
|
52
|
+
amountScyOut = amountBase.rayDiv(scyIndexCurrent());
|
|
53
|
+
} else {
|
|
54
|
+
IAavePool(pool).supply(underlying, amountBase, address(this), 0);
|
|
55
|
+
_afterSendToken(underlying);
|
|
56
|
+
amountScyOut = _afterReceiveToken(aToken);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function _redeem(address token, uint256 amountScy)
|
|
61
|
+
internal
|
|
62
|
+
virtual
|
|
63
|
+
override
|
|
64
|
+
returns (uint256 amountBaseOut)
|
|
65
|
+
{
|
|
66
|
+
if (token == aToken) {
|
|
67
|
+
amountBaseOut = amountScy.rayMul(scyIndexCurrent());
|
|
68
|
+
} else {
|
|
69
|
+
uint256 amountBaseExpected = amountScy.rayMul(scyIndexCurrent());
|
|
70
|
+
IAavePool(pool).withdraw(underlying, amountBaseExpected, address(this));
|
|
71
|
+
_afterSendToken(aToken);
|
|
72
|
+
amountBaseOut = _afterReceiveToken(token);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/*///////////////////////////////////////////////////////////////
|
|
77
|
+
SCY-INDEX
|
|
78
|
+
//////////////////////////////////////////////////////////////*/
|
|
79
|
+
|
|
80
|
+
function scyIndexCurrent() public virtual override returns (uint256 res) {
|
|
81
|
+
res = IAavePool(pool).getReserveNormalizedIncome(underlying);
|
|
82
|
+
lastScyIndex = res;
|
|
83
|
+
return res;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function scyIndexStored() public view override returns (uint256 res) {
|
|
87
|
+
res = lastScyIndex;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function getRewardTokens() public view override returns (address[] memory res) {
|
|
91
|
+
return IAaveRewardsController(rewardsController).getRewardsByAsset(aToken);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/*///////////////////////////////////////////////////////////////
|
|
95
|
+
MISC FUNCTIONS FOR METADATA
|
|
96
|
+
//////////////////////////////////////////////////////////////*/
|
|
97
|
+
|
|
98
|
+
function getBaseTokens() public view virtual override returns (address[] memory res) {
|
|
99
|
+
res = new address[](2);
|
|
100
|
+
res[0] = underlying;
|
|
101
|
+
res[1] = aToken;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function isValidBaseToken(address token) public view virtual override returns (bool res) {
|
|
105
|
+
res = (token == underlying || token == aToken);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/*///////////////////////////////////////////////////////////////
|
|
109
|
+
REWARDS-RELATED
|
|
110
|
+
//////////////////////////////////////////////////////////////*/
|
|
111
|
+
|
|
112
|
+
function _redeemExternalReward() internal override {
|
|
113
|
+
address[] memory assets = new address[](1);
|
|
114
|
+
assets[0] = aToken;
|
|
115
|
+
|
|
116
|
+
IAaveRewardsController(rewardsController).claimAllRewards(assets, address(this));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/// @dev balance of aToken is saved by scaledBalanceOf instead
|
|
120
|
+
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
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function _afterSendToken(address token) internal virtual override {
|
|
133
|
+
if (token == aToken) {
|
|
134
|
+
lastBalanceOf[token] = IAToken(aToken).scaledBalanceOf(address(this));
|
|
135
|
+
} else {
|
|
136
|
+
lastBalanceOf[token] = IERC20(token).balanceOf(address(this));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
pragma solidity 0.8.9;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @title WadRayMath library
|
|
6
|
+
* @author Aave
|
|
7
|
+
* @notice Provides functions to perform calculations with Wad and Ray units
|
|
8
|
+
* @dev Provides mul and div function for wads (decimal numbers with 18 digits of precision) and rays (decimal numbers
|
|
9
|
+
* with 27 digits of precision)
|
|
10
|
+
* @dev Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down.
|
|
11
|
+
**/
|
|
12
|
+
library WadRayMath {
|
|
13
|
+
// HALF_WAD and HALF_RAY expressed with extended notation as constant with operations are not supported in Yul assembly
|
|
14
|
+
uint256 internal constant WAD = 1e18;
|
|
15
|
+
uint256 internal constant HALF_WAD = 0.5e18;
|
|
16
|
+
|
|
17
|
+
uint256 internal constant RAY = 1e27;
|
|
18
|
+
uint256 internal constant HALF_RAY = 0.5e27;
|
|
19
|
+
|
|
20
|
+
uint256 internal constant WAD_RAY_RATIO = 1e9;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @dev Multiplies two wad, rounding half up to the nearest wad
|
|
24
|
+
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
|
|
25
|
+
* @param a Wad
|
|
26
|
+
* @param b Wad
|
|
27
|
+
* @return c = a*b, in wad
|
|
28
|
+
**/
|
|
29
|
+
function wadMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
|
|
30
|
+
// to avoid overflow, a <= (type(uint256).max - HALF_WAD) / b
|
|
31
|
+
assembly {
|
|
32
|
+
if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_WAD), b))))) {
|
|
33
|
+
revert(0, 0)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
c := div(add(mul(a, b), HALF_WAD), WAD)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @dev Divides two wad, rounding half up to the nearest wad
|
|
42
|
+
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
|
|
43
|
+
* @param a Wad
|
|
44
|
+
* @param b Wad
|
|
45
|
+
* @return c = a/b, in wad
|
|
46
|
+
**/
|
|
47
|
+
function wadDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
|
|
48
|
+
// to avoid overflow, a <= (type(uint256).max - halfB) / WAD
|
|
49
|
+
assembly {
|
|
50
|
+
if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), WAD))))) {
|
|
51
|
+
revert(0, 0)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
c := div(add(mul(a, WAD), div(b, 2)), b)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @notice Multiplies two ray, rounding half up to the nearest ray
|
|
60
|
+
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
|
|
61
|
+
* @param a Ray
|
|
62
|
+
* @param b Ray
|
|
63
|
+
* @return c = a raymul b
|
|
64
|
+
**/
|
|
65
|
+
function rayMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
|
|
66
|
+
// to avoid overflow, a <= (type(uint256).max - HALF_RAY) / b
|
|
67
|
+
assembly {
|
|
68
|
+
if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_RAY), b))))) {
|
|
69
|
+
revert(0, 0)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
c := div(add(mul(a, b), HALF_RAY), RAY)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @notice Divides two ray, rounding half up to the nearest ray
|
|
78
|
+
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
|
|
79
|
+
* @param a Ray
|
|
80
|
+
* @param b Ray
|
|
81
|
+
* @return c = a raydiv b
|
|
82
|
+
**/
|
|
83
|
+
function rayDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
|
|
84
|
+
// to avoid overflow, a <= (type(uint256).max - halfB) / RAY
|
|
85
|
+
assembly {
|
|
86
|
+
if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), RAY))))) {
|
|
87
|
+
revert(0, 0)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
c := div(add(mul(a, RAY), div(b, 2)), b)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @dev Casts ray down to wad
|
|
96
|
+
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
|
|
97
|
+
* @param a Ray
|
|
98
|
+
* @return b = a converted to wad, rounded half up to the nearest wad
|
|
99
|
+
**/
|
|
100
|
+
function rayToWad(uint256 a) internal pure returns (uint256 b) {
|
|
101
|
+
assembly {
|
|
102
|
+
b := div(a, WAD_RAY_RATIO)
|
|
103
|
+
let remainder := mod(a, WAD_RAY_RATIO)
|
|
104
|
+
if iszero(lt(remainder, div(WAD_RAY_RATIO, 2))) {
|
|
105
|
+
b := add(b, 1)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @dev Converts wad up to ray
|
|
112
|
+
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
|
|
113
|
+
* @param a Wad
|
|
114
|
+
* @return b = a converted in ray
|
|
115
|
+
**/
|
|
116
|
+
function wadToRay(uint256 a) internal pure returns (uint256 b) {
|
|
117
|
+
// to avoid overflow, b/WAD_RAY_RATIO == a
|
|
118
|
+
assembly {
|
|
119
|
+
b := mul(a, WAD_RAY_RATIO)
|
|
120
|
+
|
|
121
|
+
if iszero(eq(div(b, WAD_RAY_RATIO), a)) {
|
|
122
|
+
revert(0, 0)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|