@pendle/core-v2 4.5.0 → 4.5.1-beta-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 (39) hide show
  1. package/build/artifacts/contracts/core/StandardizedYield/implementations/PendleERC20WithSupplyCapSY.sol/PendleERC20WithSupplyCapSY.dbg.json +1 -1
  2. package/build/artifacts/contracts/interfaces/IPActionMiscV3.sol/IPActionMiscV3.dbg.json +1 -1
  3. package/build/artifacts/contracts/interfaces/IPActionMiscV3.sol/IPActionMiscV3.json +1156 -34
  4. package/build/artifacts/contracts/interfaces/IPAllActionV3.sol/IPAllActionV3.dbg.json +1 -1
  5. package/build/artifacts/contracts/interfaces/IPAllActionV3.sol/IPAllActionV3.json +1183 -61
  6. package/build/artifacts/contracts/offchain-helpers/PendlePoolDeployHelper.sol/PendlePoolDeployHelper.dbg.json +1 -1
  7. package/build/artifacts/contracts/offchain-helpers/PendlePoolDeployHelper.sol/PendlePoolDeployHelper.json +2 -2
  8. package/build/artifacts/contracts/offchain-helpers/router-static/base/ActionMarketAuxStatic.sol/ActionMarketAuxStatic.dbg.json +1 -1
  9. package/build/artifacts/contracts/router/ActionAddRemoveLiqV3.sol/ActionAddRemoveLiqV3.dbg.json +1 -1
  10. package/build/artifacts/contracts/router/ActionAddRemoveLiqV3.sol/ActionAddRemoveLiqV3.json +2 -2
  11. package/build/artifacts/contracts/router/ActionMiscV3.sol/ActionMiscV3.dbg.json +1 -1
  12. package/build/artifacts/contracts/router/ActionMiscV3.sol/ActionMiscV3.json +1158 -36
  13. package/build/artifacts/contracts/router/ActionSwapPTV3.sol/ActionSwapPTV3.dbg.json +1 -1
  14. package/build/artifacts/contracts/router/ActionSwapPTV3.sol/ActionSwapPTV3.json +2 -2
  15. package/build/artifacts/contracts/router/ActionSwapYTV3.sol/ActionSwapYTV3.dbg.json +1 -1
  16. package/build/artifacts/contracts/router/ActionSwapYTV3.sol/ActionSwapYTV3.json +2 -2
  17. package/build/artifacts/contracts/router/base/ActionBase.sol/ActionBase.dbg.json +1 -1
  18. package/contracts/interfaces/IPActionMiscV3.sol +92 -0
  19. package/contracts/router/ActionMiscV3.sol +150 -36
  20. package/contracts/router/ActionSwapYTV3.sol +0 -85
  21. package/contracts/router/base/ActionBase.sol +106 -1
  22. package/deployments/merkle-distribution/2024-04-25.json +14930 -0
  23. package/package.json +1 -1
  24. package/typechain-types/ActionMiscV3.ts +573 -16
  25. package/typechain-types/IPActionMiscV3.ts +573 -16
  26. package/typechain-types/IPAllActionV3.ts +480 -0
  27. package/typechain-types/ISwellSimpleStakingERC20.ts +289 -0
  28. package/typechain-types/PendleSwellRswETHStakingSY.ts +1325 -0
  29. package/typechain-types/PendleSwellStakingERC20SY.ts +1299 -0
  30. package/typechain-types/factories/ActionAddRemoveLiqV3__factory.ts +1 -1
  31. package/typechain-types/factories/ActionMiscV3__factory.ts +1157 -35
  32. package/typechain-types/factories/ActionSwapPTV3__factory.ts +1 -1
  33. package/typechain-types/factories/ActionSwapYTV3__factory.ts +1 -1
  34. package/typechain-types/factories/IPActionMiscV3__factory.ts +1156 -34
  35. package/typechain-types/factories/IPAllActionV3__factory.ts +1183 -61
  36. package/typechain-types/factories/ISwellSimpleStakingERC20__factory.ts +226 -0
  37. package/typechain-types/factories/PendlePoolDeployHelper__factory.ts +1 -1
  38. package/typechain-types/factories/PendleSwellRswETHStakingSY__factory.ts +1106 -0
  39. package/typechain-types/factories/PendleSwellStakingERC20SY__factory.ts +1112 -0
@@ -79,18 +79,16 @@ contract ActionMiscV3 is IPActionMiscV3, ActionBase {
79
79
  address[] calldata yts,
80
80
  address[] calldata markets
81
81
  ) external {
82
- unchecked {
83
- for (uint256 i = 0; i < sys.length; ++i) {
84
- IStandardizedYield(sys[i]).claimRewards(user);
85
- }
86
-
87
- for (uint256 i = 0; i < yts.length; ++i) {
88
- IPYieldToken(yts[i]).redeemDueInterestAndRewards(user, true, true);
89
- }
90
-
91
- for (uint256 i = 0; i < markets.length; ++i) {
92
- IPMarket(markets[i]).redeemRewards(user);
93
- }
82
+ for (uint256 i = 0; i < sys.length; ++i) {
83
+ IStandardizedYield(sys[i]).claimRewards(user);
84
+ }
85
+
86
+ for (uint256 i = 0; i < yts.length; ++i) {
87
+ IPYieldToken(yts[i]).redeemDueInterestAndRewards(user, true, true);
88
+ }
89
+
90
+ for (uint256 i = 0; i < markets.length; ++i) {
91
+ IPMarket(markets[i]).redeemRewards(user);
94
92
  }
95
93
  }
96
94
 
@@ -118,40 +116,156 @@ contract ActionMiscV3 is IPActionMiscV3, ActionBase {
118
116
  netTokenOut = IStandardizedYield(SY).redeem(receiver, netSyInterm, tokenRedeemSy, minTokenOut, true);
119
117
  }
120
118
 
119
+ // TODO: need to allow exit to SY as well
120
+ // TODO: check against minOut
121
+ // double check event orders
122
+
123
+ function exitPreExpToToken(
124
+ address receiver,
125
+ address market,
126
+ uint256 netPtIn,
127
+ uint256 netYtIn,
128
+ uint256 netLpIn,
129
+ TokenOutput calldata output,
130
+ LimitOrderData calldata limit
131
+ ) external returns (uint256 totalTokenOut, ExitPreExpReturnParams memory params) {
132
+ IStandardizedYield SY;
133
+
134
+ (SY, params) = _exitPreExpToSy(true, address(0), market, netPtIn, netYtIn, netLpIn, limit);
135
+ totalTokenOut = _redeemSyToToken(receiver, address(SY), params.totalSyOut, output, false);
136
+
137
+ emit ExitPreExpToToken(msg.sender, market, output.tokenOut, receiver, netLpIn, totalTokenOut, params);
138
+ }
139
+
140
+ function exitPreExpToSy(
141
+ address receiver,
142
+ address market,
143
+ uint256 netPtIn,
144
+ uint256 netYtIn,
145
+ uint256 netLpIn,
146
+ uint256 minSyOut,
147
+ LimitOrderData calldata limit
148
+ ) external returns (ExitPreExpReturnParams memory params) {
149
+ (, params) = _exitPreExpToSy(false, receiver, market, netPtIn, netYtIn, netLpIn, limit);
150
+ require(params.totalSyOut >= minSyOut, "Slippage: INSUFFICIENT_SY_OUT");
151
+
152
+ emit ExitPreExpToSy(msg.sender, market, receiver, netLpIn, params);
153
+ }
154
+
155
+ function _exitPreExpToSy(
156
+ bool setReceiverToSy,
157
+ address receiver,
158
+ address market,
159
+ uint256 netPtIn,
160
+ uint256 netYtIn,
161
+ uint256 netLpIn,
162
+ LimitOrderData calldata limit
163
+ ) internal returns (IStandardizedYield SY, ExitPreExpReturnParams memory p) {
164
+ IPPrincipalToken PT;
165
+ IPYieldToken YT;
166
+ (SY, PT, YT) = IPMarket(market).readTokens();
167
+
168
+ if (setReceiverToSy) receiver = address(SY);
169
+
170
+ if (netLpIn > 0) {
171
+ _transferFrom(IERC20(market), msg.sender, market, netLpIn);
172
+ (p.netSyFromRemove, p.netPtFromRemove) = IPMarket(market).burn(receiver, address(this), netLpIn);
173
+ }
174
+
175
+ if (netPtIn > 0) {
176
+ _transferIn(address(PT), address(this), netPtIn);
177
+ }
178
+
179
+ p.netPyRedeem = PMath.min(p.netPtFromRemove + netPtIn, netYtIn);
180
+
181
+ if (p.netPyRedeem > 0) {
182
+ _transferOut(address(PT), address(YT), p.netPyRedeem);
183
+ _transferFrom(YT, msg.sender, address(YT), p.netPyRedeem);
184
+ p.netSyFromRedeem = IPYieldToken(YT).redeemPY(receiver);
185
+ }
186
+
187
+ p.netPtSwap = p.netPtFromRemove + netPtIn - p.netPyRedeem;
188
+ p.netYtSwap = netYtIn - p.netPyRedeem;
189
+
190
+ if (p.netPtSwap > 0) {
191
+ address ptEntry = _entry_swapExactPtForSy(market, limit);
192
+ if (ptEntry != address(this)) _transferOut(address(PT), ptEntry, p.netPtSwap);
193
+ (p.netSyFromSwap, p.netSyFee) = _swapExactPtForSy(receiver, market, p.netPtSwap, 0, limit);
194
+ } else if (p.netYtSwap > 0) {
195
+ _transferFrom(YT, msg.sender, _entry_swapExactYtForSy(YT, limit), p.netYtSwap);
196
+ (p.netSyFromSwap, p.netSyFee) = _swapExactYtForSy(receiver, market, SY, YT, p.netYtSwap, 0, limit);
197
+ }
198
+
199
+ p.totalSyOut = p.netSyFromRemove + p.netSyFromRedeem + p.netSyFromSwap;
200
+ }
201
+
202
+ function exitPostExpToToken(
203
+ address receiver,
204
+ address market,
205
+ uint256 netPtIn,
206
+ uint256 netLpIn,
207
+ TokenOutput calldata output
208
+ ) external returns (uint256 totalTokenOut, ExitPostExpReturnParams memory params) {
209
+ IStandardizedYield SY;
210
+
211
+ (SY, params) = _exitPostExpToSy(receiver, market, netPtIn, netLpIn);
212
+ totalTokenOut = _redeemSyToToken(receiver, address(SY), params.totalSyOut, output, false);
213
+
214
+ emit ExitPostExpToToken(msg.sender, market, output.tokenOut, receiver, netLpIn, totalTokenOut, params);
215
+ }
216
+
217
+ function exitPostExpToSy(
218
+ address receiver,
219
+ address market,
220
+ uint256 netPtIn,
221
+ uint256 netLpIn,
222
+ uint256 minSyOut
223
+ ) external returns (ExitPostExpReturnParams memory params) {
224
+ (, params) = _exitPostExpToSy(receiver, market, netPtIn, netLpIn);
225
+ require(params.totalSyOut >= minSyOut, "Slippage: INSUFFICIENT_SY_OUT");
226
+
227
+ emit ExitPostExpToSy(msg.sender, market, receiver, netLpIn, params);
228
+ }
229
+
230
+ function _exitPostExpToSy(
231
+ address receiver,
232
+ address market,
233
+ uint256 netPtIn,
234
+ uint256 netLpIn
235
+ ) internal returns (IStandardizedYield SY, ExitPostExpReturnParams memory p) {
236
+ IPPrincipalToken PT;
237
+ IPYieldToken YT;
238
+ (SY, PT, YT) = IPMarket(market).readTokens();
239
+
240
+ if (netLpIn > 0) {
241
+ _transferFrom(IERC20(market), msg.sender, market, netLpIn);
242
+ (p.netSyFromRemove, p.netPtFromRemove) = IPMarket(market).burn(receiver, address(YT), netLpIn);
243
+ }
244
+
245
+ if (netPtIn > 0) {
246
+ _transferFrom(PT, msg.sender, address(YT), netPtIn);
247
+ }
248
+
249
+ p.netPtRedeem = p.netPtFromRemove + netPtIn;
250
+ p.netSyFromRedeem = IPYieldToken(YT).redeemPY(receiver);
251
+
252
+ p.totalSyOut = p.netSyFromRemove + p.netSyFromRedeem;
253
+ }
254
+
121
255
  // ----------------- MISC FUNCTIONS -----------------
122
256
 
123
257
  function boostMarkets(address[] memory markets) external {
124
- for (uint256 i = 0; i < markets.length; ) {
258
+ for (uint256 i = 0; i < markets.length; i++) {
125
259
  IPMarket(markets[i]).transferFrom(msg.sender, markets[i], 0);
126
- unchecked {
127
- i++;
128
- }
129
260
  }
130
261
  }
131
262
 
132
263
  function multicall(Call3[] calldata calls) external payable returns (Result[] memory res) {
133
264
  uint256 length = calls.length;
134
265
  res = new Result[](length);
135
- Call3 calldata call;
136
- for (uint256 i = 0; i < length; ) {
137
- call = calls[i];
138
-
139
- // delegatecall to itself, it turns allowing invoking functions from other actions
140
- (bool success, bytes memory result) = address(this).delegatecall(call.callData);
141
-
142
- if (!success && !call.allowFailure) {
143
- assembly {
144
- // We use Yul's revert() to bubble up errors from the target contract.
145
- revert(add(32, result), mload(result))
146
- }
147
- }
148
-
149
- res[i].success = success;
150
- res[i].returnData = result;
151
-
152
- unchecked {
153
- ++i;
154
- }
266
+ for (uint256 i = 0; i < length; i++) {
267
+ (bool success, bytes memory result) = _delegateToSelf(calls[i].callData, calls[i].allowFailure);
268
+ res[i] = Result(success, result);
155
269
  }
156
270
  }
157
271
 
@@ -52,51 +52,6 @@ contract ActionSwapYTV3 is CallbackHelper, IPActionSwapYTV3, ActionBase {
52
52
  emit SwapYtAndSy(msg.sender, market, receiver, netYtOut.Int(), exactSyIn.neg());
53
53
  }
54
54
 
55
- function _entry_swapExactSyForYt(IPYieldToken YT, LimitOrderData calldata limit) internal view returns (address) {
56
- return !_isEmptyLimit(limit) ? address(this) : address(YT);
57
- }
58
-
59
- function _swapExactSyForYt(
60
- address receiver,
61
- address market,
62
- IStandardizedYield SY,
63
- IPYieldToken YT,
64
- uint256 exactSyIn,
65
- uint256 minYtOut,
66
- ApproxParams calldata guessYtOut,
67
- LimitOrderData calldata limit
68
- ) internal returns (uint256 netYtOut, uint256 netSyFee) {
69
- uint256 netSyLeft = exactSyIn;
70
- bool doMarketOrder = true;
71
-
72
- if (!_isEmptyLimit(limit)) {
73
- (netSyLeft, netYtOut, netSyFee, doMarketOrder) = _fillLimit(receiver, SY, netSyLeft, limit);
74
- if (doMarketOrder) {
75
- _transferOut(address(SY), address(YT), netSyLeft);
76
- }
77
- }
78
-
79
- if (doMarketOrder) {
80
- (uint256 netYtOutMarket, ) = _readMarket(market).approxSwapExactSyForYt(
81
- YT.newIndex(),
82
- netSyLeft,
83
- block.timestamp,
84
- guessYtOut
85
- );
86
-
87
- (, uint256 netSyFeeMarket) = IPMarket(market).swapExactPtForSy(
88
- address(YT),
89
- netYtOutMarket, // exactPtIn = netYtOut
90
- _encodeSwapExactSyForYt(receiver, YT)
91
- );
92
-
93
- netYtOut += netYtOutMarket;
94
- netSyFee += netSyFeeMarket;
95
- }
96
-
97
- if (netYtOut < minYtOut) revert("Slippage: INSUFFICIENT_YT_OUT");
98
- }
99
-
100
55
  // ------------------ SWAP TOKEN FOR TOKEN ------------------
101
56
 
102
57
  function swapExactYtForToken(
@@ -138,46 +93,6 @@ contract ActionSwapYTV3 is CallbackHelper, IPActionSwapYTV3, ActionBase {
138
93
  emit SwapYtAndSy(msg.sender, market, receiver, exactYtIn.neg(), netSyOut.Int());
139
94
  }
140
95
 
141
- function _entry_swapExactYtForSy(IPYieldToken YT, LimitOrderData calldata limit) internal view returns (address) {
142
- return !_isEmptyLimit(limit) ? address(this) : address(YT);
143
- }
144
-
145
- function _swapExactYtForSy(
146
- address receiver,
147
- address market,
148
- IStandardizedYield SY,
149
- IPYieldToken YT,
150
- uint256 exactYtIn,
151
- uint256 minSyOut,
152
- LimitOrderData calldata limit
153
- ) internal returns (uint256 netSyOut, uint256 netSyFee) {
154
- uint256 netYtLeft = exactYtIn;
155
- bool doMarketOrder = true;
156
-
157
- if (!_isEmptyLimit(limit)) {
158
- (netYtLeft, netSyOut, netSyFee, doMarketOrder) = _fillLimit(receiver, YT, netYtLeft, limit);
159
- if (doMarketOrder) {
160
- _transferOut(address(YT), address(YT), netYtLeft);
161
- }
162
- }
163
-
164
- if (doMarketOrder) {
165
- uint256 preSyBalance = SY.balanceOf(receiver);
166
-
167
- (, uint256 netSyFeeMarket) = IPMarket(market).swapSyForExactPt(
168
- address(YT),
169
- netYtLeft, // exactPtOut = netYtLeft
170
- _encodeSwapYtForSy(receiver, YT)
171
- );
172
-
173
- // avoid stack issue
174
- netSyFee += netSyFeeMarket;
175
- netSyOut += SY.balanceOf(receiver) - preSyBalance;
176
- }
177
-
178
- if (netSyOut < minSyOut) revert("Slippage: INSUFFICIENT_SY_OUT");
179
- }
180
-
181
96
  // ------------------ SWAP PT FOR YT ------------------
182
97
 
183
98
  function swapExactPtForYt(
@@ -10,8 +10,10 @@ import "../../router/base/MarketApproxLib.sol";
10
10
 
11
11
  import "../../core/libraries/Errors.sol";
12
12
  import "../swap-aggregator/IPSwapAggregator.sol";
13
+ import "./CallbackHelper.sol";
13
14
 
14
- abstract contract ActionBase is TokenHelper, IPLimitOrderType {
15
+ abstract contract ActionBase is TokenHelper, CallbackHelper, IPLimitOrderType {
16
+ using MarketApproxPtInLib for MarketState;
15
17
  using MarketApproxPtOutLib for MarketState;
16
18
  using PMath for uint256;
17
19
  using PYIndexLib for IPYieldToken;
@@ -236,6 +238,93 @@ abstract contract ActionBase is TokenHelper, IPLimitOrderType {
236
238
  if (netPtOut < minPtOut) revert("Slippage: INSUFFICIENT_PT_OUT");
237
239
  }
238
240
 
241
+ // ----------------- YT SWAP -----------------
242
+
243
+ function _entry_swapExactYtForSy(IPYieldToken YT, LimitOrderData calldata limit) internal view returns (address) {
244
+ return !_isEmptyLimit(limit) ? address(this) : address(YT);
245
+ }
246
+
247
+ function _swapExactYtForSy(
248
+ address receiver,
249
+ address market,
250
+ IStandardizedYield SY,
251
+ IPYieldToken YT,
252
+ uint256 exactYtIn,
253
+ uint256 minSyOut,
254
+ LimitOrderData calldata limit
255
+ ) internal returns (uint256 netSyOut, uint256 netSyFee) {
256
+ uint256 netYtLeft = exactYtIn;
257
+ bool doMarketOrder = true;
258
+
259
+ if (!_isEmptyLimit(limit)) {
260
+ (netYtLeft, netSyOut, netSyFee, doMarketOrder) = _fillLimit(receiver, YT, netYtLeft, limit);
261
+ if (doMarketOrder) {
262
+ _transferOut(address(YT), address(YT), netYtLeft);
263
+ }
264
+ }
265
+
266
+ if (doMarketOrder) {
267
+ uint256 preSyBalance = SY.balanceOf(receiver);
268
+
269
+ (, uint256 netSyFeeMarket) = IPMarket(market).swapSyForExactPt(
270
+ address(YT),
271
+ netYtLeft, // exactPtOut = netYtLeft
272
+ _encodeSwapYtForSy(receiver, YT)
273
+ );
274
+
275
+ // avoid stack issue
276
+ netSyFee += netSyFeeMarket;
277
+ netSyOut += SY.balanceOf(receiver) - preSyBalance;
278
+ }
279
+
280
+ if (netSyOut < minSyOut) revert("Slippage: INSUFFICIENT_SY_OUT");
281
+ }
282
+
283
+ function _entry_swapExactSyForYt(IPYieldToken YT, LimitOrderData calldata limit) internal view returns (address) {
284
+ return !_isEmptyLimit(limit) ? address(this) : address(YT);
285
+ }
286
+
287
+ function _swapExactSyForYt(
288
+ address receiver,
289
+ address market,
290
+ IStandardizedYield SY,
291
+ IPYieldToken YT,
292
+ uint256 exactSyIn,
293
+ uint256 minYtOut,
294
+ ApproxParams calldata guessYtOut,
295
+ LimitOrderData calldata limit
296
+ ) internal returns (uint256 netYtOut, uint256 netSyFee) {
297
+ uint256 netSyLeft = exactSyIn;
298
+ bool doMarketOrder = true;
299
+
300
+ if (!_isEmptyLimit(limit)) {
301
+ (netSyLeft, netYtOut, netSyFee, doMarketOrder) = _fillLimit(receiver, SY, netSyLeft, limit);
302
+ if (doMarketOrder) {
303
+ _transferOut(address(SY), address(YT), netSyLeft);
304
+ }
305
+ }
306
+
307
+ if (doMarketOrder) {
308
+ (uint256 netYtOutMarket, ) = _readMarket(market).approxSwapExactSyForYt(
309
+ YT.newIndex(),
310
+ netSyLeft,
311
+ block.timestamp,
312
+ guessYtOut
313
+ );
314
+
315
+ (, uint256 netSyFeeMarket) = IPMarket(market).swapExactPtForSy(
316
+ address(YT),
317
+ netYtOutMarket, // exactPtIn = netYtOut
318
+ _encodeSwapExactSyForYt(receiver, YT)
319
+ );
320
+
321
+ netYtOut += netYtOutMarket;
322
+ netSyFee += netSyFeeMarket;
323
+ }
324
+
325
+ if (netYtOut < minYtOut) revert("Slippage: INSUFFICIENT_YT_OUT");
326
+ }
327
+
239
328
  // ----------------- LIMIT ORDERS -----------------
240
329
  function _fillLimit(
241
330
  address receiver,
@@ -284,4 +373,20 @@ abstract contract ActionBase is TokenHelper, IPLimitOrderType {
284
373
  function _isEmptyLimit(LimitOrderData calldata a) internal pure returns (bool) {
285
374
  return a.normalFills.length == 0 && a.flashFills.length == 0;
286
375
  }
376
+
377
+ // ----------------- DELEGATE CALL -----------------
378
+
379
+ function _delegateToSelf(
380
+ bytes memory data,
381
+ bool allowFailure
382
+ ) internal returns (bool success, bytes memory result) {
383
+ (success, result) = address(this).delegatecall(data);
384
+
385
+ if (!success && !allowFailure) {
386
+ assembly {
387
+ // We use Yul's revert() to bubble up errors from the target contract.
388
+ revert(add(32, result), mload(result))
389
+ }
390
+ }
391
+ }
287
392
  }