Skip to content
This repository was archived by the owner on Oct 21, 2025. It is now read-only.

Commit b7ead26

Browse files
authored
feat: Add withdraw and swap paraswap adapter (#180)
* feat: withdraw and swap adapter * fix: rename method * fix: use safeTransfer * fix: updated comment * test: withdraw and swap * fix: feedback items
1 parent 8f3380d commit b7ead26

File tree

2 files changed

+1068
-0
lines changed

2 files changed

+1068
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// SPDX-License-Identifier: AGPL-3.0
2+
pragma solidity ^0.8.10;
3+
4+
import {IERC20Detailed} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol';
5+
import {IERC20WithPermit} from '@aave/core-v3/contracts/interfaces/IERC20WithPermit.sol';
6+
import {IPoolAddressesProvider} from '@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol';
7+
import {BaseParaSwapSellAdapter} from './BaseParaSwapSellAdapter.sol';
8+
import {IParaSwapAugustusRegistry} from './interfaces/IParaSwapAugustusRegistry.sol';
9+
import {SafeERC20} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeERC20.sol';
10+
import {IParaSwapAugustus} from './interfaces/IParaSwapAugustus.sol';
11+
import {ReentrancyGuard} from '../../dependencies/openzeppelin/ReentrancyGuard.sol';
12+
13+
contract ParaSwapWithdrawSwapAdapter is BaseParaSwapSellAdapter, ReentrancyGuard {
14+
using SafeERC20 for IERC20Detailed;
15+
16+
constructor(
17+
IPoolAddressesProvider addressesProvider,
18+
IParaSwapAugustusRegistry augustusRegistry,
19+
address owner
20+
) BaseParaSwapSellAdapter(addressesProvider, augustusRegistry) {
21+
transferOwnership(owner);
22+
}
23+
24+
function executeOperation(
25+
address,
26+
uint256,
27+
uint256,
28+
address,
29+
bytes calldata
30+
) external override nonReentrant returns (bool) {
31+
revert('NOT_SUPPORTED');
32+
}
33+
34+
/**
35+
* @dev Swaps an amount of an asset to another after a withdraw and transfers the new asset to the user.
36+
* The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset and perform the swap.
37+
* @param assetToSwapFrom Address of the underlying asset to be swapped from
38+
* @param assetToSwapTo Address of the underlying asset to be swapped to
39+
* @param amountToSwap Amount to be swapped, or maximum amount when swapping all balance
40+
* @param minAmountToReceive Minimum amount to be received from the swap
41+
* @param swapAllBalanceOffset Set to offset of fromAmount in Augustus calldata if wanting to swap all balance, otherwise 0
42+
* @param swapCalldata Calldata for ParaSwap's AugustusSwapper contract
43+
* @param augustus Address of ParaSwap's AugustusSwapper contract
44+
* @param permitParams Struct containing the permit signatures, set to all zeroes if not used
45+
*/
46+
function withdrawAndSwap(
47+
IERC20Detailed assetToSwapFrom,
48+
IERC20Detailed assetToSwapTo,
49+
uint256 amountToSwap,
50+
uint256 minAmountToReceive,
51+
uint256 swapAllBalanceOffset,
52+
bytes calldata swapCalldata,
53+
IParaSwapAugustus augustus,
54+
PermitSignature calldata permitParams
55+
) external nonReentrant {
56+
IERC20WithPermit aToken = IERC20WithPermit(
57+
_getReserveData(address(assetToSwapFrom)).aTokenAddress
58+
);
59+
60+
if (swapAllBalanceOffset != 0) {
61+
uint256 balance = aToken.balanceOf(msg.sender);
62+
require(balance <= amountToSwap, 'INSUFFICIENT_AMOUNT_TO_SWAP');
63+
amountToSwap = balance;
64+
}
65+
66+
_pullATokenAndWithdraw(
67+
address(assetToSwapFrom),
68+
aToken,
69+
msg.sender,
70+
amountToSwap,
71+
permitParams
72+
);
73+
74+
uint256 amountReceived = _sellOnParaSwap(
75+
swapAllBalanceOffset,
76+
swapCalldata,
77+
augustus,
78+
assetToSwapFrom,
79+
assetToSwapTo,
80+
amountToSwap,
81+
minAmountToReceive
82+
);
83+
84+
assetToSwapTo.safeTransfer(msg.sender, amountReceived);
85+
}
86+
}

0 commit comments

Comments
 (0)