Skip to content

Commit ebb67ec

Browse files
committed
swap and repay using flash loans added
1 parent 177ae15 commit ebb67ec

File tree

2 files changed

+93
-122
lines changed

2 files changed

+93
-122
lines changed

contracts/adapters/BaseParaSwapAdapter.sol

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable {
8585
return LENDING_POOL.getReserveData(asset);
8686
}
8787

88+
function _pullATokenAndWithdraw(
89+
address reserve,
90+
address user,
91+
uint256 amount,
92+
PermitSignature memory permitSignature
93+
) internal {
94+
IERC20WithPermit reserveAToken =
95+
IERC20WithPermit(_getReserveData(address(reserve)).aTokenAddress);
96+
_pullATokenAndWithdraw(reserve, reserveAToken, user, amount, permitSignature);
97+
}
98+
8899
/**
89100
* @dev Pull the ATokens from the user
90101
* @param reserve address of the asset

contracts/adapters/ParaSwapRepayAdapter.sol

Lines changed: 82 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -40,41 +40,60 @@ contract ParaSwapRepayAdapter is BaseParaSwapBuyAdapter, ReentrancyGuard {
4040
* and repay the flash loan.
4141
* Supports only one asset on the flash loan.
4242
* @param assets Address of debt asset
43-
* @param amounts Amount of the debt to be repaid
43+
* @param amounts Amount of the debt to be repaid, or maximum amount when repaying entire debt
4444
* @param premiums Fee of the flash loan
4545
* @param initiator Address of the user
4646
* @param params Additional variadic field to include extra params. Expected parameters:
47-
* address collateralAsset Address of the reserve to be swapped
48-
* uint256 collateralAmount Amount of reserve to be swapped
47+
* IERC20Detailed collateralAsset Address of the reserve to be swapped
48+
* uint256 collateralAmount max Amount of the collateral to be swapped
4949
* uint256 rateMode Rate modes of the debt to be repaid
50-
* uint256 permitAmount Amount for the permit signature
5150
* uint256 deadline Deadline for the permit signature
52-
* uint8 v V param for the permit signature
53-
* bytes32 r R param for the permit signature
54-
* bytes32 s S param for the permit signature
51+
* uint256 debtRateMode Rate mode of the debt to be repaid
52+
* bytes paraswapData Paraswap Data
53+
* * bytes buyCallData Call data for augustus
54+
* * IParaSwapAugustus augustus Address of Augustus Swapper
55+
* PermitSignature permitParams Struct containing the permit signatures, set to all zeroes if not used
5556
*/
5657
function executeOperation(
5758
address[] calldata assets,
5859
uint256[] calldata amounts,
5960
uint256[] calldata premiums,
6061
address initiator,
6162
bytes calldata params
62-
) external override returns (bool) {
63+
) external override nonReentrant returns (bool) {
6364
require(msg.sender == address(LENDING_POOL), 'CALLER_MUST_BE_LENDING_POOL');
6465

65-
RepayParams memory decodedParams = _decodeParams(params);
66+
require(
67+
assets.length == 1 && amounts.length == 1 && premiums.length == 1,
68+
'FLASHLOAN_MULTIPLE_ASSETS_NOT_SUPPORTED'
69+
);
70+
71+
uint256 debtRepayAmount = amounts[0];
72+
uint256 premium = premiums[0];
73+
address initiatorLocal = initiator;
6674

67-
/**_swapAndRepay(
68-
decodedParams.collateralAsset,
69-
assets[0],
70-
amounts[0],
71-
decodedParams.collateralAmount,
72-
decodedParams.rateMode,
73-
initiator,
74-
premiums[0],
75-
decodedParams.permitSignature,
76-
decodedParams.useEthPath
77-
);*/
75+
IERC20Detailed debtAsset = IERC20Detailed(assets[0]);
76+
(
77+
IERC20Detailed collateralAsset,
78+
uint256 collateralAmount,
79+
uint256 buyAllBalanceOffset,
80+
uint256 debtRateMode,
81+
bytes memory paraswapData,
82+
PermitSignature memory permitParams
83+
) = abi.decode(params, (IERC20Detailed, uint256, uint256, uint256, bytes, PermitSignature));
84+
85+
_swapAndRepay(
86+
buyAllBalanceOffset,
87+
paraswapData,
88+
permitParams,
89+
debtRepayAmount,
90+
premium,
91+
initiatorLocal,
92+
collateralAsset,
93+
debtAsset,
94+
collateralAmount,
95+
debtRateMode
96+
);
7897

7998
return true;
8099
}
@@ -104,30 +123,24 @@ contract ParaSwapRepayAdapter is BaseParaSwapBuyAdapter, ReentrancyGuard {
104123
bytes calldata paraswapData,
105124
PermitSignature calldata permitSignature
106125
) external nonReentrant {
107-
IERC20WithPermit aToken =
108-
IERC20WithPermit(_getReserveData(address(collateralAsset)).aTokenAddress);
109-
110126
DataTypes.ReserveData memory debtReserveData = _getReserveData(address(debtAsset));
111127

112128
address debtToken =
113129
DataTypes.InterestRateMode(debtRateMode) == DataTypes.InterestRateMode.STABLE
114130
? debtReserveData.stableDebtTokenAddress
115131
: debtReserveData.variableDebtTokenAddress;
116132

133+
uint256 currentDebt = IERC20(debtToken).balanceOf(msg.sender);
134+
117135
if (buyAllBalanceOffset != 0) {
118-
uint256 currentDebt = IERC20(debtToken).balanceOf(msg.sender);
119136
require(currentDebt <= debtRepayAmount, 'INSUFFICIENT_AMOUNT_TO_REPAY');
120137
debtRepayAmount = currentDebt;
138+
} else {
139+
require(debtRepayAmount <= currentDebt, 'INVALID_DEBT_REPAY_AMOUNT');
121140
}
122141

123142
// Pull aTokens from user
124-
_pullATokenAndWithdraw(
125-
address(collateralAsset),
126-
aToken,
127-
msg.sender,
128-
collateralAmount,
129-
permitSignature
130-
);
143+
_pullATokenAndWithdraw(address(collateralAsset), msg.sender, collateralAmount, permitSignature);
131144
//buy debt asset using collateral asset
132145
uint256 amountSold =
133146
_buyOnParaSwap(
@@ -154,118 +167,65 @@ contract ParaSwapRepayAdapter is BaseParaSwapBuyAdapter, ReentrancyGuard {
154167

155168
/**
156169
* @dev Perform the repay of the debt, pulls the initiator collateral and swaps to repay the flash loan
157-
*
170+
* @param buyAllBalanceOffset Set to offset of fromAmount in Augustus calldata if wanting to swap all balance, otherwise 0
171+
* @param paraswapData Paraswap data
172+
* @param permitSignature struct containing the permit signature
173+
* @param debtRepayAmount Amount of the debt to be repaid, or maximum amount when repaying entire debt(flash loan amount
174+
* @param premium Fee of the flash loan
175+
* @param initiator Address of the user
158176
* @param collateralAsset Address of token to be swapped
159177
* @param debtAsset Address of debt token to be received from the swap
160-
* @param amount Amount of the debt to be repaid
161178
* @param collateralAmount Amount of the reserve to be swapped
162179
* @param rateMode Rate mode of the debt to be repaid
163-
* @param initiator Address of the user
164-
* @param premium Fee of the flash loan
165-
* @param permitSignature struct containing the permit signature
166180
*/
167-
/**function _swapAndRepay(
168-
address collateralAsset,
169-
address debtAsset,
170-
uint256 amount,
171-
uint256 collateralAmount,
172-
uint256 rateMode,
173-
address initiator,
174-
uint256 premium,
181+
182+
function _swapAndRepay(
183+
uint256 buyAllBalanceOffset,
184+
bytes memory paraswapData,
175185
PermitSignature memory permitSignature,
176-
bool useEthPath
186+
uint256 debtRepayAmount,
187+
uint256 premium,
188+
address initiator,
189+
IERC20Detailed collateralAsset,
190+
IERC20Detailed debtAsset,
191+
uint256 collateralAmount,
192+
uint256 rateMode
177193
) internal {
178-
DataTypes.ReserveData memory collateralReserveData = _getReserveData(collateralAsset);
179-
180194
// Repay debt. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix.
181195
IERC20(debtAsset).safeApprove(address(LENDING_POOL), 0);
182-
IERC20(debtAsset).safeApprove(address(LENDING_POOL), amount);
196+
IERC20(debtAsset).safeApprove(address(LENDING_POOL), debtRepayAmount);
183197
uint256 repaidAmount = IERC20(debtAsset).balanceOf(address(this));
184-
LENDING_POOL.repay(debtAsset, amount, rateMode, initiator);
198+
LENDING_POOL.repay(address(debtAsset), debtRepayAmount, rateMode, initiator);
185199
repaidAmount = repaidAmount.sub(IERC20(debtAsset).balanceOf(address(this)));
186200

187-
if (collateralAsset != debtAsset) {
188-
uint256 maxCollateralToSwap = collateralAmount;
189-
if (repaidAmount < amount) {
190-
maxCollateralToSwap = maxCollateralToSwap.mul(repaidAmount).div(amount);
191-
}
201+
uint256 neededForFlashLoanDebt = repaidAmount.add(premium);
192202

193-
uint256 neededForFlashLoanDebt = repaidAmount.add(premium);
194-
uint256[] memory amounts =
195-
_getAmountsIn(collateralAsset, debtAsset, neededForFlashLoanDebt, useEthPath);
196-
require(amounts[0] <= maxCollateralToSwap, 'slippage too high');
203+
if (repaidAmount < debtRepayAmount) {
204+
collateralAmount = collateralAmount.mul(repaidAmount).div(debtRepayAmount);
205+
}
197206

198-
// Pull aTokens from user
199-
_pullAToken(
200-
collateralAsset,
201-
collateralReserveData.aTokenAddress,
202-
initiator,
203-
amounts[0],
204-
permitSignature
205-
);
207+
// Pull aTokens from user
208+
_pullATokenAndWithdraw(address(collateralAsset), initiator, collateralAmount, permitSignature);
206209

207-
// Swap collateral asset to the debt asset
208-
_swapTokensForExactTokens(
210+
uint256 amountSold =
211+
_buyOnParaSwap(
212+
buyAllBalanceOffset,
213+
paraswapData,
209214
collateralAsset,
210215
debtAsset,
211-
amounts[0],
212-
neededForFlashLoanDebt,
213-
useEthPath
214-
);
215-
} else {
216-
// Pull aTokens from user
217-
_pullAToken(
218-
collateralAsset,
219-
collateralReserveData.aTokenAddress,
220-
initiator,
221-
repaidAmount.add(premium),
222-
permitSignature
216+
collateralAmount,
217+
neededForFlashLoanDebt
223218
);
219+
220+
uint256 collateralBalanceLeft = collateralAmount - amountSold;
221+
222+
//deposit collateral back in the pool, if left after the swap(buy)
223+
if (collateralBalanceLeft > 0) {
224+
LENDING_POOL.deposit(address(collateralAsset), collateralBalanceLeft, initiator, 0);
224225
}
225226

226227
// Repay flashloan. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix.
227228
IERC20(debtAsset).safeApprove(address(LENDING_POOL), 0);
228-
IERC20(debtAsset).safeApprove(address(LENDING_POOL), amount.add(premium));
229-
}*/
230-
231-
/**
232-
* @dev Decodes debt information encoded in the flash loan params
233-
* @param params Additional variadic field to include extra params. Expected parameters:
234-
* address collateralAsset Address of the reserve to be swapped
235-
* uint256 collateralAmount Amount of reserve to be swapped
236-
* uint256 rateMode Rate modes of the debt to be repaid
237-
* uint256 permitAmount Amount for the permit signature
238-
* uint256 deadline Deadline for the permit signature
239-
* uint8 v V param for the permit signature
240-
* bytes32 r R param for the permit signature
241-
* bytes32 s S param for the permit signature
242-
* bool useEthPath use WETH path route
243-
* @return RepayParams struct containing decoded params
244-
*/
245-
function _decodeParams(bytes memory params) internal pure returns (RepayParams memory) {
246-
(
247-
address collateralAsset,
248-
uint256 collateralAmount,
249-
uint256 rateMode,
250-
uint256 permitAmount,
251-
uint256 deadline,
252-
uint8 v,
253-
bytes32 r,
254-
bytes32 s,
255-
bool useEthPath
256-
) =
257-
abi.decode(
258-
params,
259-
(address, uint256, uint256, uint256, uint256, uint8, bytes32, bytes32, bool)
260-
);
261-
262-
return
263-
RepayParams(
264-
collateralAsset,
265-
collateralAmount,
266-
rateMode,
267-
PermitSignature(permitAmount, deadline, v, r, s),
268-
useEthPath
269-
);
229+
IERC20(debtAsset).safeApprove(address(LENDING_POOL), debtRepayAmount.add(premium));
270230
}
271231
}

0 commit comments

Comments
 (0)