11// SPDX-License-Identifier: MIT AND Apache-2.0
22pragma solidity 0.8.23 ;
33
4- import { IDelegationManager } from "../interfaces/IDelegationManager.sol " ;
5- import { IAavePool } from "./interfaces/IAavePool.sol " ;
64import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
75import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol " ;
8- import { Delegation, ModeCode, Execution } from "../utils/Types .sol " ;
6+ import { Ownable2Step, Ownable } from "@openzeppelin/contracts/access/Ownable2Step .sol " ;
97import { ModeLib } from "@erc7579/lib/ModeLib.sol " ;
108import { ExecutionLib } from "@erc7579/lib/ExecutionLib.sol " ;
119
10+ import { Delegation, ModeCode, Execution } from "../utils/Types.sol " ;
11+ import { IDelegationManager } from "../interfaces/IDelegationManager.sol " ;
12+ import { IAavePool } from "./interfaces/IAavePool.sol " ;
13+
1214/// @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 {
15+ /// @notice Adapter contract that enables Aave lending operations through MetaMask's delegation framework
16+ /// @dev This contract acts as an intermediary between users and Aave, enabling delegation-based token operations
17+ /// without requiring direct token approvals. It supports both supply and withdrawal operations with two
18+ /// execution models:
19+ ///
20+ /// 1. Delegator-only execution: Only the token owner (delegator) can execute operations, providing
21+ /// maximum control over when and how their tokens are used in Aave operations.
22+ ///
23+ /// 2. Open-ended execution: Any authorized delegate can execute operations on behalf of the delegator,
24+ /// enabling automated or third-party execution while ensuring benefits always flow to the delegator.
25+ ///
26+ /// The contract leverages ERC-7710 delegations to transfer tokens from users to itself, then interacts
27+ /// with Aave pools on their behalf. This eliminates the need for traditional ERC20 approvals and enables
28+ /// more flexible, intent-based interactions with DeFi protocols.
29+ ///
30+ /// Ownable functionality is implemented for emergency administration:
31+ /// - Recovery of tokens accidentally sent directly to the contract (bypassing delegation flow)
32+ /// - The contract is designed to never hold tokens during normal operation, making owner functions
33+ /// purely for exceptional circumstances
34+ contract AaveAdapter is Ownable2Step {
1635 using SafeERC20 for IERC20 ;
1736
1837 ////////////////////// Events //////////////////////
@@ -31,6 +50,12 @@ contract AaveAdapter {
3150 /// @param amount Amount of tokens withdrawn
3251 event WithdrawExecuted (address indexed delegator , address indexed delegate , address indexed token , uint256 amount );
3352
53+ /// @notice Event emitted when stuck tokens are withdrawn by owner
54+ /// @param token Address of the token withdrawn
55+ /// @param recipient Address of the recipient
56+ /// @param amount Amount of tokens withdrawn
57+ event StuckTokensWithdrawn (IERC20 indexed token , address indexed recipient , uint256 amount );
58+
3459 ////////////////////// Errors //////////////////////
3560
3661 /// @notice Thrown when a zero address is provided for required parameters
@@ -50,9 +75,10 @@ contract AaveAdapter {
5075 ////////////////////// Constructor //////////////////////
5176
5277 /// @notice Initializes the adapter with delegation manager and Aave pool addresses
78+ /// @param _owner Address of the contract owner
5379 /// @param _delegationManager Address of the delegation manager contract
5480 /// @param _aavePool Address of the Aave lending pool contract
55- constructor (address _delegationManager , address _aavePool ) {
81+ constructor (address _owner , address _delegationManager , address _aavePool ) Ownable (_owner ) {
5682 if (_delegationManager == address (0 ) || _aavePool == address (0 )) revert InvalidZeroAddress ();
5783
5884 delegationManager = IDelegationManager (_delegationManager);
@@ -193,4 +219,20 @@ contract AaveAdapter {
193219
194220 emit WithdrawExecuted (_delegations[0 ].delegator, msg .sender , _token, _amount);
195221 }
222+
223+ /**
224+ * @notice Emergency function to recover tokens accidentally sent to this contract.
225+ * @dev This contract should never hold ERC20 tokens as all token operations are handled
226+ * through delegation-based transfers that move tokens directly between users and Aave.
227+ * This function is only for recovering tokens that users may have sent to this contract
228+ * by mistake (e.g., direct transfers instead of using delegation functions).
229+ * @param _token The token to be recovered.
230+ * @param _amount The amount of tokens to recover.
231+ * @param _recipient The address to receive the recovered tokens.
232+ */
233+ function withdraw (IERC20 _token , uint256 _amount , address _recipient ) external onlyOwner {
234+ IERC20 (_token).safeTransfer (_recipient, _amount);
235+
236+ emit StuckTokensWithdrawn (_token, _recipient, _amount);
237+ }
196238}
0 commit comments