diff --git a/contracts/optimism/connectors/aave/v3/events.sol b/contracts/optimism/connectors/aave/v3/events.sol index b29b4425..3b2513dd 100644 --- a/contracts/optimism/connectors/aave/v3/events.sol +++ b/contracts/optimism/connectors/aave/v3/events.sol @@ -32,4 +32,10 @@ contract Events { event LogDisableCollateral(address[] tokens); event LogSwapRateMode(address indexed token, uint256 rateMode); event LogSetUserEMode(uint8 categoryId); + event LogApproveDelegation( + address token, + uint16 debtType, + address delegateTo, + uint256 amount + ); } diff --git a/contracts/optimism/connectors/aave/v3/helpers.sol b/contracts/optimism/connectors/aave/v3/helpers.sol index ae72fa02..d7f8f0a2 100644 --- a/contracts/optimism/connectors/aave/v3/helpers.sol +++ b/contracts/optimism/connectors/aave/v3/helpers.sol @@ -64,4 +64,21 @@ abstract contract Helpers is DSMath, Basic { address(this) ); } + + /** + * @dev Get debt token address for an asset + * @param token token address of the asset + * @param rateMode Debt type: stable-1, variable-2 + */ + function getDTokenAddr(address token, uint16 rateMode) + internal + view + returns(address dToken) + { + if (rateMode == 1) { + (, dToken, ) = aaveData.getReserveTokensAddresses(token); + } else { + (, , dToken) = aaveData.getReserveTokensAddresses(token); + } + } } diff --git a/contracts/optimism/connectors/aave/v3/interface.sol b/contracts/optimism/connectors/aave/v3/interface.sol index 81553143..6de08261 100644 --- a/contracts/optimism/connectors/aave/v3/interface.sol +++ b/contracts/optimism/connectors/aave/v3/interface.sol @@ -90,3 +90,7 @@ interface AaveAddressProviderRegistryInterface { interface ATokenInterface { function balanceOf(address _user) external view returns (uint256); } + +interface DTokenInterface { + function approveDelegation(address delegatee, uint256 amount) external; +} diff --git a/contracts/optimism/connectors/aave/v3/main.sol b/contracts/optimism/connectors/aave/v3/main.sol index e98ae77e..3a544184 100644 --- a/contracts/optimism/connectors/aave/v3/main.sol +++ b/contracts/optimism/connectors/aave/v3/main.sol @@ -10,7 +10,7 @@ import { TokenInterface } from "../../../common/interfaces.sol"; import { Stores } from "../../../common/stores.sol"; import { Helpers } from "./helpers.sol"; import { Events } from "./events.sol"; -import { AaveInterface } from "./interface.sol"; +import { AaveInterface, DTokenInterface } from "./interface.sol"; abstract contract AaveResolver is Events, Helpers { /** @@ -63,6 +63,56 @@ abstract contract AaveResolver is Events, Helpers { _eventParam = abi.encode(token, _amt, getId, setId); } + /** + * @dev Deposit ETH/ERC20_Token. + * @notice Deposit a token to Aave v3 for lending / collaterization. + * @param token The address of the token to deposit.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to deposit. (For max: `uint256(-1)`) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens deposited. + */ + function depositWithoutCollateral( + address token, + uint256 amt, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + if (isEth) { + _amt = _amt == uint256(-1) ? address(this).balance : _amt; + convertEthToWeth(isEth, tokenContract, _amt); + } else { + _amt = _amt == uint256(-1) + ? tokenContract.balanceOf(address(this)) + : _amt; + } + + approve(tokenContract, address(aave), _amt); + + aave.supply(_token, _amt, address(this), referralCode); + + if (getCollateralBalance(_token) > 0 && getIsColl(token)) { + aave.setUserUseReserveAsCollateral(_token, false); + } + + setUint(setId, _amt); + + _eventName = "LogDeposit(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } + /** * @dev Withdraw ETH/ERC20_Token. * @notice Withdraw deposited token from Aave v3 @@ -139,6 +189,44 @@ abstract contract AaveResolver is Events, Helpers { _eventParam = abi.encode(token, _amt, rateMode, getId, setId); } + /** + * @dev Borrow ETH/ERC20_Token on behalf of a user. + * @notice Borrow a token using Aave v3 on behalf of a user + * @param token The address of the token to borrow.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to borrow. + * @param rateMode The type of borrow debt. (For Stable: 1, Variable: 2) + * @param onBehalfOf The user who will incur the debt + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens borrowed. + */ + function borrowOnBehalfOf( + address token, + uint256 amt, + uint256 rateMode, + address onBehalfOf, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; + + aave.borrow(_token, _amt, rateMode, referralCode, onBehalfOf); + convertEthToWeth(isEth, TokenInterface(_token), _amt); + + setUint(setId, _amt); + + _eventName = "LogBorrow(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + /** * @dev Payback borrowed ETH/ERC20_Token. * @notice Payback debt owed. @@ -316,6 +404,32 @@ abstract contract AaveResolver is Events, Helpers { _eventName = "LogSetUserEMode(uint8)"; _eventParam = abi.encode(categoryId); } + + /** + * @dev Approve Delegation + * @notice Gives approval to delegate debt tokens + * @param token The address of token + * @param rateMode The type of borrow debt + * @param delegateTo The address to whom the user is delegating + * @param amount The amount + */ + function approveDelegation(address token, uint16 rateMode, address delegateTo, uint256 amount) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + require(rateMode == 1 || rateMode == 2, "Invalid debt type"); + + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; + + address _dToken = getDTokenAddr(_token, rateMode); + DTokenInterface(_dToken).approveDelegation(delegateTo, amount); + + _eventName = "LogApproveDelegation(address,uint16,address,uint256)"; + _eventParam = abi.encode(token, rateMode, delegateTo, amount); + + } } contract ConnectV2AaveV3Optimism is AaveResolver {