Skip to content

Commit

Permalink
feat: Add withdraw and swap paraswap adapter (#180)
Browse files Browse the repository at this point in the history
* feat: withdraw and swap adapter

* fix: rename method

* fix: use safeTransfer

* fix: updated comment

* test: withdraw and swap

* fix: feedback items
  • Loading branch information
grothem authored Aug 22, 2023
1 parent 8f3380d commit b7ead26
Show file tree
Hide file tree
Showing 2 changed files with 1,068 additions and 0 deletions.
86 changes: 86 additions & 0 deletions contracts/adapters/paraswap/ParaSwapWithdrawSwapAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.10;

import {IERC20Detailed} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {IERC20WithPermit} from '@aave/core-v3/contracts/interfaces/IERC20WithPermit.sol';
import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol';
import {BaseParaSwapSellAdapter} from './BaseParaSwapSellAdapter.sol';
import {IParaSwapAugustusRegistry} from './interfaces/IParaSwapAugustusRegistry.sol';
import {SafeERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeERC20.sol';
import {IParaSwapAugustus} from './interfaces/IParaSwapAugustus.sol';
import {ReentrancyGuard} from '../../dependencies/openzeppelin/ReentrancyGuard.sol';

contract ParaSwapWithdrawSwapAdapter is BaseParaSwapSellAdapter, ReentrancyGuard {
using SafeERC20 for IERC20Detailed;

constructor(
IPoolAddressesProvider addressesProvider,
IParaSwapAugustusRegistry augustusRegistry,
address owner
) BaseParaSwapSellAdapter(addressesProvider, augustusRegistry) {
transferOwnership(owner);
}

function executeOperation(
address,
uint256,
uint256,
address,
bytes calldata
) external override nonReentrant returns (bool) {
revert('NOT_SUPPORTED');
}

/**
* @dev Swaps an amount of an asset to another after a withdraw and transfers the new asset to the user.
* The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset and perform the swap.
* @param assetToSwapFrom Address of the underlying asset to be swapped from
* @param assetToSwapTo Address of the underlying asset to be swapped to
* @param amountToSwap Amount to be swapped, or maximum amount when swapping all balance
* @param minAmountToReceive Minimum amount to be received from the swap
* @param swapAllBalanceOffset Set to offset of fromAmount in Augustus calldata if wanting to swap all balance, otherwise 0
* @param swapCalldata Calldata for ParaSwap's AugustusSwapper contract
* @param augustus Address of ParaSwap's AugustusSwapper contract
* @param permitParams Struct containing the permit signatures, set to all zeroes if not used
*/
function withdrawAndSwap(
IERC20Detailed assetToSwapFrom,
IERC20Detailed assetToSwapTo,
uint256 amountToSwap,
uint256 minAmountToReceive,
uint256 swapAllBalanceOffset,
bytes calldata swapCalldata,
IParaSwapAugustus augustus,
PermitSignature calldata permitParams
) external nonReentrant {
IERC20WithPermit aToken = IERC20WithPermit(
_getReserveData(address(assetToSwapFrom)).aTokenAddress
);

if (swapAllBalanceOffset != 0) {
uint256 balance = aToken.balanceOf(msg.sender);
require(balance <= amountToSwap, 'INSUFFICIENT_AMOUNT_TO_SWAP');
amountToSwap = balance;
}

_pullATokenAndWithdraw(
address(assetToSwapFrom),
aToken,
msg.sender,
amountToSwap,
permitParams
);

uint256 amountReceived = _sellOnParaSwap(
swapAllBalanceOffset,
swapCalldata,
augustus,
assetToSwapFrom,
assetToSwapTo,
amountToSwap,
minAmountToReceive
);

assetToSwapTo.safeTransfer(msg.sender, amountReceived);
}
}
Loading

0 comments on commit b7ead26

Please sign in to comment.