@@ -25,6 +25,8 @@ import { SafeCast } from "@openzeppelin/contracts/utils/SafeCast.sol";
25
25
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol " ;
26
26
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol " ;
27
27
28
+ import { IBalancerVault } from "../interfaces/IBalancerVault.sol " ;
29
+ import { IMorpho } from "../interfaces/IMorpho.sol " ;
28
30
import { FlashLoanSimpleReceiverBase } from "../lib/FlashLoanSimpleReceiverBase.sol " ;
29
31
import { IPoolAddressesProvider } from "../interfaces/IPoolAddressesProvider.sol " ;
30
32
@@ -39,7 +41,7 @@ import { ITradeModule } from "../interfaces/ITradeModule.sol";
39
41
import { PreciseUnitMath } from "../lib/PreciseUnitMath.sol " ;
40
42
41
43
/**
42
- * @title AaveMigrationExtension
44
+ * @title MigrationExtension
43
45
* @author Index Coop
44
46
* @notice This extension facilitates the migration of a SetToken's position from an unwrapped collateral
45
47
* asset to another SetToken that consists solely of Aave's wrapped collateral asset. The migration is
@@ -49,7 +51,7 @@ import { PreciseUnitMath } from "../lib/PreciseUnitMath.sol";
49
51
* redeeming any excess wrapped SetToken. This process is specifically designed to efficiently migrate
50
52
* the SetToken's collateral using only the TradeModule on the SetToken.
51
53
*/
52
- contract AaveMigrationExtension is BaseExtension , FlashLoanSimpleReceiverBase , IERC721Receiver {
54
+ contract MigrationExtension is BaseExtension , FlashLoanSimpleReceiverBase , IERC721Receiver {
53
55
using PreciseUnitMath for uint256 ;
54
56
using SafeCast for int256 ;
55
57
using SafeERC20 for IERC20 ;
@@ -81,13 +83,15 @@ contract AaveMigrationExtension is BaseExtension, FlashLoanSimpleReceiverBase, I
81
83
ITradeModule public immutable tradeModule;
82
84
IDebtIssuanceModule public immutable issuanceModule;
83
85
INonfungiblePositionManager public immutable nonfungiblePositionManager;
86
+ IMorpho public immutable morpho;
87
+ IBalancerVault public immutable balancer;
84
88
85
89
uint256 [] public tokenIds; // UniV3 LP Token IDs
86
90
87
91
/* ============ Constructor ============ */
88
92
89
93
/**
90
- * @notice Initializes the AaveMigrationExtension with immutable migration variables.
94
+ * @notice Initializes the MigrationExtension with immutable migration variables.
91
95
* @param _manager BaseManager contract for managing the SetToken's operations and permissions.
92
96
* @param _underlyingToken Address of the underlying token to be migrated.
93
97
* @param _aaveToken Address of Aave's wrapped collateral asset.
@@ -105,7 +109,9 @@ contract AaveMigrationExtension is BaseExtension, FlashLoanSimpleReceiverBase, I
105
109
ITradeModule _tradeModule ,
106
110
IDebtIssuanceModule _issuanceModule ,
107
111
INonfungiblePositionManager _nonfungiblePositionManager ,
108
- IPoolAddressesProvider _addressProvider
112
+ IPoolAddressesProvider _addressProvider ,
113
+ IMorpho _morpho ,
114
+ IBalancerVault _balancer
109
115
)
110
116
public
111
117
BaseExtension (_manager)
@@ -119,6 +125,8 @@ contract AaveMigrationExtension is BaseExtension, FlashLoanSimpleReceiverBase, I
119
125
tradeModule = _tradeModule;
120
126
issuanceModule = _issuanceModule;
121
127
nonfungiblePositionManager = _nonfungiblePositionManager;
128
+ morpho = _morpho;
129
+ balancer = _balancer;
122
130
}
123
131
124
132
/* ========== External Functions ========== */
@@ -258,12 +266,13 @@ contract AaveMigrationExtension is BaseExtension, FlashLoanSimpleReceiverBase, I
258
266
/**
259
267
* @notice OPERATOR ONLY: Migrates a SetToken's position from an unwrapped collateral asset to another SetToken
260
268
* that consists solely of Aave's wrapped collateral asset
269
+ * using Aave Flashloan
261
270
* @param _decodedParams The decoded migration parameters.
262
271
* @param _underlyingLoanAmount The amount of unwrapped collateral asset to be borrowed via flash loan.
263
272
* @param _maxSubsidy The maximum amount of unwrapped collateral asset to be transferred to the Extension as a subsidy.
264
273
* @return underlyingOutputAmount The amount of unwrapped collateral asset returned to the operator.
265
274
*/
266
- function migrate (
275
+ function migrateAave (
267
276
DecodedParams memory _decodedParams ,
268
277
uint256 _underlyingLoanAmount ,
269
278
uint256 _maxSubsidy
@@ -293,6 +302,109 @@ contract AaveMigrationExtension is BaseExtension, FlashLoanSimpleReceiverBase, I
293
302
underlyingOutputAmount = _returnExcessUnderlying ();
294
303
}
295
304
305
+ /**
306
+ * @notice OPERATOR ONLY: Migrates a SetToken's position from an unwrapped collateral asset to another SetToken
307
+ * that consists solely of Aave's wrapped collateral asset
308
+ * using Balancer Flashloan
309
+ * @param _decodedParams The decoded migration parameters.
310
+ * @param _underlyingLoanAmount The amount of unwrapped collateral asset to be borrowed via flash loan.
311
+ * @param _maxSubsidy The maximum amount of unwrapped collateral asset to be transferred to the Extension as a subsidy.
312
+ * @return underlyingOutputAmount The amount of unwrapped collateral asset returned to the operator.
313
+ */
314
+ function migrateBalancer (
315
+ DecodedParams memory _decodedParams ,
316
+ uint256 _underlyingLoanAmount ,
317
+ uint256 _maxSubsidy
318
+ )
319
+ external
320
+ onlyOperator
321
+ returns (uint256 underlyingOutputAmount )
322
+ {
323
+ // Subsidize the migration
324
+ if (_maxSubsidy > 0 ) {
325
+ underlyingToken.transferFrom (msg .sender , address (this ), _maxSubsidy);
326
+ }
327
+
328
+ // Encode migration parameters for flash loan callback
329
+ bytes memory params = abi.encode (_decodedParams);
330
+ address [] memory tokens = new address [](1 );
331
+ tokens[0 ] = address (underlyingToken);
332
+ uint256 [] memory amounts = new uint256 [](1 );
333
+ amounts[0 ] = _underlyingLoanAmount;
334
+
335
+ // Request flash loan for the underlying token
336
+ balancer.flashLoan (address (this ), tokens, amounts, params);
337
+
338
+ // Return remaining underlying token to the operator
339
+ underlyingOutputAmount = _returnExcessUnderlying ();
340
+ }
341
+
342
+ /**
343
+ * @dev Callback function for Balancer flashloan
344
+ */
345
+ function receiveFlashLoan (
346
+ IERC20 [] memory tokens ,
347
+ uint256 [] memory amounts ,
348
+ uint256 [] memory feeAmounts ,
349
+ bytes memory params
350
+ ) external {
351
+ require (msg .sender == address (balancer));
352
+ // Decode parameters and migrate
353
+ DecodedParams memory decodedParams = abi.decode (params, (DecodedParams));
354
+ _migrate (decodedParams);
355
+
356
+ underlyingToken.transfer (address (balancer), amounts[0 ] + feeAmounts[0 ]);
357
+ }
358
+
359
+
360
+ /**
361
+ * @notice OPERATOR ONLY: Migrates a SetToken's position from an unwrapped collateral asset to another SetToken
362
+ * that consists solely of Aave's wrapped collateral asset
363
+ * using Morpho Flashloan
364
+ * @param _decodedParams The decoded migration parameters.
365
+ * @param _underlyingLoanAmount The amount of unwrapped collateral asset to be borrowed via flash loan.
366
+ * @param _maxSubsidy The maximum amount of unwrapped collateral asset to be transferred to the Extension as a subsidy.
367
+ * @return underlyingOutputAmount The amount of unwrapped collateral asset returned to the operator.
368
+ */
369
+ function migrateMorpho (
370
+ DecodedParams memory _decodedParams ,
371
+ uint256 _underlyingLoanAmount ,
372
+ uint256 _maxSubsidy
373
+ )
374
+ external
375
+ onlyOperator
376
+ returns (uint256 underlyingOutputAmount )
377
+ {
378
+ // Subsidize the migration
379
+ if (_maxSubsidy > 0 ) {
380
+ underlyingToken.transferFrom (msg .sender , address (this ), _maxSubsidy);
381
+ }
382
+
383
+ // Encode migration parameters for flash loan callback
384
+ bytes memory params = abi.encode (_decodedParams);
385
+
386
+ // Request flash loan for the underlying token
387
+ morpho.flashLoan (address (underlyingToken), _underlyingLoanAmount, params);
388
+
389
+ // Return remaining underlying token to the operator
390
+ underlyingOutputAmount = _returnExcessUnderlying ();
391
+ }
392
+
393
+ /**
394
+ * @dev Callback function for Morpho Flashloan
395
+ */
396
+ function onMorphoFlashLoan (uint256 assets , bytes calldata params ) external
397
+ {
398
+ require (msg .sender == address (morpho), "MigrationExtension: invalid flashloan sender " );
399
+
400
+ // Decode parameters and migrate
401
+ DecodedParams memory decodedParams = abi.decode (params, (DecodedParams));
402
+ _migrate (decodedParams);
403
+
404
+ underlyingToken.approve (address (morpho), assets);
405
+ }
406
+
407
+
296
408
/**
297
409
* @dev Callback function for Aave V3 flash loan, executed post-loan. It decodes the provided parameters, conducts the migration, and repays the flash loan.
298
410
* @param amount The amount borrowed.
0 commit comments