Skip to content

Commit

Permalink
fix: Transfer excess back and reset allowance (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelmtzinf authored Sep 17, 2024
1 parent 13caab8 commit 105baaf
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
* @param maxAmountToSwap Max amount to be swapped
* @param amountToReceive Amount to be received from the swap
* @return amountSold The amount sold during the swap
* @return amountBought The amount bought during the swap
*/
function _buyOnParaSwap(
uint256 toAmountOffset,
Expand All @@ -47,7 +48,7 @@ abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
IERC20Detailed assetToSwapTo,
uint256 maxAmountToSwap,
uint256 amountToReceive
) internal returns (uint256 amountSold) {
) internal returns (uint256 amountSold, uint256 amountBought) {
(bytes memory buyCalldata, IParaSwapAugustus augustus) = abi.decode(
paraswapData,
(bytes, IParaSwapAugustus)
Expand Down Expand Up @@ -75,7 +76,6 @@ abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
uint256 balanceBeforeAssetTo = assetToSwapTo.balanceOf(address(this));

address tokenTransferProxy = augustus.getTokenTransferProxy();
assetToSwapFrom.safeApprove(tokenTransferProxy, 0);
assetToSwapFrom.safeApprove(tokenTransferProxy, maxAmountToSwap);

if (toAmountOffset != 0) {
Expand All @@ -101,12 +101,15 @@ abstract contract BaseParaSwapBuyAdapter is BaseParaSwapAdapter {
}
}

// Reset allowance
assetToSwapFrom.safeApprove(tokenTransferProxy, 0);

uint256 balanceAfterAssetFrom = assetToSwapFrom.balanceOf(address(this));
amountSold = balanceBeforeAssetFrom - balanceAfterAssetFrom;
require(amountSold <= maxAmountToSwap, 'WRONG_BALANCE_AFTER_SWAP');
uint256 amountReceived = assetToSwapTo.balanceOf(address(this)).sub(balanceBeforeAssetTo);
require(amountReceived >= amountToReceive, 'INSUFFICIENT_AMOUNT_RECEIVED');
amountBought = assetToSwapTo.balanceOf(address(this)).sub(balanceBeforeAssetTo);
require(amountBought >= amountToReceive, 'INSUFFICIENT_AMOUNT_RECEIVED');

emit Bought(address(assetToSwapFrom), address(assetToSwapTo), amountSold, amountReceived);
emit Bought(address(assetToSwapFrom), address(assetToSwapTo), amountSold, amountBought);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter {
revert(0, returndatasize())
}
}

require(
assetToSwapFrom.balanceOf(address(this)) == balanceBeforeAssetFrom - amountToSwap,
'WRONG_BALANCE_AFTER_SWAP'
Expand Down
26 changes: 21 additions & 5 deletions src/periphery/contracts/adapters/paraswap/ParaSwapRepayAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ contract ParaSwapRepayAdapter is BaseParaSwapBuyAdapter, ReentrancyGuard {
// Pull aTokens from user
_pullATokenAndWithdraw(address(collateralAsset), msg.sender, collateralAmount, permitSignature);
//buy debt asset using collateral asset
uint256 amountSold = _buyOnParaSwap(
(uint256 amountSold, uint256 amountBought) = _buyOnParaSwap(
buyAllBalanceOffset,
paraswapData,
collateralAsset,
Expand All @@ -127,15 +127,23 @@ contract ParaSwapRepayAdapter is BaseParaSwapBuyAdapter, ReentrancyGuard {

//deposit collateral back in the pool, if left after the swap(buy)
if (collateralBalanceLeft > 0) {
IERC20(collateralAsset).safeApprove(address(POOL), 0);
IERC20(collateralAsset).safeApprove(address(POOL), collateralBalanceLeft);
POOL.deposit(address(collateralAsset), collateralBalanceLeft, msg.sender, 0);
IERC20(collateralAsset).safeApprove(address(POOL), 0);
}

// Repay debt. Approves 0 first to comply with tokens that implement the anti frontrunning approval fix
IERC20(debtAsset).safeApprove(address(POOL), 0);
IERC20(debtAsset).safeApprove(address(POOL), debtRepayAmount);
POOL.repay(address(debtAsset), debtRepayAmount, debtRateMode, msg.sender);
IERC20(debtAsset).safeApprove(address(POOL), 0);

{
//transfer excess of debtAsset back to the user, if any
uint256 debtAssetExcess = amountBought - debtRepayAmount;
if (debtAssetExcess > 0) {
IERC20(debtAsset).safeTransfer(msg.sender, debtAssetExcess);
}
}
}

/**
Expand Down Expand Up @@ -170,7 +178,7 @@ contract ParaSwapRepayAdapter is BaseParaSwapBuyAdapter, ReentrancyGuard {
initiator
);

uint256 amountSold = _buyOnParaSwap(
(uint256 amountSold, uint256 amountBought) = _buyOnParaSwap(
buyAllBalanceOffset,
paraswapData,
collateralAsset,
Expand All @@ -180,9 +188,9 @@ contract ParaSwapRepayAdapter is BaseParaSwapBuyAdapter, ReentrancyGuard {
);

// Repay debt. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix.
IERC20(debtAsset).safeApprove(address(POOL), 0);
IERC20(debtAsset).safeApprove(address(POOL), debtRepayAmount);
POOL.repay(address(debtAsset), debtRepayAmount, rateMode, initiator);
IERC20(debtAsset).safeApprove(address(POOL), 0);

uint256 neededForFlashLoanRepay = amountSold.add(premium);

Expand All @@ -194,6 +202,14 @@ contract ParaSwapRepayAdapter is BaseParaSwapBuyAdapter, ReentrancyGuard {
permitSignature
);

{
//transfer excess of debtAsset back to the user, if any
uint256 debtAssetExcess = amountBought - debtRepayAmount;
if (debtAssetExcess > 0) {
IERC20(debtAsset).safeTransfer(initiator, debtAssetExcess);
}
}

// Repay flashloan. Approves for 0 first to comply with tokens that implement the anti frontrunning approval fix.
IERC20(collateralAsset).safeApprove(address(POOL), 0);
IERC20(collateralAsset).safeApprove(address(POOL), collateralAmount.add(premium));
Expand Down

0 comments on commit 105baaf

Please sign in to comment.