Skip to content

Commit 1a70cc6

Browse files
committed
test: moved aave poc folder, added withdrawals
1 parent d49a1f6 commit 1a70cc6

3 files changed

Lines changed: 483 additions & 338 deletions

File tree

src/helpers/AaveAdapter.sol

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// SPDX-License-Identifier: MIT AND Apache-2.0
2+
pragma solidity 0.8.23;
3+
4+
import { IDelegationManager } from "../interfaces/IDelegationManager.sol";
5+
import { IAavePool } from "./interfaces/IAavePool.sol";
6+
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7+
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
8+
import { Delegation, ModeCode, Execution } from "../utils/Types.sol";
9+
import { ModeLib } from "@erc7579/lib/ModeLib.sol";
10+
import { ExecutionLib } from "@erc7579/lib/ExecutionLib.sol";
11+
12+
/// @title AaveAdapter
13+
/// @notice Proof of concept adapter contract for Aave lending operations using delegations
14+
/// @dev Handles token transfers and Aave supply operations through delegation-based permissions
15+
contract AaveAdapter {
16+
using SafeERC20 for IERC20;
17+
18+
IDelegationManager public immutable delegationManager;
19+
IAavePool public immutable aavePool;
20+
21+
/// @notice Initializes the adapter with delegation manager and Aave pool addresses
22+
/// @param _delegationManager Address of the delegation manager contract
23+
/// @param _aavePool Address of the Aave lending pool contract
24+
constructor(address _delegationManager, address _aavePool) {
25+
delegationManager = IDelegationManager(_delegationManager);
26+
aavePool = IAavePool(_aavePool);
27+
}
28+
29+
/// @notice Ensures sufficient token allowance for Aave operations
30+
/// @dev Checks current allowance and increases to max if needed
31+
/// @param _token Token to manage allowance for
32+
/// @param _amount Amount needed for the operation
33+
function _ensureAllowance(IERC20 _token, uint256 _amount) private {
34+
uint256 allowance_ = _token.allowance(address(this), address(aavePool));
35+
if (allowance_ < _amount) {
36+
_token.safeIncreaseAllowance(address(aavePool), type(uint256).max);
37+
}
38+
}
39+
40+
/// @notice Supplies tokens to Aave using delegation-based token transfer
41+
/// @dev Only the delegator can execute this function, ensuring full control over supply parameters
42+
/// @param _delegations Array containing a single delegation for token transfer
43+
/// @param _token Address of the token to supply to Aave
44+
/// @param _amount Amount of tokens to supply
45+
function supplyByDelegation(Delegation[] memory _delegations, address _token, uint256 _amount) external {
46+
require(_delegations.length == 1, "Wrong number of delegations");
47+
require(_delegations[0].delegator == msg.sender, "Not allowed");
48+
49+
bytes[] memory permissionContexts_ = new bytes[](1);
50+
permissionContexts_[0] = abi.encode(_delegations);
51+
52+
ModeCode[] memory encodedModes_ = new ModeCode[](1);
53+
encodedModes_[0] = ModeLib.encodeSimpleSingle();
54+
55+
bytes[] memory executionCallDatas_ = new bytes[](1);
56+
57+
bytes memory encodedTransfer_ = abi.encodeCall(IERC20.transfer, (address(this), _amount));
58+
executionCallDatas_[0] = ExecutionLib.encodeSingle(address(_token), 0, encodedTransfer_);
59+
60+
delegationManager.redeemDelegations(permissionContexts_, encodedModes_, executionCallDatas_);
61+
62+
_ensureAllowance(IERC20(_token), _amount);
63+
aavePool.supply(_token, _amount, msg.sender, 0);
64+
}
65+
66+
/// @notice Supplies tokens to Aave using delegation-based token transfer with open-ended execution
67+
/// @dev Any delegate can execute this function, but aTokens are always credited to the delegator
68+
/// @param _delegations Array containing a single delegation for token transfer
69+
/// @param _token Address of the token to supply to Aave
70+
/// @param _amount Amount of tokens to supply
71+
function supplyByDelegationOpenEnded(Delegation[] memory _delegations, address _token, uint256 _amount) external {
72+
require(_delegations.length == 1, "Wrong number of delegations");
73+
74+
bytes[] memory permissionContexts_ = new bytes[](1);
75+
permissionContexts_[0] = abi.encode(_delegations);
76+
77+
ModeCode[] memory encodedModes_ = new ModeCode[](1);
78+
encodedModes_[0] = ModeLib.encodeSimpleSingle();
79+
80+
bytes[] memory executionCallDatas_ = new bytes[](1);
81+
82+
bytes memory encodedTransfer_ = abi.encodeCall(IERC20.transfer, (address(this), _amount));
83+
executionCallDatas_[0] = ExecutionLib.encodeSingle(address(_token), 0, encodedTransfer_);
84+
85+
delegationManager.redeemDelegations(permissionContexts_, encodedModes_, executionCallDatas_);
86+
87+
_ensureAllowance(IERC20(_token), _amount);
88+
aavePool.supply(_token, _amount, _delegations[0].delegator, 0);
89+
}
90+
91+
/// @notice Withdraws tokens from Aave using delegation-based aToken transfer
92+
/// @dev Only the delegator can execute this function, ensuring full control over withdrawal parameters
93+
/// @param _delegations Array containing a single delegation for aToken transfer
94+
/// @param _token Address of the underlying token to withdraw from Aave
95+
/// @param _amount Amount of tokens to withdraw (or type(uint256).max for all)
96+
function withdrawByDelegation(Delegation[] memory _delegations, address _token, uint256 _amount) external {
97+
require(_delegations.length == 1, "Wrong number of delegations");
98+
require(_delegations[0].delegator == msg.sender, "Not allowed");
99+
100+
bytes[] memory permissionContexts_ = new bytes[](1);
101+
permissionContexts_[0] = abi.encode(_delegations);
102+
103+
ModeCode[] memory encodedModes_ = new ModeCode[](1);
104+
encodedModes_[0] = ModeLib.encodeSimpleSingle();
105+
106+
bytes[] memory executionCallDatas_ = new bytes[](1);
107+
108+
// Get the aToken address for the underlying token
109+
IERC20 aToken_ = IERC20(aavePool.getReserveAToken(_token));
110+
111+
bytes memory encodedTransfer_ = abi.encodeCall(IERC20.transfer, (address(this), _amount));
112+
executionCallDatas_[0] = ExecutionLib.encodeSingle(address(aToken_), 0, encodedTransfer_);
113+
114+
delegationManager.redeemDelegations(permissionContexts_, encodedModes_, executionCallDatas_);
115+
116+
// Withdraw from Aave directly to the delegator
117+
aavePool.withdraw(_token, _amount, msg.sender);
118+
}
119+
120+
/// @notice Withdraws tokens from Aave using delegation-based aToken transfer with open-ended execution
121+
/// @dev Any delegate can execute this function, but underlying tokens are always sent to the delegator
122+
/// @param _delegations Array containing a single delegation for aToken transfer
123+
/// @param _token Address of the underlying token to withdraw from Aave
124+
/// @param _amount Amount of tokens to withdraw (or type(uint256).max for all)
125+
function withdrawByDelegationOpenEnded(Delegation[] memory _delegations, address _token, uint256 _amount) external {
126+
require(_delegations.length == 1, "Wrong number of delegations");
127+
128+
bytes[] memory permissionContexts_ = new bytes[](1);
129+
permissionContexts_[0] = abi.encode(_delegations);
130+
131+
ModeCode[] memory encodedModes_ = new ModeCode[](1);
132+
encodedModes_[0] = ModeLib.encodeSimpleSingle();
133+
134+
bytes[] memory executionCallDatas_ = new bytes[](1);
135+
136+
// Get the aToken address for the underlying token
137+
IERC20 aToken_ = IERC20(aavePool.getReserveAToken(_token));
138+
139+
bytes memory encodedTransfer_ = abi.encodeCall(IERC20.transfer, (address(this), _amount));
140+
executionCallDatas_[0] = ExecutionLib.encodeSingle(address(aToken_), 0, encodedTransfer_);
141+
142+
delegationManager.redeemDelegations(permissionContexts_, encodedModes_, executionCallDatas_);
143+
144+
// Withdraw from Aave directly to the delegator
145+
aavePool.withdraw(_token, _amount, _delegations[0].delegator);
146+
}
147+
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
// Based on: https://github.com/aave-dao/aave-v3-origin/blob/main/src/contracts/interfaces/IPool.sol
22

3-
// SPDX-License-Identifier: MIT
4-
pragma solidity ^0.8.0;
3+
// SPDX-License-Identifier: MIT AND Apache-2.0
4+
pragma solidity 0.8.23;
55

66
/**
7-
* @title IPool
7+
* @title IAavePool
88
* @author Aave
99
* @notice Defines the basic interface for an Aave Pool.
1010
*/
11-
interface IPool {
11+
interface IAavePool {
1212
/**
1313
* @dev Emitted on mintUnbacked()
1414
* @param reserve The address of the underlying asset of the reserve

0 commit comments

Comments
 (0)