From 7e21f4684125258ea47e80a7869b3ca5d6b6067b Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Mon, 14 Feb 2022 11:57:50 +0530 Subject: [PATCH 01/30] initial commit --- .../mainnet/connectors/aave/v3/events.sol | 10 + .../mainnet/connectors/aave/v3/helpers.sol | 49 ++++ .../mainnet/connectors/aave/v3/interface.sol | 47 ++++ contracts/mainnet/connectors/aave/v3/main.sol | 215 ++++++++++++++++++ 4 files changed, 321 insertions(+) create mode 100644 contracts/mainnet/connectors/aave/v3/events.sol create mode 100644 contracts/mainnet/connectors/aave/v3/helpers.sol create mode 100644 contracts/mainnet/connectors/aave/v3/interface.sol create mode 100644 contracts/mainnet/connectors/aave/v3/main.sol diff --git a/contracts/mainnet/connectors/aave/v3/events.sol b/contracts/mainnet/connectors/aave/v3/events.sol new file mode 100644 index 00000000..805b2209 --- /dev/null +++ b/contracts/mainnet/connectors/aave/v3/events.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDeposit(address indexed token, uint256 tokenAmt, uint256 getId, uint256 setId); + event LogWithdraw(address indexed token, uint256 tokenAmt, uint256 getId, uint256 setId); + event LogBorrow(address indexed token, uint256 tokenAmt, uint256 indexed rateMode, uint256 getId, uint256 setId); + event LogPayback(address indexed token, uint256 tokenAmt, uint256 indexed rateMode, uint256 getId, uint256 setId); + event LogEnableCollateral(address[] tokens); + event LogSwapRateMode(address indexed token, uint256 rateMode); +} diff --git a/contracts/mainnet/connectors/aave/v3/helpers.sol b/contracts/mainnet/connectors/aave/v3/helpers.sol new file mode 100644 index 00000000..7d5b9836 --- /dev/null +++ b/contracts/mainnet/connectors/aave/v3/helpers.sol @@ -0,0 +1,49 @@ +pragma solidity ^0.7.0; + +import { DSMath } from "../../../common/math.sol"; +import { Basic } from "../../../common/basic.sol"; +import { AaveLendingPoolProviderInterface, AaveDataProviderInterface } from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + + /** + * @dev Aave Lending Pool Provider + */ + AaveLendingPoolProviderInterface constant internal aaveProvider = AaveLendingPoolProviderInterface(0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5); + + /** + * @dev Aave Protocol Data Provider + */ + AaveDataProviderInterface constant internal aaveData = AaveDataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); + + /** + * @dev Aave Referral Code + */ + uint16 constant internal referralCode = 3228; + + /** + * @dev Checks if collateral is enabled for an asset + * @param token token address of the asset.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + function getIsColl(address token) internal view returns (bool isCol) { + (, , , , , , , , isCol) = aaveData.getUserReserveData(token, address(this)); + } + + /** + * @dev Get total debt balance & fee for an asset + * @param token token address of the debt.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Borrow rate mode (Stable = 1, Variable = 2) + */ + function getPaybackBalance(address token, uint rateMode) internal view returns (uint) { + (, uint stableDebt, uint variableDebt, , , , , , ) = aaveData.getUserReserveData(token, address(this)); + return rateMode == 1 ? stableDebt : variableDebt; + } + + /** + * @dev Get total collateral balance for an asset + * @param token token address of the collateral.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + function getCollateralBalance(address token) internal view returns (uint bal) { + (bal, , , , , , , ,) = aaveData.getUserReserveData(token, address(this)); + } +} diff --git a/contracts/mainnet/connectors/aave/v3/interface.sol b/contracts/mainnet/connectors/aave/v3/interface.sol new file mode 100644 index 00000000..ab17fd22 --- /dev/null +++ b/contracts/mainnet/connectors/aave/v3/interface.sol @@ -0,0 +1,47 @@ +pragma solidity ^0.7.0; + +interface AaveInterface { + function deposit(address _asset, uint256 _amount, address _onBehalfOf, uint16 _referralCode) external; + function withdraw(address _asset, uint256 _amount, address _to) external; + function borrow( + address _asset, + uint256 _amount, + uint256 _interestRateMode, + uint16 _referralCode, + address _onBehalfOf + ) external; + function repay(address _asset, uint256 _amount, uint256 _rateMode, address _onBehalfOf) external; + function setUserUseReserveAsCollateral(address _asset, bool _useAsCollateral) external; + function swapBorrowRateMode(address _asset, uint256 _rateMode) external; +} + +interface AaveLendingPoolProviderInterface { + function getLendingPool() external view returns (address); +} + +interface AaveDataProviderInterface { + function getReserveTokensAddresses(address _asset) external view returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); + function getUserReserveData(address _asset, address _user) external view returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); +} + +interface AaveAddressProviderRegistryInterface { + function getAddressesProvidersList() external view returns (address[] memory); +} + +interface ATokenInterface { + function balanceOf(address _user) external view returns(uint256); +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/aave/v3/main.sol b/contracts/mainnet/connectors/aave/v3/main.sol new file mode 100644 index 00000000..d3f7d01a --- /dev/null +++ b/contracts/mainnet/connectors/aave/v3/main.sol @@ -0,0 +1,215 @@ +pragma solidity ^0.7.0; + +/** + * @title Aave v2. + * @dev Lending & Borrowing. + */ + +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"; + +abstract contract AaveResolver is Events, Helpers { + /** + * @dev Deposit ETH/ERC20_Token. + * @notice Deposit a token to Aave v2 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 deposit( + address token, + uint256 amt, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + if (isEth) { + _amt = _amt == uint(-1) ? address(this).balance : _amt; + convertEthToWeth(isEth, tokenContract, _amt); + } else { + _amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt; + } + + approve(tokenContract, address(aave), _amt); + + aave.deposit(_token, _amt, address(this), referralCode); + + if (!getIsColl(_token)) { + aave.setUserUseReserveAsCollateral(_token, true); + } + + 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 v2 + * @param token The address of the token to withdraw.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens withdrawn. + */ + function withdraw( + address token, + uint256 amt, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + uint initialBal = tokenContract.balanceOf(address(this)); + aave.withdraw(_token, _amt, address(this)); + uint finalBal = tokenContract.balanceOf(address(this)); + + _amt = sub(finalBal, initialBal); + + convertWethToEth(isEth, tokenContract, _amt); + + setUint(setId, _amt); + + _eventName = "LogWithdraw(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } + + /** + * @dev Borrow ETH/ERC20_Token. + * @notice Borrow a token using Aave v2 + * @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 getId ID to retrieve amt. + * @param setId ID stores the amount of tokens borrowed. + */ + function borrow( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; + + aave.borrow(_token, _amt, rateMode, referralCode, address(this)); + convertWethToEth(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. + * @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function payback( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + _amt = _amt == uint(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isEth) convertEthToWeth(isEth, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repay(_token, _amt, rateMode, address(this)); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Enable collateral + * @notice Enable an array of tokens as collateral + * @param tokens Array of tokens to enable collateral + */ + function enableCollateral( + address[] calldata tokens + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _length = tokens.length; + require(_length > 0, "0-tokens-not-allowed"); + + AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + + for (uint i = 0; i < _length; i++) { + address token = tokens[i]; + if (getCollateralBalance(token) > 0 && !getIsColl(token)) { + aave.setUserUseReserveAsCollateral(token, true); + } + } + + _eventName = "LogEnableCollateral(address[])"; + _eventParam = abi.encode(tokens); + } + + /** + * @dev Swap borrow rate mode + * @notice Swaps user borrow rate mode between variable and stable + * @param token The address of the token to swap borrow rate.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2) + */ + function swapBorrowRateMode( + address token, + uint rateMode + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + + uint currentRateMode = rateMode == 1 ? 2 : 1; + + if (getPaybackBalance(token, currentRateMode) > 0) { + aave.swapBorrowRateMode(token, rateMode); + } + + _eventName = "LogSwapRateMode(address,uint256)"; + _eventParam = abi.encode(token, rateMode); + } +} + +contract ConnectV2AaveV2 is AaveResolver { + string constant public name = "AaveV2-v1.1"; +} From 420ada2036465b2ad7d671734655a79ea573eda3 Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Sat, 19 Feb 2022 19:17:39 +0530 Subject: [PATCH 02/30] added paybackWithAToken func + minor fix --- .../mainnet/connectors/aave/v3/helpers.sol | 91 +++-- .../mainnet/connectors/aave/v3/interface.sol | 110 +++-- contracts/mainnet/connectors/aave/v3/main.sol | 382 ++++++++++-------- 3 files changed, 354 insertions(+), 229 deletions(-) diff --git a/contracts/mainnet/connectors/aave/v3/helpers.sol b/contracts/mainnet/connectors/aave/v3/helpers.sol index 7d5b9836..13431d11 100644 --- a/contracts/mainnet/connectors/aave/v3/helpers.sol +++ b/contracts/mainnet/connectors/aave/v3/helpers.sol @@ -2,48 +2,65 @@ pragma solidity ^0.7.0; import { DSMath } from "../../../common/math.sol"; import { Basic } from "../../../common/basic.sol"; -import { AaveLendingPoolProviderInterface, AaveDataProviderInterface } from "./interface.sol"; +import { AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol"; abstract contract Helpers is DSMath, Basic { - - /** - * @dev Aave Lending Pool Provider - */ - AaveLendingPoolProviderInterface constant internal aaveProvider = AaveLendingPoolProviderInterface(0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5); + /** + * @dev Aave Pool Provider + */ + AavePoolProviderInterface internal constant aaveProvider = + AavePoolProviderInterface(0xA55125A90d75a95EC00130E8E8C197dB5641Eb19); // rinkeby address - /** - * @dev Aave Protocol Data Provider - */ - AaveDataProviderInterface constant internal aaveData = AaveDataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); + /** + * @dev Aave Pool Data Provider + */ + AaveDataProviderInterface internal constant aaveData = + AaveDataProviderInterface(0x256bBbeDbA70a1240a1EB64210abB1b063267408); // rinkeby address - /** - * @dev Aave Referral Code - */ - uint16 constant internal referralCode = 3228; + /** + * @dev Aave Referral Code + */ + uint16 internal constant referralCode = 3228; - /** - * @dev Checks if collateral is enabled for an asset - * @param token token address of the asset.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - */ - function getIsColl(address token) internal view returns (bool isCol) { - (, , , , , , , , isCol) = aaveData.getUserReserveData(token, address(this)); - } + /** + * @dev Checks if collateral is enabled for an asset + * @param token token address of the asset.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ - /** - * @dev Get total debt balance & fee for an asset - * @param token token address of the debt.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param rateMode Borrow rate mode (Stable = 1, Variable = 2) - */ - function getPaybackBalance(address token, uint rateMode) internal view returns (uint) { - (, uint stableDebt, uint variableDebt, , , , , , ) = aaveData.getUserReserveData(token, address(this)); - return rateMode == 1 ? stableDebt : variableDebt; - } + function getIsColl(address token) internal view returns (bool isCol) { + (, , , , , , , , isCol) = aaveData.getUserReserveData( + token, + address(this) + ); + } - /** - * @dev Get total collateral balance for an asset - * @param token token address of the collateral.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - */ - function getCollateralBalance(address token) internal view returns (uint bal) { - (bal, , , , , , , ,) = aaveData.getUserReserveData(token, address(this)); - } + /** + * @dev Get total debt balance & fee for an asset + * @param token token address of the debt.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Borrow rate mode (Stable = 1, Variable = 2) + */ + function getPaybackBalance(address token, uint256 rateMode) + internal + view + returns (uint256) + { + (, uint256 stableDebt, uint256 variableDebt, , , , , , ) = aaveData + .getUserReserveData(token, address(this)); + return rateMode == 1 ? stableDebt : variableDebt; + } + + /** + * @dev Get total collateral balance for an asset + * @param token token address of the collateral.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + function getCollateralBalance(address token) + internal + view + returns (uint256 bal) + { + (bal, , , , , , , , ) = aaveData.getUserReserveData( + token, + address(this) + ); + } } diff --git a/contracts/mainnet/connectors/aave/v3/interface.sol b/contracts/mainnet/connectors/aave/v3/interface.sol index ab17fd22..8ae14716 100644 --- a/contracts/mainnet/connectors/aave/v3/interface.sol +++ b/contracts/mainnet/connectors/aave/v3/interface.sol @@ -1,47 +1,91 @@ pragma solidity ^0.7.0; interface AaveInterface { - function deposit(address _asset, uint256 _amount, address _onBehalfOf, uint16 _referralCode) external; - function withdraw(address _asset, uint256 _amount, address _to) external; - function borrow( - address _asset, - uint256 _amount, - uint256 _interestRateMode, - uint16 _referralCode, - address _onBehalfOf - ) external; - function repay(address _asset, uint256 _amount, uint256 _rateMode, address _onBehalfOf) external; - function setUserUseReserveAsCollateral(address _asset, bool _useAsCollateral) external; - function swapBorrowRateMode(address _asset, uint256 _rateMode) external; + function supply( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + function withdraw( + address asset, + uint256 amount, + address to + ) external returns (uint256); + + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) external; + + function repay( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf + ) external returns (uint256); + + function repayWithATokens( + address asset, + uint256 amount, + uint256 interestRateMode + ) external returns (uint256); + + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) + external; + + function swapBorrowRateMode(address asset, uint256 interestRateMode) + external; + + function setUserEMode(uint8 categoryId) external; } -interface AaveLendingPoolProviderInterface { - function getLendingPool() external view returns (address); +interface AavePoolProviderInterface { + function getPool() external view returns (address); } interface AaveDataProviderInterface { - function getReserveTokensAddresses(address _asset) external view returns ( - address aTokenAddress, - address stableDebtTokenAddress, - address variableDebtTokenAddress - ); - function getUserReserveData(address _asset, address _user) external view returns ( - uint256 currentATokenBalance, - uint256 currentStableDebt, - uint256 currentVariableDebt, - uint256 principalStableDebt, - uint256 scaledVariableDebt, - uint256 stableBorrowRate, - uint256 liquidityRate, - uint40 stableRateLastUpdated, - bool usageAsCollateralEnabled - ); + function getReserveTokensAddresses(address _asset) + external + view + returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); + + function getUserReserveData(address _asset, address _user) + external + view + returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); + + function getReserveEModeCategory(address asset) + external + view + returns (uint256); } interface AaveAddressProviderRegistryInterface { - function getAddressesProvidersList() external view returns (address[] memory); + function getAddressesProvidersList() + external + view + returns (address[] memory); } interface ATokenInterface { - function balanceOf(address _user) external view returns(uint256); -} \ No newline at end of file + function balanceOf(address _user) external view returns (uint256); +} diff --git a/contracts/mainnet/connectors/aave/v3/main.sol b/contracts/mainnet/connectors/aave/v3/main.sol index d3f7d01a..d55e0339 100644 --- a/contracts/mainnet/connectors/aave/v3/main.sol +++ b/contracts/mainnet/connectors/aave/v3/main.sol @@ -1,7 +1,7 @@ pragma solidity ^0.7.0; /** - * @title Aave v2. + * @title Aave v3. * @dev Lending & Borrowing. */ @@ -12,204 +12,268 @@ import { Events } from "./events.sol"; import { AaveInterface } from "./interface.sol"; abstract contract AaveResolver is Events, Helpers { - /** - * @dev Deposit ETH/ERC20_Token. - * @notice Deposit a token to Aave v2 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 deposit( - address token, - uint256 amt, - uint256 getId, - uint256 setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _amt = getUint(getId, amt); + /** + * @dev Deposit ETH/ERC20_Token. + * @notice Deposit a token to Aave v2 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 deposit( + 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.getLendingPool()); + AaveInterface aave = AaveInterface(aaveProvider.getPool()); - bool isEth = token == ethAddr; - address _token = isEth ? wethAddr : token; + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; - TokenInterface tokenContract = TokenInterface(_token); + TokenInterface tokenContract = TokenInterface(_token); - if (isEth) { - _amt = _amt == uint(-1) ? address(this).balance : _amt; - convertEthToWeth(isEth, tokenContract, _amt); - } else { - _amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt; - } + 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); + approve(tokenContract, address(aave), _amt); - aave.deposit(_token, _amt, address(this), referralCode); + aave.supply(_token, _amt, address(this), referralCode); - if (!getIsColl(_token)) { - aave.setUserUseReserveAsCollateral(_token, true); - } + if (!getIsColl(_token)) { + aave.setUserUseReserveAsCollateral(_token, true); + } - setUint(setId, _amt); + setUint(setId, _amt); - _eventName = "LogDeposit(address,uint256,uint256,uint256)"; - _eventParam = abi.encode(token, _amt, getId, setId); - } + _eventName = "LogDeposit(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } - /** - * @dev Withdraw ETH/ERC20_Token. - * @notice Withdraw deposited token from Aave v2 - * @param token The address of the token to withdraw.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) - * @param getId ID to retrieve amt. - * @param setId ID stores the amount of tokens withdrawn. - */ - function withdraw( - address token, - uint256 amt, - uint256 getId, - uint256 setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _amt = getUint(getId, amt); + /** + * @dev Withdraw ETH/ERC20_Token. + * @notice Withdraw deposited token from Aave v2 + * @param token The address of the token to withdraw.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens withdrawn. + */ + function withdraw( + 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.getLendingPool()); - bool isEth = token == ethAddr; - address _token = isEth ? wethAddr : token; + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; - TokenInterface tokenContract = TokenInterface(_token); + TokenInterface tokenContract = TokenInterface(_token); - uint initialBal = tokenContract.balanceOf(address(this)); - aave.withdraw(_token, _amt, address(this)); - uint finalBal = tokenContract.balanceOf(address(this)); + uint256 initialBal = tokenContract.balanceOf(address(this)); + aave.withdraw(_token, _amt, address(this)); + uint256 finalBal = tokenContract.balanceOf(address(this)); - _amt = sub(finalBal, initialBal); + _amt = sub(finalBal, initialBal); - convertWethToEth(isEth, tokenContract, _amt); - - setUint(setId, _amt); + convertWethToEth(isEth, tokenContract, _amt); - _eventName = "LogWithdraw(address,uint256,uint256,uint256)"; - _eventParam = abi.encode(token, _amt, getId, setId); - } + setUint(setId, _amt); - /** - * @dev Borrow ETH/ERC20_Token. - * @notice Borrow a token using Aave v2 - * @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 getId ID to retrieve amt. - * @param setId ID stores the amount of tokens borrowed. - */ - function borrow( - address token, - uint256 amt, - uint256 rateMode, - uint256 getId, - uint256 setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _amt = getUint(getId, amt); + _eventName = "LogWithdraw(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } - AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + /** + * @dev Borrow ETH/ERC20_Token. + * @notice Borrow a token using Aave v2 + * @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 getId ID to retrieve amt. + * @param setId ID stores the amount of tokens borrowed. + */ + function borrow( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); - bool isEth = token == ethAddr; - address _token = isEth ? wethAddr : token; + AaveInterface aave = AaveInterface(aaveProvider.getPool()); - aave.borrow(_token, _amt, rateMode, referralCode, address(this)); - convertWethToEth(isEth, TokenInterface(_token), _amt); + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; - setUint(setId, _amt); + aave.borrow(_token, _amt, rateMode, referralCode, address(this)); + convertWethToEth(isEth, TokenInterface(_token), _amt); - _eventName = "LogBorrow(address,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(token, _amt, rateMode, getId, setId); - } + setUint(setId, _amt); - /** - * @dev Payback borrowed ETH/ERC20_Token. - * @notice Payback debt owed. - * @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param amt The amount of the token to payback. (For max: `uint256(-1)`) - * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) - * @param getId ID to retrieve amt. - * @param setId ID stores the amount of tokens paid back. - */ - function payback( - address token, - uint256 amt, - uint256 rateMode, - uint256 getId, - uint256 setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _amt = getUint(getId, amt); + _eventName = "LogBorrow(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } - AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + /** + * @dev Payback borrowed ETH/ERC20_Token. + * @notice Payback debt owed. + * @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function payback( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); - bool isEth = token == ethAddr; - address _token = isEth ? wethAddr : token; + AaveInterface aave = AaveInterface(aaveProvider.getPool()); - TokenInterface tokenContract = TokenInterface(_token); + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; - _amt = _amt == uint(-1) ? getPaybackBalance(_token, rateMode) : _amt; + TokenInterface tokenContract = TokenInterface(_token); - if (isEth) convertEthToWeth(isEth, tokenContract, _amt); + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; - approve(tokenContract, address(aave), _amt); + if (isEth) convertEthToWeth(isEth, tokenContract, _amt); - aave.repay(_token, _amt, rateMode, address(this)); + approve(tokenContract, address(aave), _amt); - setUint(setId, _amt); + aave.repay(_token, _amt, rateMode, address(this)); - _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(token, _amt, rateMode, getId, setId); - } + setUint(setId, _amt); - /** - * @dev Enable collateral - * @notice Enable an array of tokens as collateral - * @param tokens Array of tokens to enable collateral - */ - function enableCollateral( - address[] calldata tokens - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _length = tokens.length; - require(_length > 0, "0-tokens-not-allowed"); + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } - AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + /** + * @dev Payback borrowed ETH/ERC20_Token . + * @notice Payback debt owed. + * @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function paybackWithATokens( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); - for (uint i = 0; i < _length; i++) { - address token = tokens[i]; - if (getCollateralBalance(token) > 0 && !getIsColl(token)) { - aave.setUserUseReserveAsCollateral(token, true); - } - } + AaveInterface aave = AaveInterface(aaveProvider.getPool()); - _eventName = "LogEnableCollateral(address[])"; - _eventParam = abi.encode(tokens); - } + bool isEth = token == ethAddr; + address _token = isEth ? wethAddr : token; - /** - * @dev Swap borrow rate mode - * @notice Swaps user borrow rate mode between variable and stable - * @param token The address of the token to swap borrow rate.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2) - */ - function swapBorrowRateMode( - address token, - uint rateMode - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - AaveInterface aave = AaveInterface(aaveProvider.getLendingPool()); + TokenInterface tokenContract = TokenInterface(_token); - uint currentRateMode = rateMode == 1 ? 2 : 1; + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; - if (getPaybackBalance(token, currentRateMode) > 0) { - aave.swapBorrowRateMode(token, rateMode); - } + if (isEth) convertEthToWeth(isEth, tokenContract, _amt); - _eventName = "LogSwapRateMode(address,uint256)"; - _eventParam = abi.encode(token, rateMode); - } + approve(tokenContract, address(aave), _amt); + + aave.repayWithATokens(_token, _amt, rateMode); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Enable collateral + * @notice Enable an array of tokens as collateral + * @param tokens Array of tokens to enable collateral + */ + function enableCollateral(address[] calldata tokens) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _length = tokens.length; + require(_length > 0, "0-tokens-not-allowed"); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + for (uint256 i = 0; i < _length; i++) { + address token = tokens[i]; + if (getCollateralBalance(token) > 0 && !getIsColl(token)) { + aave.setUserUseReserveAsCollateral(token, true); + } + } + + _eventName = "LogEnableCollateral(address[])"; + _eventParam = abi.encode(tokens); + } + + /** + * @dev Swap borrow rate mode + * @notice Swaps user borrow rate mode between variable and stable + * @param token The address of the token to swap borrow rate.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2) + */ + function swapBorrowRateMode(address token, uint256 rateMode) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + uint256 currentRateMode = rateMode == 1 ? 2 : 1; + + if (getPaybackBalance(token, currentRateMode) > 0) { + aave.swapBorrowRateMode(token, rateMode); + } + + _eventName = "LogSwapRateMode(address,uint256)"; + _eventParam = abi.encode(token, rateMode); + } } -contract ConnectV2AaveV2 is AaveResolver { - string constant public name = "AaveV2-v1.1"; +contract ConnectV2AaveV3 is AaveResolver { + string public constant name = "AaveV3-v1.1"; } From 2842fed13af0896460d9a5b9727d4b7dc189f256 Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Mon, 21 Feb 2022 15:47:39 +0530 Subject: [PATCH 03/30] added e-mode func --- .../mainnet/connectors/aave/v3/events.sol | 35 +++++++++++++++---- contracts/mainnet/connectors/aave/v3/main.sol | 22 ++++++++++-- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/contracts/mainnet/connectors/aave/v3/events.sol b/contracts/mainnet/connectors/aave/v3/events.sol index 805b2209..9f60f22b 100644 --- a/contracts/mainnet/connectors/aave/v3/events.sol +++ b/contracts/mainnet/connectors/aave/v3/events.sol @@ -1,10 +1,33 @@ pragma solidity ^0.7.0; contract Events { - event LogDeposit(address indexed token, uint256 tokenAmt, uint256 getId, uint256 setId); - event LogWithdraw(address indexed token, uint256 tokenAmt, uint256 getId, uint256 setId); - event LogBorrow(address indexed token, uint256 tokenAmt, uint256 indexed rateMode, uint256 getId, uint256 setId); - event LogPayback(address indexed token, uint256 tokenAmt, uint256 indexed rateMode, uint256 getId, uint256 setId); - event LogEnableCollateral(address[] tokens); - event LogSwapRateMode(address indexed token, uint256 rateMode); + event LogDeposit( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogWithdraw( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogBorrow( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogPayback( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogEnableCollateral(address[] tokens); + event LogSwapRateMode(address indexed token, uint256 rateMode); + event LogSetUserEMode(uint8 categoryId); } diff --git a/contracts/mainnet/connectors/aave/v3/main.sol b/contracts/mainnet/connectors/aave/v3/main.sol index d55e0339..980ce1e0 100644 --- a/contracts/mainnet/connectors/aave/v3/main.sol +++ b/contracts/mainnet/connectors/aave/v3/main.sol @@ -182,8 +182,9 @@ abstract contract AaveResolver is Events, Helpers { } /** - * @dev Payback borrowed ETH/ERC20_Token . - * @notice Payback debt owed. + * @dev Payback borrowed ETH/ERC20_Token using aTokens. + * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the + * equivalent debt tokens. * @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param amt The amount of the token to payback. (For max: `uint256(-1)`) * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) @@ -272,6 +273,23 @@ abstract contract AaveResolver is Events, Helpers { _eventName = "LogSwapRateMode(address,uint256)"; _eventParam = abi.encode(token, rateMode); } + + /** + * @dev Set user e-mode + * @notice Updates the user's e-mode category + * @param categoryId The category Id of the e-mode user want to set + */ + function setUserEMode(uint8 categoryId) + external + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + aave.setUserEMode(categoryId); + + _eventName = "LogSetUserEMode(uint8)"; + _eventParam = abi.encode(categoryId); + } } contract ConnectV2AaveV3 is AaveResolver { From 713e618990c74994462e97fade3893084be2bc7a Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Mon, 21 Feb 2022 15:51:48 +0530 Subject: [PATCH 04/30] minor fix --- contracts/mainnet/connectors/aave/v3/main.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/mainnet/connectors/aave/v3/main.sol b/contracts/mainnet/connectors/aave/v3/main.sol index 980ce1e0..713f78a8 100644 --- a/contracts/mainnet/connectors/aave/v3/main.sol +++ b/contracts/mainnet/connectors/aave/v3/main.sol @@ -183,8 +183,7 @@ abstract contract AaveResolver is Events, Helpers { /** * @dev Payback borrowed ETH/ERC20_Token using aTokens. - * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the - * equivalent debt tokens. + * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the equivalent debt tokens. * @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param amt The amount of the token to payback. (For max: `uint256(-1)`) * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) From fb19080980e695c80f059f4b688bb0921d08523d Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Mon, 21 Feb 2022 21:50:51 +0530 Subject: [PATCH 05/30] fixed typo --- contracts/mainnet/connectors/aave/v3/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mainnet/connectors/aave/v3/main.sol b/contracts/mainnet/connectors/aave/v3/main.sol index 713f78a8..14ee9678 100644 --- a/contracts/mainnet/connectors/aave/v3/main.sol +++ b/contracts/mainnet/connectors/aave/v3/main.sol @@ -292,5 +292,5 @@ abstract contract AaveResolver is Events, Helpers { } contract ConnectV2AaveV3 is AaveResolver { - string public constant name = "AaveV3-v1.1"; + string public constant name = "AaveV3-v1.0"; } From c793ce0238223f60db13c1d23573dbb7d956de54 Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Sun, 6 Mar 2022 18:19:42 +0530 Subject: [PATCH 06/30] added connector on polygon --- .../aave/v2-to-v3-import/events.sol | 14 + .../aave/v2-to-v3-import/helpers.sol | 326 ++++++++++++++++++ .../aave/v2-to-v3-import/interfaces.sol | 150 ++++++++ .../connectors/aave/v2-to-v3-import/main.sol | 130 +++++++ 4 files changed, 620 insertions(+) create mode 100644 contracts/polygon/connectors/aave/v2-to-v3-import/events.sol create mode 100644 contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol create mode 100644 contracts/polygon/connectors/aave/v2-to-v3-import/interfaces.sol create mode 100644 contracts/polygon/connectors/aave/v2-to-v3-import/main.sol diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol new file mode 100644 index 00000000..3aa98805 --- /dev/null +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogAaveV2ImportToV3( + address indexed user, + bool convertStable, + address[] supplyTokens, + address[] borrowTokens, + uint256[] flashLoanFees, + uint256[] supplyAmts, + uint256[] stableBorrowAmts, + uint256[] variableBorrowAmts + ); +} diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol new file mode 100644 index 00000000..c05dc259 --- /dev/null +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol @@ -0,0 +1,326 @@ +pragma solidity ^0.7.0; + +import { DSMath } from "../../../common/math.sol"; +import { Basic } from "../../../common/basic.sol"; +import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol"; +import "./events.sol"; +import "./interfaces.sol"; + +abstract contract Helper is DSMath, Basic { + /** + * @dev Aave referal code + */ + uint16 internal constant referalCode = 3228; + + /** + * @dev AaveV2 Lending Pool Provider + */ + AaveV2LendingPoolProviderInterface internal constant aaveV2Provider = + AaveV2LendingPoolProviderInterface( + 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 // v2 address TODO: need to update this + ); + + /** + * @dev AaveV3 Lending Pool Provider + */ + AaveV3PoolProviderInterface internal constant aaveV3Provider = + AaveV3PoolProviderInterface( + 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 // v2 address TODO: need to update this + ); + + /** + * @dev Aave Protocol Data Provider + */ + AaveV2DataProviderInterface internal constant aaveData = + AaveV2DataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); // TODO: need to update this + + function getIsColl(address token, address user) + internal + view + returns (bool isCol) + { + (, , , , , , , , isCol) = aaveData.getUserReserveData(token, user); + } + + struct ImportData { + address[] _supplyTokens; + address[] _borrowTokens; + ATokenV2Interface[] aTokens; + uint256[] supplyAmts; + uint256[] variableBorrowAmts; + uint256[] variableBorrowAmtsWithFee; + uint256[] stableBorrowAmts; + uint256[] stableBorrowAmtsWithFee; + uint256[] totalBorrowAmts; + uint256[] totalBorrowAmtsWithFee; + bool convertStable; + } + + struct ImportInputData { + address[] supplyTokens; + address[] borrowTokens; + bool convertStable; + uint256[] flashLoanFees; + } +} + +contract _AaveHelper is Helper { + function getBorrowAmount(address _token, address userAccount) + internal + view + returns (uint256 stableBorrow, uint256 variableBorrow) + { + ( + , + address stableDebtTokenAddress, + address variableDebtTokenAddress + ) = aaveData.getReserveTokensAddresses(_token); + + stableBorrow = ATokenV2Interface(stableDebtTokenAddress).balanceOf( + userAccount + ); + variableBorrow = ATokenV2Interface(variableDebtTokenAddress).balanceOf( + userAccount + ); + } + + function getBorrowAmounts( + address userAccount, + AaveV2Interface aaveV2, + ImportInputData memory inputData, + ImportData memory data + ) internal returns (ImportData memory) { + if (inputData.borrowTokens.length > 0) { + data._borrowTokens = new address[](inputData.borrowTokens.length); + data.variableBorrowAmts = new uint256[]( + inputData.borrowTokens.length + ); + data.stableBorrowAmts = new uint256[]( + inputData.borrowTokens.length + ); + data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length); + for (uint256 i = 0; i < inputData.borrowTokens.length; i++) { + for (uint256 j = i; j < inputData.borrowTokens.length; j++) { + if (j != i) { + require( + inputData.borrowTokens[i] != + inputData.borrowTokens[j], + "token-repeated" + ); + } + } + } + for (uint256 i = 0; i < inputData.borrowTokens.length; i++) { + address _token = inputData.borrowTokens[i] == maticAddr + ? wmaticAddr + : inputData.borrowTokens[i]; + data._borrowTokens[i] = _token; + + ( + data.stableBorrowAmts[i], + data.variableBorrowAmts[i] + ) = getBorrowAmount(_token, userAccount); + + if (data.variableBorrowAmts[i] != 0) { + data.variableBorrowAmtsWithFee[i] = add( + data.variableBorrowAmts[i], + inputData.flashLoanFees[i] + ); + data.stableBorrowAmtsWithFee[i] = data.stableBorrowAmts[i]; + } else { + data.stableBorrowAmtsWithFee[i] = add( + data.stableBorrowAmts[i], + inputData.flashLoanFees[i] + ); + } + + data.totalBorrowAmts[i] = add( + data.stableBorrowAmts[i], + data.variableBorrowAmts[i] + ); + data.totalBorrowAmtsWithFee[i] = add( + data.stableBorrowAmtsWithFee[i], + data.variableBorrowAmtsWithFee[i] + ); + + if (data.totalBorrowAmts[i] > 0) { + uint256 _amt = data.totalBorrowAmts[i]; + TokenInterface(_token).approve(address(aaveV2), _amt); + } + } + } + return data; + } + + function getSupplyAmounts( + address userAccount, + ImportInputData memory inputData, + ImportData memory data + ) internal view returns (ImportData memory) { + data.supplyAmts = new uint256[](inputData.supplyTokens.length); + data._supplyTokens = new address[](inputData.supplyTokens.length); + data.aTokens = new ATokenV2Interface[](inputData.supplyTokens.length); + + for (uint256 i = 0; i < inputData.supplyTokens.length; i++) { + for (uint256 j = i; j < inputData.supplyTokens.length; j++) { + if (j != i) { + require( + inputData.supplyTokens[i] != inputData.supplyTokens[j], + "token-repeated" + ); + } + } + } + for (uint256 i = 0; i < inputData.supplyTokens.length; i++) { + address _token = inputData.supplyTokens[i] == maticAddr + ? wmaticAddr + : inputData.supplyTokens[i]; + (address _aToken, , ) = aaveData.getReserveTokensAddresses(_token); + data._supplyTokens[i] = _token; + data.aTokens[i] = ATokenV2Interface(_aToken); + data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount); + } + + return data; + } + + function _paybackBehalfOne( + AaveV2Interface aaveV2, + address token, + uint256 amt, + uint256 rateMode, + address user + ) private { + aaveV2.repay(token, amt, rateMode, user); + } + + function _PaybackStable( + uint256 _length, + AaveV2Interface aaveV2, + address[] memory tokens, + uint256[] memory amts, + address user + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + _paybackBehalfOne(aaveV2, tokens[i], amts[i], 1, user); + } + } + } + + function _PaybackVariable( + uint256 _length, + AaveV2Interface aaveV2, + address[] memory tokens, + uint256[] memory amts, + address user + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + _paybackBehalfOne(aaveV2, tokens[i], amts[i], 2, user); + } + } + } + + function _TransferAtokens( + uint256 _length, + AaveV2Interface aaveV2, + ATokenV2Interface[] memory atokenContracts, + uint256[] memory amts, + address[] memory tokens, + address userAccount + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + require( + atokenContracts[i].transferFrom( + userAccount, + address(this), + _amt + ), + "allowance?" + ); + + if (!getIsColl(tokens[i], address(this))) { + aaveV2.setUserUseReserveAsCollateral(tokens[i], true); + } + } + } + } + + function _WithdrawTokensFromV2( + uint256 _length, + AaveV2Interface aaveV2, + uint256[] memory amts, + address[] memory tokens + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + address _token = tokens[i]; + aaveV2.withdraw(_token, _amt, address(this)); + } + } + } + + function _depositTokensInV3( + uint256 _length, + AaveV3Interface aaveV3, + uint256[] memory amts, + address[] memory tokens + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + address _token = tokens[i]; + TokenInterface tokenContract = TokenInterface(_token); + require( + tokenContract.balanceOf(address(this)) >= _amt, + "Insufficient funds to deposit in v3" + ); + approve(tokenContract, address(aaveV3), _amt); + aaveV3.supply(_token, _amt, address(this), referalCode); + + if (!getIsColl(_token, address(this))) { + aaveV3.setUserUseReserveAsCollateral(_token, true); + } + } + } + } + + function _BorrowVariable( + uint256 _length, + AaveV3Interface aaveV3, + address[] memory tokens, + uint256[] memory amts + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + _borrowOne(aaveV3, tokens[i], amts[i], 2); + } + } + } + + function _BorrowStable( + uint256 _length, + AaveV3Interface aaveV3, + address[] memory tokens, + uint256[] memory amts + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + _borrowOne(aaveV3, tokens[i], amts[i], 1); + } + } + } + + function _borrowOne( + AaveV3Interface aaveV3, + address token, + uint256 amt, + uint256 rateMode + ) private { + aaveV3.borrow(token, amt, rateMode, referalCode, address(this)); + } +} diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/interfaces.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/interfaces.sol new file mode 100644 index 00000000..b28f49e0 --- /dev/null +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/interfaces.sol @@ -0,0 +1,150 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +// aave v2 +interface AaveV2Interface { + function withdraw( + address _asset, + uint256 _amount, + address _to + ) external; + + function borrow( + address _asset, + uint256 _amount, + uint256 _interestRateMode, + uint16 _referralCode, + address _onBehalfOf + ) external; + + function repay( + address _asset, + uint256 _amount, + uint256 _rateMode, + address _onBehalfOf + ) external; + + function setUserUseReserveAsCollateral( + address _asset, + bool _useAsCollateral + ) external; + + function getUserAccountData(address user) + external + view + returns ( + uint256 totalCollateralETH, + uint256 totalDebtETH, + uint256 availableBorrowsETH, + uint256 currentLiquidationThreshold, + uint256 ltv, + uint256 healthFactor + ); +} + +interface AaveV2LendingPoolProviderInterface { + function getLendingPool() external view returns (address); +} + +// Aave Protocol Data Provider +interface AaveV2DataProviderInterface { + function getUserReserveData(address _asset, address _user) + external + view + returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); + + // function getReserveConfigurationData(address asset) + // external + // view + // returns ( + // uint256 decimals, + // uint256 ltv, + // uint256 liquidationThreshold, + // uint256 liquidationBonus, + // uint256 reserveFactor, + // bool usageAsCollateralEnabled, + // bool borrowingEnabled, + // bool stableBorrowRateEnabled, + // bool isActive, + // bool isFrozen + // ); + + function getReserveTokensAddresses(address asset) + external + view + returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); +} + +interface ATokenV2Interface { + function scaledBalanceOf(address _user) external view returns (uint256); + + function isTransferAllowed(address _user, uint256 _amount) + external + view + returns (bool); + + function balanceOf(address _user) external view returns (uint256); + + function transferFrom( + address, + address, + uint256 + ) external returns (bool); + + function allowance(address, address) external returns (uint256); +} + +// aave v3 +interface AaveV3Interface { + function supply( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + function withdraw( + address asset, + uint256 amount, + address to + ) external returns (uint256); + + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) external; + + function repay( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf + ) external returns (uint256); + + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) + external; + + function swapBorrowRateMode(address asset, uint256 interestRateMode) + external; +} + +interface AaveV3PoolProviderInterface { + function getPool() external view returns (address); +} diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol new file mode 100644 index 00000000..d4574198 --- /dev/null +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol @@ -0,0 +1,130 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol"; +import "./interfaces.sol"; +import "./helpers.sol"; +import "./events.sol"; + +contract _AaveV2ToV3MigrationResolver is _AaveHelper { + function _importAave(address userAccount, ImportInputData memory inputData) + internal + returns (string memory _eventName, bytes memory _eventParam) + { + require( + AccountInterface(address(this)).isAuth(userAccount), + "user-account-not-auth" + ); + + require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); + + ImportData memory data; + + AaveV2Interface aaveV2 = AaveV2Interface( + aaveV2Provider.getLendingPool() + ); + AaveV3Interface aaveV3 = AaveV3Interface(aaveV3Provider.getPool()); + + data = getBorrowAmounts(userAccount, aaveV2, inputData, data); + data = getSupplyAmounts(userAccount, inputData, data); + + // payback borrowed amount; + _PaybackStable( + data._borrowTokens.length, + aaveV2, + data._borrowTokens, + data.stableBorrowAmts, + userAccount + ); + _PaybackVariable( + data._borrowTokens.length, + aaveV2, + data._borrowTokens, + data.variableBorrowAmts, + userAccount + ); + + // transfer atokens to this address; + _TransferAtokens( + data._supplyTokens.length, + aaveV2, + data.aTokens, + data.supplyAmts, + data._supplyTokens, + userAccount + ); + + // withdraw v2 supplied tokens + _WithdrawTokensFromV2( + data._supplyTokens.length, + aaveV2, + data.supplyAmts, + data._supplyTokens + ); + // deposit tokens in v3 + _depositTokensInV3( + data._supplyTokens.length, + aaveV3, + data.supplyAmts, + data._supplyTokens + ); + + // borrow assets in aave v3 after migrating position + if (data.convertStable) { + _BorrowVariable( + data._borrowTokens.length, + aaveV3, + data._borrowTokens, + data.totalBorrowAmtsWithFee + ); + } else { + _BorrowStable( + data._borrowTokens.length, + aaveV3, + data._borrowTokens, + data.stableBorrowAmtsWithFee + ); + _BorrowVariable( + data._borrowTokens.length, + aaveV3, + data._borrowTokens, + data.variableBorrowAmtsWithFee + ); + } + + _eventName = "LogAaveV2ImportToV3(address,bool,address[],address[],uint256,uint256[],uint256[],uint256[])"; + _eventParam = abi.encode( + userAccount, + inputData.convertStable, + inputData.supplyTokens, + inputData.borrowTokens, + inputData.flashLoanFees, + data.supplyAmts, + data.stableBorrowAmts, + data.variableBorrowAmts + ); + } + + function importAaveV2ToV3( + address userAccount, + ImportInputData memory inputData + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + (_eventName, _eventParam) = _importAave(userAccount, inputData); + } + + function migrateAaveV2ToV3(ImportInputData memory inputData) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + (_eventName, _eventParam) = _importAave(msg.sender, inputData); + } +} + +contract AaveV2ToV3MigrationResolverPolygon is _AaveV2ToV3MigrationResolver { + string public constant name = "Aave-v2-to-v3-import"; +} From ae6598b2f6a1006d5e2f4a15191110c74d9c5a55 Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Sun, 6 Mar 2022 18:19:55 +0530 Subject: [PATCH 07/30] added connector on avalanche --- .../aave/v2-to-v3-import/events.sol | 14 + .../aave/v2-to-v3-import/helpers.sol | 326 ++++++++++++++++++ .../aave/v2-to-v3-import/interfaces.sol | 150 ++++++++ .../connectors/aave/v2-to-v3-import/main.sol | 130 +++++++ 4 files changed, 620 insertions(+) create mode 100644 contracts/avalanche/connectors/aave/v2-to-v3-import/events.sol create mode 100644 contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol create mode 100644 contracts/avalanche/connectors/aave/v2-to-v3-import/interfaces.sol create mode 100644 contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/events.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/events.sol new file mode 100644 index 00000000..3aa98805 --- /dev/null +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/events.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogAaveV2ImportToV3( + address indexed user, + bool convertStable, + address[] supplyTokens, + address[] borrowTokens, + uint256[] flashLoanFees, + uint256[] supplyAmts, + uint256[] stableBorrowAmts, + uint256[] variableBorrowAmts + ); +} diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol new file mode 100644 index 00000000..d4dab63a --- /dev/null +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol @@ -0,0 +1,326 @@ +pragma solidity ^0.7.0; + +import { DSMath } from "../../../common/math.sol"; +import { Basic } from "../../../common/basic.sol"; +import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol"; +import "./events.sol"; +import "./interfaces.sol"; + +abstract contract Helper is DSMath, Basic { + /** + * @dev Aave referal code + */ + uint16 internal constant referalCode = 3228; + + /** + * @dev AaveV2 Lending Pool Provider + */ + AaveV2LendingPoolProviderInterface internal constant aaveV2Provider = + AaveV2LendingPoolProviderInterface( + 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 // v2 address TODO: need to update this + ); + + /** + * @dev AaveV3 Lending Pool Provider + */ + AaveV3PoolProviderInterface internal constant aaveV3Provider = + AaveV3PoolProviderInterface( + 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 // v2 address TODO: need to update this + ); + + /** + * @dev Aave Protocol Data Provider + */ + AaveV2DataProviderInterface internal constant aaveData = + AaveV2DataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); // TODO: need to update this + + function getIsColl(address token, address user) + internal + view + returns (bool isCol) + { + (, , , , , , , , isCol) = aaveData.getUserReserveData(token, user); + } + + struct ImportData { + address[] _supplyTokens; + address[] _borrowTokens; + ATokenV2Interface[] aTokens; + uint256[] supplyAmts; + uint256[] variableBorrowAmts; + uint256[] variableBorrowAmtsWithFee; + uint256[] stableBorrowAmts; + uint256[] stableBorrowAmtsWithFee; + uint256[] totalBorrowAmts; + uint256[] totalBorrowAmtsWithFee; + bool convertStable; + } + + struct ImportInputData { + address[] supplyTokens; + address[] borrowTokens; + bool convertStable; + uint256[] flashLoanFees; + } +} + +contract _AaveHelper is Helper { + function getBorrowAmount(address _token, address userAccount) + internal + view + returns (uint256 stableBorrow, uint256 variableBorrow) + { + ( + , + address stableDebtTokenAddress, + address variableDebtTokenAddress + ) = aaveData.getReserveTokensAddresses(_token); + + stableBorrow = ATokenV2Interface(stableDebtTokenAddress).balanceOf( + userAccount + ); + variableBorrow = ATokenV2Interface(variableDebtTokenAddress).balanceOf( + userAccount + ); + } + + function getBorrowAmounts( + address userAccount, + AaveV2Interface aaveV2, + ImportInputData memory inputData, + ImportData memory data + ) internal returns (ImportData memory) { + if (inputData.borrowTokens.length > 0) { + data._borrowTokens = new address[](inputData.borrowTokens.length); + data.variableBorrowAmts = new uint256[]( + inputData.borrowTokens.length + ); + data.stableBorrowAmts = new uint256[]( + inputData.borrowTokens.length + ); + data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length); + for (uint256 i = 0; i < inputData.borrowTokens.length; i++) { + for (uint256 j = i; j < inputData.borrowTokens.length; j++) { + if (j != i) { + require( + inputData.borrowTokens[i] != + inputData.borrowTokens[j], + "token-repeated" + ); + } + } + } + for (uint256 i = 0; i < inputData.borrowTokens.length; i++) { + address _token = inputData.borrowTokens[i] == avaxAddr + ? wavaxAddr + : inputData.borrowTokens[i]; + data._borrowTokens[i] = _token; + + ( + data.stableBorrowAmts[i], + data.variableBorrowAmts[i] + ) = getBorrowAmount(_token, userAccount); + + if (data.variableBorrowAmts[i] != 0) { + data.variableBorrowAmtsWithFee[i] = add( + data.variableBorrowAmts[i], + inputData.flashLoanFees[i] + ); + data.stableBorrowAmtsWithFee[i] = data.stableBorrowAmts[i]; + } else { + data.stableBorrowAmtsWithFee[i] = add( + data.stableBorrowAmts[i], + inputData.flashLoanFees[i] + ); + } + + data.totalBorrowAmts[i] = add( + data.stableBorrowAmts[i], + data.variableBorrowAmts[i] + ); + data.totalBorrowAmtsWithFee[i] = add( + data.stableBorrowAmtsWithFee[i], + data.variableBorrowAmtsWithFee[i] + ); + + if (data.totalBorrowAmts[i] > 0) { + uint256 _amt = data.totalBorrowAmts[i]; + TokenInterface(_token).approve(address(aaveV2), _amt); + } + } + } + return data; + } + + function getSupplyAmounts( + address userAccount, + ImportInputData memory inputData, + ImportData memory data + ) internal view returns (ImportData memory) { + data.supplyAmts = new uint256[](inputData.supplyTokens.length); + data._supplyTokens = new address[](inputData.supplyTokens.length); + data.aTokens = new ATokenV2Interface[](inputData.supplyTokens.length); + + for (uint256 i = 0; i < inputData.supplyTokens.length; i++) { + for (uint256 j = i; j < inputData.supplyTokens.length; j++) { + if (j != i) { + require( + inputData.supplyTokens[i] != inputData.supplyTokens[j], + "token-repeated" + ); + } + } + } + for (uint256 i = 0; i < inputData.supplyTokens.length; i++) { + address _token = inputData.supplyTokens[i] == avaxAddr + ? wavaxAddr + : inputData.supplyTokens[i]; + (address _aToken, , ) = aaveData.getReserveTokensAddresses(_token); + data._supplyTokens[i] = _token; + data.aTokens[i] = ATokenV2Interface(_aToken); + data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount); + } + + return data; + } + + function _paybackBehalfOne( + AaveV2Interface aaveV2, + address token, + uint256 amt, + uint256 rateMode, + address user + ) private { + aaveV2.repay(token, amt, rateMode, user); + } + + function _PaybackStable( + uint256 _length, + AaveV2Interface aaveV2, + address[] memory tokens, + uint256[] memory amts, + address user + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + _paybackBehalfOne(aaveV2, tokens[i], amts[i], 1, user); + } + } + } + + function _PaybackVariable( + uint256 _length, + AaveV2Interface aaveV2, + address[] memory tokens, + uint256[] memory amts, + address user + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + _paybackBehalfOne(aaveV2, tokens[i], amts[i], 2, user); + } + } + } + + function _TransferAtokens( + uint256 _length, + AaveV2Interface aaveV2, + ATokenV2Interface[] memory atokenContracts, + uint256[] memory amts, + address[] memory tokens, + address userAccount + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + require( + atokenContracts[i].transferFrom( + userAccount, + address(this), + _amt + ), + "allowance?" + ); + + if (!getIsColl(tokens[i], address(this))) { + aaveV2.setUserUseReserveAsCollateral(tokens[i], true); + } + } + } + } + + function _WithdrawTokensFromV2( + uint256 _length, + AaveV2Interface aaveV2, + uint256[] memory amts, + address[] memory tokens + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + address _token = tokens[i]; + aaveV2.withdraw(_token, _amt, address(this)); + } + } + } + + function _depositTokensInV3( + uint256 _length, + AaveV3Interface aaveV3, + uint256[] memory amts, + address[] memory tokens + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + uint256 _amt = amts[i]; + address _token = tokens[i]; + TokenInterface tokenContract = TokenInterface(_token); + require( + tokenContract.balanceOf(address(this)) >= _amt, + "Insufficient funds to deposit in v3" + ); + approve(tokenContract, address(aaveV3), _amt); + aaveV3.supply(_token, _amt, address(this), referalCode); + + if (!getIsColl(_token, address(this))) { + aaveV3.setUserUseReserveAsCollateral(_token, true); + } + } + } + } + + function _BorrowVariable( + uint256 _length, + AaveV3Interface aaveV3, + address[] memory tokens, + uint256[] memory amts + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + _borrowOne(aaveV3, tokens[i], amts[i], 2); + } + } + } + + function _BorrowStable( + uint256 _length, + AaveV3Interface aaveV3, + address[] memory tokens, + uint256[] memory amts + ) internal { + for (uint256 i = 0; i < _length; i++) { + if (amts[i] > 0) { + _borrowOne(aaveV3, tokens[i], amts[i], 1); + } + } + } + + function _borrowOne( + AaveV3Interface aaveV3, + address token, + uint256 amt, + uint256 rateMode + ) private { + aaveV3.borrow(token, amt, rateMode, referalCode, address(this)); + } +} diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/interfaces.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/interfaces.sol new file mode 100644 index 00000000..b28f49e0 --- /dev/null +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/interfaces.sol @@ -0,0 +1,150 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +// aave v2 +interface AaveV2Interface { + function withdraw( + address _asset, + uint256 _amount, + address _to + ) external; + + function borrow( + address _asset, + uint256 _amount, + uint256 _interestRateMode, + uint16 _referralCode, + address _onBehalfOf + ) external; + + function repay( + address _asset, + uint256 _amount, + uint256 _rateMode, + address _onBehalfOf + ) external; + + function setUserUseReserveAsCollateral( + address _asset, + bool _useAsCollateral + ) external; + + function getUserAccountData(address user) + external + view + returns ( + uint256 totalCollateralETH, + uint256 totalDebtETH, + uint256 availableBorrowsETH, + uint256 currentLiquidationThreshold, + uint256 ltv, + uint256 healthFactor + ); +} + +interface AaveV2LendingPoolProviderInterface { + function getLendingPool() external view returns (address); +} + +// Aave Protocol Data Provider +interface AaveV2DataProviderInterface { + function getUserReserveData(address _asset, address _user) + external + view + returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); + + // function getReserveConfigurationData(address asset) + // external + // view + // returns ( + // uint256 decimals, + // uint256 ltv, + // uint256 liquidationThreshold, + // uint256 liquidationBonus, + // uint256 reserveFactor, + // bool usageAsCollateralEnabled, + // bool borrowingEnabled, + // bool stableBorrowRateEnabled, + // bool isActive, + // bool isFrozen + // ); + + function getReserveTokensAddresses(address asset) + external + view + returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); +} + +interface ATokenV2Interface { + function scaledBalanceOf(address _user) external view returns (uint256); + + function isTransferAllowed(address _user, uint256 _amount) + external + view + returns (bool); + + function balanceOf(address _user) external view returns (uint256); + + function transferFrom( + address, + address, + uint256 + ) external returns (bool); + + function allowance(address, address) external returns (uint256); +} + +// aave v3 +interface AaveV3Interface { + function supply( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + function withdraw( + address asset, + uint256 amount, + address to + ) external returns (uint256); + + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) external; + + function repay( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf + ) external returns (uint256); + + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) + external; + + function swapBorrowRateMode(address asset, uint256 interestRateMode) + external; +} + +interface AaveV3PoolProviderInterface { + function getPool() external view returns (address); +} diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol new file mode 100644 index 00000000..a8b74e8f --- /dev/null +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol @@ -0,0 +1,130 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol"; +import "./interfaces.sol"; +import "./helpers.sol"; +import "./events.sol"; + +contract _AaveV2ToV3MigrationResolver is _AaveHelper { + function _importAave(address userAccount, ImportInputData memory inputData) + internal + returns (string memory _eventName, bytes memory _eventParam) + { + require( + AccountInterface(address(this)).isAuth(userAccount), + "user-account-not-auth" + ); + + require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); + + ImportData memory data; + + AaveV2Interface aaveV2 = AaveV2Interface( + aaveV2Provider.getLendingPool() + ); + AaveV3Interface aaveV3 = AaveV3Interface(aaveV3Provider.getPool()); + + data = getBorrowAmounts(userAccount, aaveV2, inputData, data); + data = getSupplyAmounts(userAccount, inputData, data); + + // payback borrowed amount; + _PaybackStable( + data._borrowTokens.length, + aaveV2, + data._borrowTokens, + data.stableBorrowAmts, + userAccount + ); + _PaybackVariable( + data._borrowTokens.length, + aaveV2, + data._borrowTokens, + data.variableBorrowAmts, + userAccount + ); + + // transfer atokens to this address; + _TransferAtokens( + data._supplyTokens.length, + aaveV2, + data.aTokens, + data.supplyAmts, + data._supplyTokens, + userAccount + ); + + // withdraw v2 supplied tokens + _WithdrawTokensFromV2( + data._supplyTokens.length, + aaveV2, + data.supplyAmts, + data._supplyTokens + ); + // deposit tokens in v3 + _depositTokensInV3( + data._supplyTokens.length, + aaveV3, + data.supplyAmts, + data._supplyTokens + ); + + // borrow assets in aave v3 after migrating position + if (data.convertStable) { + _BorrowVariable( + data._borrowTokens.length, + aaveV3, + data._borrowTokens, + data.totalBorrowAmtsWithFee + ); + } else { + _BorrowStable( + data._borrowTokens.length, + aaveV3, + data._borrowTokens, + data.stableBorrowAmtsWithFee + ); + _BorrowVariable( + data._borrowTokens.length, + aaveV3, + data._borrowTokens, + data.variableBorrowAmtsWithFee + ); + } + + _eventName = "LogAaveV2ImportToV3(address,bool,address[],address[],uint256,uint256[],uint256[],uint256[])"; + _eventParam = abi.encode( + userAccount, + inputData.convertStable, + inputData.supplyTokens, + inputData.borrowTokens, + inputData.flashLoanFees, + data.supplyAmts, + data.stableBorrowAmts, + data.variableBorrowAmts + ); + } + + function importAaveV2ToV3( + address userAccount, + ImportInputData memory inputData + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + (_eventName, _eventParam) = _importAave(userAccount, inputData); + } + + function migrateAaveV2ToV3(ImportInputData memory inputData) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + (_eventName, _eventParam) = _importAave(msg.sender, inputData); + } +} + +contract AaveV2ToV3MigrationResolverAvalanche is _AaveV2ToV3MigrationResolver { + string public constant name = "Aave-v2-to-v3-import"; +} From bbeee1727e11f77cd28d7a83fec3859f90995e2d Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Sun, 6 Mar 2022 18:51:41 +0530 Subject: [PATCH 08/30] added connector on polygon --- .../polygon/connectors/aave/v3/events.sol | 33 ++ .../polygon/connectors/aave/v3/helpers.sol | 66 ++++ .../polygon/connectors/aave/v3/interface.sol | 91 ++++++ contracts/polygon/connectors/aave/v3/main.sol | 296 ++++++++++++++++++ 4 files changed, 486 insertions(+) create mode 100644 contracts/polygon/connectors/aave/v3/events.sol create mode 100644 contracts/polygon/connectors/aave/v3/helpers.sol create mode 100644 contracts/polygon/connectors/aave/v3/interface.sol create mode 100644 contracts/polygon/connectors/aave/v3/main.sol diff --git a/contracts/polygon/connectors/aave/v3/events.sol b/contracts/polygon/connectors/aave/v3/events.sol new file mode 100644 index 00000000..9f60f22b --- /dev/null +++ b/contracts/polygon/connectors/aave/v3/events.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDeposit( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogWithdraw( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogBorrow( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogPayback( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogEnableCollateral(address[] tokens); + event LogSwapRateMode(address indexed token, uint256 rateMode); + event LogSetUserEMode(uint8 categoryId); +} diff --git a/contracts/polygon/connectors/aave/v3/helpers.sol b/contracts/polygon/connectors/aave/v3/helpers.sol new file mode 100644 index 00000000..13431d11 --- /dev/null +++ b/contracts/polygon/connectors/aave/v3/helpers.sol @@ -0,0 +1,66 @@ +pragma solidity ^0.7.0; + +import { DSMath } from "../../../common/math.sol"; +import { Basic } from "../../../common/basic.sol"; +import { AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + /** + * @dev Aave Pool Provider + */ + AavePoolProviderInterface internal constant aaveProvider = + AavePoolProviderInterface(0xA55125A90d75a95EC00130E8E8C197dB5641Eb19); // rinkeby address + + /** + * @dev Aave Pool Data Provider + */ + AaveDataProviderInterface internal constant aaveData = + AaveDataProviderInterface(0x256bBbeDbA70a1240a1EB64210abB1b063267408); // rinkeby address + + /** + * @dev Aave Referral Code + */ + uint16 internal constant referralCode = 3228; + + /** + * @dev Checks if collateral is enabled for an asset + * @param token token address of the asset.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + + function getIsColl(address token) internal view returns (bool isCol) { + (, , , , , , , , isCol) = aaveData.getUserReserveData( + token, + address(this) + ); + } + + /** + * @dev Get total debt balance & fee for an asset + * @param token token address of the debt.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Borrow rate mode (Stable = 1, Variable = 2) + */ + function getPaybackBalance(address token, uint256 rateMode) + internal + view + returns (uint256) + { + (, uint256 stableDebt, uint256 variableDebt, , , , , , ) = aaveData + .getUserReserveData(token, address(this)); + return rateMode == 1 ? stableDebt : variableDebt; + } + + /** + * @dev Get total collateral balance for an asset + * @param token token address of the collateral.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + function getCollateralBalance(address token) + internal + view + returns (uint256 bal) + { + (bal, , , , , , , , ) = aaveData.getUserReserveData( + token, + address(this) + ); + } +} diff --git a/contracts/polygon/connectors/aave/v3/interface.sol b/contracts/polygon/connectors/aave/v3/interface.sol new file mode 100644 index 00000000..8ae14716 --- /dev/null +++ b/contracts/polygon/connectors/aave/v3/interface.sol @@ -0,0 +1,91 @@ +pragma solidity ^0.7.0; + +interface AaveInterface { + function supply( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + function withdraw( + address asset, + uint256 amount, + address to + ) external returns (uint256); + + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) external; + + function repay( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf + ) external returns (uint256); + + function repayWithATokens( + address asset, + uint256 amount, + uint256 interestRateMode + ) external returns (uint256); + + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) + external; + + function swapBorrowRateMode(address asset, uint256 interestRateMode) + external; + + function setUserEMode(uint8 categoryId) external; +} + +interface AavePoolProviderInterface { + function getPool() external view returns (address); +} + +interface AaveDataProviderInterface { + function getReserveTokensAddresses(address _asset) + external + view + returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); + + function getUserReserveData(address _asset, address _user) + external + view + returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); + + function getReserveEModeCategory(address asset) + external + view + returns (uint256); +} + +interface AaveAddressProviderRegistryInterface { + function getAddressesProvidersList() + external + view + returns (address[] memory); +} + +interface ATokenInterface { + function balanceOf(address _user) external view returns (uint256); +} diff --git a/contracts/polygon/connectors/aave/v3/main.sol b/contracts/polygon/connectors/aave/v3/main.sol new file mode 100644 index 00000000..39038f75 --- /dev/null +++ b/contracts/polygon/connectors/aave/v3/main.sol @@ -0,0 +1,296 @@ +pragma solidity ^0.7.0; + +/** + * @title Aave v3. + * @dev Lending & Borrowing. + */ + +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"; + +abstract contract AaveResolver is Events, Helpers { + /** + * @dev Deposit Matic/ERC20_Token. + * @notice Deposit a token to Aave v3 for lending / collaterization. + * @param token The address of the token to deposit.(For Matic: 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 deposit( + 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 isMatic = token == maticAddr; + address _token = isMatic ? wmaticAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + if (isMatic) { + _amt = _amt == uint256(-1) ? address(this).balance : _amt; + convertMaticToWmatic(isMatic, 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 (!getIsColl(_token)) { + aave.setUserUseReserveAsCollateral(_token, true); + } + + setUint(setId, _amt); + + _eventName = "LogDeposit(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } + + /** + * @dev Withdraw matic/ERC20_Token. + * @notice Withdraw deposited token from Aave v2 + * @param token The address of the token to withdraw.(For matic: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens withdrawn. + */ + function withdraw( + 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 isMatic = token == maticAddr; + address _token = isMatic ? wmaticAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + uint256 initialBal = tokenContract.balanceOf(address(this)); + aave.withdraw(_token, _amt, address(this)); + uint256 finalBal = tokenContract.balanceOf(address(this)); + + _amt = sub(finalBal, initialBal); + + convertWmaticToMatic(isMatic, tokenContract, _amt); + + setUint(setId, _amt); + + _eventName = "LogWithdraw(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } + + /** + * @dev Borrow matic/ERC20_Token. + * @notice Borrow a token using Aave v2 + * @param token The address of the token to borrow.(For matic: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to borrow. + * @param rateMode The type of borrow debt. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens borrowed. + */ + function borrow( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isMatic = token == maticAddr; + address _token = isMatic ? wmaticAddr : token; + + aave.borrow(_token, _amt, rateMode, referralCode, address(this)); + convertWmaticToMatic(isMatic, TokenInterface(_token), _amt); + + setUint(setId, _amt); + + _eventName = "LogBorrow(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Payback borrowed matic/ERC20_Token. + * @notice Payback debt owed. + * @param token The address of the token to payback.(For matic: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function payback( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isMatic = token == maticAddr; + address _token = isMatic ? wmaticAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isMatic) convertMaticToWmatic(isMatic, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repay(_token, _amt, rateMode, address(this)); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Payback borrowed matic/ERC20_Token using aTokens. + * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the equivalent debt tokens. + * @param token The address of the token to payback.(For matic: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function paybackWithATokens( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isMatic = token == maticAddr; + address _token = isMatic ? wmaticAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isMatic) convertMaticToWmatic(isMatic, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repayWithATokens(_token, _amt, rateMode); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Enable collateral + * @notice Enable an array of tokens as collateral + * @param tokens Array of tokens to enable collateral + */ + function enableCollateral(address[] calldata tokens) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _length = tokens.length; + require(_length > 0, "0-tokens-not-allowed"); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + for (uint256 i = 0; i < _length; i++) { + address token = tokens[i]; + if (getCollateralBalance(token) > 0 && !getIsColl(token)) { + aave.setUserUseReserveAsCollateral(token, true); + } + } + + _eventName = "LogEnableCollateral(address[])"; + _eventParam = abi.encode(tokens); + } + + /** + * @dev Swap borrow rate mode + * @notice Swaps user borrow rate mode between variable and stable + * @param token The address of the token to swap borrow rate.(For matic: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2) + */ + function swapBorrowRateMode(address token, uint256 rateMode) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + uint256 currentRateMode = rateMode == 1 ? 2 : 1; + + if (getPaybackBalance(token, currentRateMode) > 0) { + aave.swapBorrowRateMode(token, rateMode); + } + + _eventName = "LogSwapRateMode(address,uint256)"; + _eventParam = abi.encode(token, rateMode); + } + + /** + * @dev Set user e-mode + * @notice Updates the user's e-mode category + * @param categoryId The category Id of the e-mode user want to set + */ + function setUserEMode(uint8 categoryId) + external + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + aave.setUserEMode(categoryId); + + _eventName = "LogSetUserEMode(uint8)"; + _eventParam = abi.encode(categoryId); + } +} + +contract ConnectV2AaveV3Polygon is AaveResolver { + string public constant name = "AaveV3-v1.0"; +} From 0e81ea5441a49e8bfe7b074e578e4625360024a7 Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Sun, 6 Mar 2022 18:51:50 +0530 Subject: [PATCH 09/30] added connector on avalanche --- .../avalanche/connectors/aave/v3/events.sol | 33 ++ .../avalanche/connectors/aave/v3/helpers.sol | 66 ++++ .../connectors/aave/v3/interface.sol | 91 ++++++ .../avalanche/connectors/aave/v3/main.sol | 296 ++++++++++++++++++ 4 files changed, 486 insertions(+) create mode 100644 contracts/avalanche/connectors/aave/v3/events.sol create mode 100644 contracts/avalanche/connectors/aave/v3/helpers.sol create mode 100644 contracts/avalanche/connectors/aave/v3/interface.sol create mode 100644 contracts/avalanche/connectors/aave/v3/main.sol diff --git a/contracts/avalanche/connectors/aave/v3/events.sol b/contracts/avalanche/connectors/aave/v3/events.sol new file mode 100644 index 00000000..9f60f22b --- /dev/null +++ b/contracts/avalanche/connectors/aave/v3/events.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDeposit( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogWithdraw( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogBorrow( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogPayback( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogEnableCollateral(address[] tokens); + event LogSwapRateMode(address indexed token, uint256 rateMode); + event LogSetUserEMode(uint8 categoryId); +} diff --git a/contracts/avalanche/connectors/aave/v3/helpers.sol b/contracts/avalanche/connectors/aave/v3/helpers.sol new file mode 100644 index 00000000..13431d11 --- /dev/null +++ b/contracts/avalanche/connectors/aave/v3/helpers.sol @@ -0,0 +1,66 @@ +pragma solidity ^0.7.0; + +import { DSMath } from "../../../common/math.sol"; +import { Basic } from "../../../common/basic.sol"; +import { AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + /** + * @dev Aave Pool Provider + */ + AavePoolProviderInterface internal constant aaveProvider = + AavePoolProviderInterface(0xA55125A90d75a95EC00130E8E8C197dB5641Eb19); // rinkeby address + + /** + * @dev Aave Pool Data Provider + */ + AaveDataProviderInterface internal constant aaveData = + AaveDataProviderInterface(0x256bBbeDbA70a1240a1EB64210abB1b063267408); // rinkeby address + + /** + * @dev Aave Referral Code + */ + uint16 internal constant referralCode = 3228; + + /** + * @dev Checks if collateral is enabled for an asset + * @param token token address of the asset.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + + function getIsColl(address token) internal view returns (bool isCol) { + (, , , , , , , , isCol) = aaveData.getUserReserveData( + token, + address(this) + ); + } + + /** + * @dev Get total debt balance & fee for an asset + * @param token token address of the debt.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Borrow rate mode (Stable = 1, Variable = 2) + */ + function getPaybackBalance(address token, uint256 rateMode) + internal + view + returns (uint256) + { + (, uint256 stableDebt, uint256 variableDebt, , , , , , ) = aaveData + .getUserReserveData(token, address(this)); + return rateMode == 1 ? stableDebt : variableDebt; + } + + /** + * @dev Get total collateral balance for an asset + * @param token token address of the collateral.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + function getCollateralBalance(address token) + internal + view + returns (uint256 bal) + { + (bal, , , , , , , , ) = aaveData.getUserReserveData( + token, + address(this) + ); + } +} diff --git a/contracts/avalanche/connectors/aave/v3/interface.sol b/contracts/avalanche/connectors/aave/v3/interface.sol new file mode 100644 index 00000000..8ae14716 --- /dev/null +++ b/contracts/avalanche/connectors/aave/v3/interface.sol @@ -0,0 +1,91 @@ +pragma solidity ^0.7.0; + +interface AaveInterface { + function supply( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + function withdraw( + address asset, + uint256 amount, + address to + ) external returns (uint256); + + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) external; + + function repay( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf + ) external returns (uint256); + + function repayWithATokens( + address asset, + uint256 amount, + uint256 interestRateMode + ) external returns (uint256); + + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) + external; + + function swapBorrowRateMode(address asset, uint256 interestRateMode) + external; + + function setUserEMode(uint8 categoryId) external; +} + +interface AavePoolProviderInterface { + function getPool() external view returns (address); +} + +interface AaveDataProviderInterface { + function getReserveTokensAddresses(address _asset) + external + view + returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); + + function getUserReserveData(address _asset, address _user) + external + view + returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); + + function getReserveEModeCategory(address asset) + external + view + returns (uint256); +} + +interface AaveAddressProviderRegistryInterface { + function getAddressesProvidersList() + external + view + returns (address[] memory); +} + +interface ATokenInterface { + function balanceOf(address _user) external view returns (uint256); +} diff --git a/contracts/avalanche/connectors/aave/v3/main.sol b/contracts/avalanche/connectors/aave/v3/main.sol new file mode 100644 index 00000000..14d5596f --- /dev/null +++ b/contracts/avalanche/connectors/aave/v3/main.sol @@ -0,0 +1,296 @@ +pragma solidity ^0.7.0; + +/** + * @title Aave v3. + * @dev Lending & Borrowing. + */ + +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"; + +abstract contract AaveResolver is Events, Helpers { + /** + * @dev Deposit avax/ERC20_Token. + * @notice Deposit a token to Aave v3 for lending / collaterization. + * @param token The address of the token to deposit.(For avax: 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 deposit( + 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 isAVAX = token == avaxAddr; + address _token = isAVAX ? wavaxAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + if (isAVAX) { + _amt = _amt == uint256(-1) ? address(this).balance : _amt; + convertAvaxToWavax(isAVAX, 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 (!getIsColl(_token)) { + aave.setUserUseReserveAsCollateral(_token, true); + } + + setUint(setId, _amt); + + _eventName = "LogDeposit(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } + + /** + * @dev Withdraw avax/ERC20_Token. + * @notice Withdraw deposited token from Aave v2 + * @param token The address of the token to withdraw.(For avax: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens withdrawn. + */ + function withdraw( + 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 isAVAX = token == avaxAddr; + address _token = isAVAX ? wavaxAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + uint256 initialBal = tokenContract.balanceOf(address(this)); + aave.withdraw(_token, _amt, address(this)); + uint256 finalBal = tokenContract.balanceOf(address(this)); + + _amt = sub(finalBal, initialBal); + + convertWavaxToAvax(isAVAX, tokenContract, _amt); + + setUint(setId, _amt); + + _eventName = "LogWithdraw(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } + + /** + * @dev Borrow avax/ERC20_Token. + * @notice Borrow a token using Aave v2 + * @param token The address of the token to borrow.(For avax: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to borrow. + * @param rateMode The type of borrow debt. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens borrowed. + */ + function borrow( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isAVAX = token == avaxAddr; + address _token = isAVAX ? wavaxAddr : token; + + aave.borrow(_token, _amt, rateMode, referralCode, address(this)); + convertWavaxToAvax(isAVAX, TokenInterface(_token), _amt); + + setUint(setId, _amt); + + _eventName = "LogBorrow(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Payback borrowed avax/ERC20_Token. + * @notice Payback debt owed. + * @param token The address of the token to payback.(For avax: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function payback( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isAVAX = token == avaxAddr; + address _token = isAVAX ? wavaxAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isAVAX) convertAvaxToWavax(isAVAX, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repay(_token, _amt, rateMode, address(this)); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Payback borrowed avax/ERC20_Token using aTokens. + * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the equivalent debt tokens. + * @param token The address of the token to payback.(For avax: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function paybackWithATokens( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isAVAX = token == avaxAddr; + address _token = isAVAX ? wavaxAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isAVAX) convertAvaxToWavax(isAVAX, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repayWithATokens(_token, _amt, rateMode); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Enable collateral + * @notice Enable an array of tokens as collateral + * @param tokens Array of tokens to enable collateral + */ + function enableCollateral(address[] calldata tokens) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _length = tokens.length; + require(_length > 0, "0-tokens-not-allowed"); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + for (uint256 i = 0; i < _length; i++) { + address token = tokens[i]; + if (getCollateralBalance(token) > 0 && !getIsColl(token)) { + aave.setUserUseReserveAsCollateral(token, true); + } + } + + _eventName = "LogEnableCollateral(address[])"; + _eventParam = abi.encode(tokens); + } + + /** + * @dev Swap borrow rate mode + * @notice Swaps user borrow rate mode between variable and stable + * @param token The address of the token to swap borrow rate.(For avax: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2) + */ + function swapBorrowRateMode(address token, uint256 rateMode) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + uint256 currentRateMode = rateMode == 1 ? 2 : 1; + + if (getPaybackBalance(token, currentRateMode) > 0) { + aave.swapBorrowRateMode(token, rateMode); + } + + _eventName = "LogSwapRateMode(address,uint256)"; + _eventParam = abi.encode(token, rateMode); + } + + /** + * @dev Set user e-mode + * @notice Updates the user's e-mode category + * @param categoryId The category Id of the e-mode user want to set + */ + function setUserEMode(uint8 categoryId) + external + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + aave.setUserEMode(categoryId); + + _eventName = "LogSetUserEMode(uint8)"; + _eventParam = abi.encode(categoryId); + } +} + +contract ConnectV2AaveV3Polygon is AaveResolver { + string public constant name = "AaveV3-v1.0"; +} From b45be6bebc2cb626f6cede2ce8c9e1bcdc439816 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 8 Mar 2022 16:30:03 +0400 Subject: [PATCH 10/30] Updated polygon addresses --- contracts/polygon/connectors/aave/v3/helpers.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/polygon/connectors/aave/v3/helpers.sol b/contracts/polygon/connectors/aave/v3/helpers.sol index 13431d11..8b2d0c50 100644 --- a/contracts/polygon/connectors/aave/v3/helpers.sol +++ b/contracts/polygon/connectors/aave/v3/helpers.sol @@ -9,13 +9,13 @@ abstract contract Helpers is DSMath, Basic { * @dev Aave Pool Provider */ AavePoolProviderInterface internal constant aaveProvider = - AavePoolProviderInterface(0xA55125A90d75a95EC00130E8E8C197dB5641Eb19); // rinkeby address + AavePoolProviderInterface(0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C); // Polygon address - PoolAddressesProvider /** * @dev Aave Pool Data Provider */ AaveDataProviderInterface internal constant aaveData = - AaveDataProviderInterface(0x256bBbeDbA70a1240a1EB64210abB1b063267408); // rinkeby address + AaveDataProviderInterface(0x44C7324E9d84D6534DD6f292Cc08f1816e45Ff6e); // Polygon address - PoolDataProvider /** * @dev Aave Referral Code From d951777382b40c0e9d97689aa42f1cdb9c310ed9 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 8 Mar 2022 16:31:56 +0400 Subject: [PATCH 11/30] Updated Aave Avalanche address --- contracts/avalanche/connectors/aave/v3/helpers.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/avalanche/connectors/aave/v3/helpers.sol b/contracts/avalanche/connectors/aave/v3/helpers.sol index 13431d11..171d7ac5 100644 --- a/contracts/avalanche/connectors/aave/v3/helpers.sol +++ b/contracts/avalanche/connectors/aave/v3/helpers.sol @@ -9,13 +9,13 @@ abstract contract Helpers is DSMath, Basic { * @dev Aave Pool Provider */ AavePoolProviderInterface internal constant aaveProvider = - AavePoolProviderInterface(0xA55125A90d75a95EC00130E8E8C197dB5641Eb19); // rinkeby address + AavePoolProviderInterface(0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C); // Avalanche address - PoolAddressesProvider /** * @dev Aave Pool Data Provider */ AaveDataProviderInterface internal constant aaveData = - AaveDataProviderInterface(0x256bBbeDbA70a1240a1EB64210abB1b063267408); // rinkeby address + AaveDataProviderInterface(0x44C7324E9d84D6534DD6f292Cc08f1816e45Ff6e); // Avalanche address - PoolDataProvider /** * @dev Aave Referral Code From 9e16f4526d45375742fdc4634b4ec2f9f5def831 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Tue, 8 Mar 2022 20:44:52 +0530 Subject: [PATCH 12/30] fixed contact name --- contracts/avalanche/connectors/aave/v3/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/avalanche/connectors/aave/v3/main.sol b/contracts/avalanche/connectors/aave/v3/main.sol index 14d5596f..6697810a 100644 --- a/contracts/avalanche/connectors/aave/v3/main.sol +++ b/contracts/avalanche/connectors/aave/v3/main.sol @@ -291,6 +291,6 @@ abstract contract AaveResolver is Events, Helpers { } } -contract ConnectV2AaveV3Polygon is AaveResolver { +contract ConnectV2AaveV3Avalanche is AaveResolver { string public constant name = "AaveV3-v1.0"; } From 56c581ac780cdab7bafa9a6fa7f9af5e24d2e138 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Tue, 8 Mar 2022 20:45:09 +0530 Subject: [PATCH 13/30] added aave v3 arbitrum --- .../arbitrum/connectors/aave/v3/events.sol | 33 ++ .../arbitrum/connectors/aave/v3/helpers.sol | 66 ++++ .../arbitrum/connectors/aave/v3/interface.sol | 91 ++++++ .../arbitrum/connectors/aave/v3/main.sol | 296 ++++++++++++++++++ 4 files changed, 486 insertions(+) create mode 100644 contracts/arbitrum/connectors/aave/v3/events.sol create mode 100644 contracts/arbitrum/connectors/aave/v3/helpers.sol create mode 100644 contracts/arbitrum/connectors/aave/v3/interface.sol create mode 100644 contracts/arbitrum/connectors/aave/v3/main.sol diff --git a/contracts/arbitrum/connectors/aave/v3/events.sol b/contracts/arbitrum/connectors/aave/v3/events.sol new file mode 100644 index 00000000..9f60f22b --- /dev/null +++ b/contracts/arbitrum/connectors/aave/v3/events.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDeposit( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogWithdraw( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogBorrow( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogPayback( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogEnableCollateral(address[] tokens); + event LogSwapRateMode(address indexed token, uint256 rateMode); + event LogSetUserEMode(uint8 categoryId); +} diff --git a/contracts/arbitrum/connectors/aave/v3/helpers.sol b/contracts/arbitrum/connectors/aave/v3/helpers.sol new file mode 100644 index 00000000..48dd4cdc --- /dev/null +++ b/contracts/arbitrum/connectors/aave/v3/helpers.sol @@ -0,0 +1,66 @@ +pragma solidity ^0.7.0; + +import { DSMath } from "../../../common/math.sol"; +import { Basic } from "../../../common/basic.sol"; +import { AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + /** + * @dev Aave Pool Provider + */ + AavePoolProviderInterface internal constant aaveProvider = + AavePoolProviderInterface(0x7B291364Ce799edd4CD471E5C023FF965347E1E1); // Arbitrum address - PoolAddressesProvider + + /** + * @dev Aave Pool Data Provider + */ + AaveDataProviderInterface internal constant aaveData = + AaveDataProviderInterface(0x224cD29570ED4Bfb2b55fF3eE27bEd28c58BBa86); //Arbitrum address - PoolDataProvider + + /** + * @dev Aave Referral Code + */ + uint16 internal constant referralCode = 3228; + + /** + * @dev Checks if collateral is enabled for an asset + * @param token token address of the asset.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + + function getIsColl(address token) internal view returns (bool isCol) { + (, , , , , , , , isCol) = aaveData.getUserReserveData( + token, + address(this) + ); + } + + /** + * @dev Get total debt balance & fee for an asset + * @param token token address of the debt.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Borrow rate mode (Stable = 1, Variable = 2) + */ + function getPaybackBalance(address token, uint256 rateMode) + internal + view + returns (uint256) + { + (, uint256 stableDebt, uint256 variableDebt, , , , , , ) = aaveData + .getUserReserveData(token, address(this)); + return rateMode == 1 ? stableDebt : variableDebt; + } + + /** + * @dev Get total collateral balance for an asset + * @param token token address of the collateral.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + function getCollateralBalance(address token) + internal + view + returns (uint256 bal) + { + (bal, , , , , , , , ) = aaveData.getUserReserveData( + token, + address(this) + ); + } +} diff --git a/contracts/arbitrum/connectors/aave/v3/interface.sol b/contracts/arbitrum/connectors/aave/v3/interface.sol new file mode 100644 index 00000000..8ae14716 --- /dev/null +++ b/contracts/arbitrum/connectors/aave/v3/interface.sol @@ -0,0 +1,91 @@ +pragma solidity ^0.7.0; + +interface AaveInterface { + function supply( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + function withdraw( + address asset, + uint256 amount, + address to + ) external returns (uint256); + + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) external; + + function repay( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf + ) external returns (uint256); + + function repayWithATokens( + address asset, + uint256 amount, + uint256 interestRateMode + ) external returns (uint256); + + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) + external; + + function swapBorrowRateMode(address asset, uint256 interestRateMode) + external; + + function setUserEMode(uint8 categoryId) external; +} + +interface AavePoolProviderInterface { + function getPool() external view returns (address); +} + +interface AaveDataProviderInterface { + function getReserveTokensAddresses(address _asset) + external + view + returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); + + function getUserReserveData(address _asset, address _user) + external + view + returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); + + function getReserveEModeCategory(address asset) + external + view + returns (uint256); +} + +interface AaveAddressProviderRegistryInterface { + function getAddressesProvidersList() + external + view + returns (address[] memory); +} + +interface ATokenInterface { + function balanceOf(address _user) external view returns (uint256); +} diff --git a/contracts/arbitrum/connectors/aave/v3/main.sol b/contracts/arbitrum/connectors/aave/v3/main.sol new file mode 100644 index 00000000..1004d0ec --- /dev/null +++ b/contracts/arbitrum/connectors/aave/v3/main.sol @@ -0,0 +1,296 @@ +pragma solidity ^0.7.0; + +/** + * @title Aave v3. + * @dev Lending & Borrowing. + */ + +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"; + +abstract contract AaveResolver is Events, Helpers { + /** + * @dev Deposit ETH/ERC20_Token. + * @notice Deposit a token to Aave v2 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 deposit( + 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 (!getIsColl(_token)) { + aave.setUserUseReserveAsCollateral(_token, true); + } + + 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 v2 + * @param token The address of the token to withdraw.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens withdrawn. + */ + function withdraw( + 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); + + uint256 initialBal = tokenContract.balanceOf(address(this)); + aave.withdraw(_token, _amt, address(this)); + uint256 finalBal = tokenContract.balanceOf(address(this)); + + _amt = sub(finalBal, initialBal); + + convertWethToEth(isEth, tokenContract, _amt); + + setUint(setId, _amt); + + _eventName = "LogWithdraw(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } + + /** + * @dev Borrow ETH/ERC20_Token. + * @notice Borrow a token using Aave v2 + * @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 getId ID to retrieve amt. + * @param setId ID stores the amount of tokens borrowed. + */ + function borrow( + address token, + uint256 amt, + uint256 rateMode, + 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, address(this)); + convertWethToEth(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. + * @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function payback( + address token, + uint256 amt, + uint256 rateMode, + 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); + + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isEth) convertEthToWeth(isEth, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repay(_token, _amt, rateMode, address(this)); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Payback borrowed ETH/ERC20_Token using aTokens. + * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the equivalent debt tokens. + * @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function paybackWithATokens( + address token, + uint256 amt, + uint256 rateMode, + 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); + + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isEth) convertEthToWeth(isEth, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repayWithATokens(_token, _amt, rateMode); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Enable collateral + * @notice Enable an array of tokens as collateral + * @param tokens Array of tokens to enable collateral + */ + function enableCollateral(address[] calldata tokens) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _length = tokens.length; + require(_length > 0, "0-tokens-not-allowed"); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + for (uint256 i = 0; i < _length; i++) { + address token = tokens[i]; + if (getCollateralBalance(token) > 0 && !getIsColl(token)) { + aave.setUserUseReserveAsCollateral(token, true); + } + } + + _eventName = "LogEnableCollateral(address[])"; + _eventParam = abi.encode(tokens); + } + + /** + * @dev Swap borrow rate mode + * @notice Swaps user borrow rate mode between variable and stable + * @param token The address of the token to swap borrow rate.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2) + */ + function swapBorrowRateMode(address token, uint256 rateMode) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + uint256 currentRateMode = rateMode == 1 ? 2 : 1; + + if (getPaybackBalance(token, currentRateMode) > 0) { + aave.swapBorrowRateMode(token, rateMode); + } + + _eventName = "LogSwapRateMode(address,uint256)"; + _eventParam = abi.encode(token, rateMode); + } + + /** + * @dev Set user e-mode + * @notice Updates the user's e-mode category + * @param categoryId The category Id of the e-mode user want to set + */ + function setUserEMode(uint8 categoryId) + external + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + aave.setUserEMode(categoryId); + + _eventName = "LogSetUserEMode(uint8)"; + _eventParam = abi.encode(categoryId); + } +} + +contract ConnectV2AaveV3Arbitrum is AaveResolver { + string public constant name = "AaveV3-v1.0"; +} From 73172cc34cc817a9a9e458a4ffaf8d18e7d6f40f Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Tue, 8 Mar 2022 20:58:07 +0530 Subject: [PATCH 14/30] optimisim: aave v3 --- .../optimism/connectors/aave/v3/events.sol | 33 ++ .../optimism/connectors/aave/v3/helpers.sol | 66 ++++ .../optimism/connectors/aave/v3/interface.sol | 91 ++++++ .../optimism/connectors/aave/v3/main.sol | 296 ++++++++++++++++++ 4 files changed, 486 insertions(+) create mode 100644 contracts/optimism/connectors/aave/v3/events.sol create mode 100644 contracts/optimism/connectors/aave/v3/helpers.sol create mode 100644 contracts/optimism/connectors/aave/v3/interface.sol create mode 100644 contracts/optimism/connectors/aave/v3/main.sol diff --git a/contracts/optimism/connectors/aave/v3/events.sol b/contracts/optimism/connectors/aave/v3/events.sol new file mode 100644 index 00000000..9f60f22b --- /dev/null +++ b/contracts/optimism/connectors/aave/v3/events.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDeposit( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogWithdraw( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogBorrow( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogPayback( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogEnableCollateral(address[] tokens); + event LogSwapRateMode(address indexed token, uint256 rateMode); + event LogSetUserEMode(uint8 categoryId); +} diff --git a/contracts/optimism/connectors/aave/v3/helpers.sol b/contracts/optimism/connectors/aave/v3/helpers.sol new file mode 100644 index 00000000..2ca0f239 --- /dev/null +++ b/contracts/optimism/connectors/aave/v3/helpers.sol @@ -0,0 +1,66 @@ +pragma solidity ^0.7.0; + +import { DSMath } from "../../../common/math.sol"; +import { Basic } from "../../../common/basic.sol"; +import { AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + /** + * @dev Aave Pool Provider + */ + AavePoolProviderInterface internal constant aaveProvider = + AavePoolProviderInterface(0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C); // Arbitrum address - PoolAddressesProvider + + /** + * @dev Aave Pool Data Provider + */ + AaveDataProviderInterface internal constant aaveData = + AaveDataProviderInterface(0x44C7324E9d84D6534DD6f292Cc08f1816e45Ff6e); //Arbitrum address - PoolDataProvider + + /** + * @dev Aave Referral Code + */ + uint16 internal constant referralCode = 3228; + + /** + * @dev Checks if collateral is enabled for an asset + * @param token token address of the asset.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + + function getIsColl(address token) internal view returns (bool isCol) { + (, , , , , , , , isCol) = aaveData.getUserReserveData( + token, + address(this) + ); + } + + /** + * @dev Get total debt balance & fee for an asset + * @param token token address of the debt.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Borrow rate mode (Stable = 1, Variable = 2) + */ + function getPaybackBalance(address token, uint256 rateMode) + internal + view + returns (uint256) + { + (, uint256 stableDebt, uint256 variableDebt, , , , , , ) = aaveData + .getUserReserveData(token, address(this)); + return rateMode == 1 ? stableDebt : variableDebt; + } + + /** + * @dev Get total collateral balance for an asset + * @param token token address of the collateral.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + function getCollateralBalance(address token) + internal + view + returns (uint256 bal) + { + (bal, , , , , , , , ) = aaveData.getUserReserveData( + token, + address(this) + ); + } +} diff --git a/contracts/optimism/connectors/aave/v3/interface.sol b/contracts/optimism/connectors/aave/v3/interface.sol new file mode 100644 index 00000000..8ae14716 --- /dev/null +++ b/contracts/optimism/connectors/aave/v3/interface.sol @@ -0,0 +1,91 @@ +pragma solidity ^0.7.0; + +interface AaveInterface { + function supply( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + function withdraw( + address asset, + uint256 amount, + address to + ) external returns (uint256); + + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) external; + + function repay( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf + ) external returns (uint256); + + function repayWithATokens( + address asset, + uint256 amount, + uint256 interestRateMode + ) external returns (uint256); + + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) + external; + + function swapBorrowRateMode(address asset, uint256 interestRateMode) + external; + + function setUserEMode(uint8 categoryId) external; +} + +interface AavePoolProviderInterface { + function getPool() external view returns (address); +} + +interface AaveDataProviderInterface { + function getReserveTokensAddresses(address _asset) + external + view + returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); + + function getUserReserveData(address _asset, address _user) + external + view + returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); + + function getReserveEModeCategory(address asset) + external + view + returns (uint256); +} + +interface AaveAddressProviderRegistryInterface { + function getAddressesProvidersList() + external + view + returns (address[] memory); +} + +interface ATokenInterface { + function balanceOf(address _user) external view returns (uint256); +} diff --git a/contracts/optimism/connectors/aave/v3/main.sol b/contracts/optimism/connectors/aave/v3/main.sol new file mode 100644 index 00000000..d778832b --- /dev/null +++ b/contracts/optimism/connectors/aave/v3/main.sol @@ -0,0 +1,296 @@ +pragma solidity ^0.7.0; + +/** + * @title Aave v3. + * @dev Lending & Borrowing. + */ + +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"; + +abstract contract AaveResolver is Events, Helpers { + /** + * @dev Deposit ETH/ERC20_Token. + * @notice Deposit a token to Aave v2 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 deposit( + 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 (!getIsColl(_token)) { + aave.setUserUseReserveAsCollateral(_token, true); + } + + 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 v2 + * @param token The address of the token to withdraw.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens withdrawn. + */ + function withdraw( + 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); + + uint256 initialBal = tokenContract.balanceOf(address(this)); + aave.withdraw(_token, _amt, address(this)); + uint256 finalBal = tokenContract.balanceOf(address(this)); + + _amt = sub(finalBal, initialBal); + + convertWethToEth(isEth, tokenContract, _amt); + + setUint(setId, _amt); + + _eventName = "LogWithdraw(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } + + /** + * @dev Borrow ETH/ERC20_Token. + * @notice Borrow a token using Aave v2 + * @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 getId ID to retrieve amt. + * @param setId ID stores the amount of tokens borrowed. + */ + function borrow( + address token, + uint256 amt, + uint256 rateMode, + 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, address(this)); + convertWethToEth(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. + * @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function payback( + address token, + uint256 amt, + uint256 rateMode, + 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); + + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isEth) convertEthToWeth(isEth, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repay(_token, _amt, rateMode, address(this)); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Payback borrowed ETH/ERC20_Token using aTokens. + * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the equivalent debt tokens. + * @param token The address of the token to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function paybackWithATokens( + address token, + uint256 amt, + uint256 rateMode, + 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); + + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isEth) convertEthToWeth(isEth, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repayWithATokens(_token, _amt, rateMode); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Enable collateral + * @notice Enable an array of tokens as collateral + * @param tokens Array of tokens to enable collateral + */ + function enableCollateral(address[] calldata tokens) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _length = tokens.length; + require(_length > 0, "0-tokens-not-allowed"); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + for (uint256 i = 0; i < _length; i++) { + address token = tokens[i]; + if (getCollateralBalance(token) > 0 && !getIsColl(token)) { + aave.setUserUseReserveAsCollateral(token, true); + } + } + + _eventName = "LogEnableCollateral(address[])"; + _eventParam = abi.encode(tokens); + } + + /** + * @dev Swap borrow rate mode + * @notice Swaps user borrow rate mode between variable and stable + * @param token The address of the token to swap borrow rate.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2) + */ + function swapBorrowRateMode(address token, uint256 rateMode) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + uint256 currentRateMode = rateMode == 1 ? 2 : 1; + + if (getPaybackBalance(token, currentRateMode) > 0) { + aave.swapBorrowRateMode(token, rateMode); + } + + _eventName = "LogSwapRateMode(address,uint256)"; + _eventParam = abi.encode(token, rateMode); + } + + /** + * @dev Set user e-mode + * @notice Updates the user's e-mode category + * @param categoryId The category Id of the e-mode user want to set + */ + function setUserEMode(uint8 categoryId) + external + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + aave.setUserEMode(categoryId); + + _eventName = "LogSetUserEMode(uint8)"; + _eventParam = abi.encode(categoryId); + } +} + +contract ConnectV2AaveV3Optimism is AaveResolver { + string public constant name = "AaveV3-v1.0"; +} From 91c8a72ef92c04a84c57d7877af27a7e8481148c Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Tue, 8 Mar 2022 19:30:23 +0400 Subject: [PATCH 15/30] Update contracts/optimism/connectors/aave/v3/helpers.sol --- contracts/optimism/connectors/aave/v3/helpers.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/optimism/connectors/aave/v3/helpers.sol b/contracts/optimism/connectors/aave/v3/helpers.sol index 2ca0f239..0e8f7c14 100644 --- a/contracts/optimism/connectors/aave/v3/helpers.sol +++ b/contracts/optimism/connectors/aave/v3/helpers.sol @@ -9,7 +9,7 @@ abstract contract Helpers is DSMath, Basic { * @dev Aave Pool Provider */ AavePoolProviderInterface internal constant aaveProvider = - AavePoolProviderInterface(0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C); // Arbitrum address - PoolAddressesProvider + AavePoolProviderInterface(0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C); // Optimism address - PoolAddressesProvider /** * @dev Aave Pool Data Provider From 3fa3e36ba906f9fc65628110e3745975d2f4f5be Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Tue, 8 Mar 2022 19:31:10 +0400 Subject: [PATCH 16/30] Update contracts/optimism/connectors/aave/v3/helpers.sol --- contracts/optimism/connectors/aave/v3/helpers.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/optimism/connectors/aave/v3/helpers.sol b/contracts/optimism/connectors/aave/v3/helpers.sol index 0e8f7c14..fc896b79 100644 --- a/contracts/optimism/connectors/aave/v3/helpers.sol +++ b/contracts/optimism/connectors/aave/v3/helpers.sol @@ -15,7 +15,7 @@ abstract contract Helpers is DSMath, Basic { * @dev Aave Pool Data Provider */ AaveDataProviderInterface internal constant aaveData = - AaveDataProviderInterface(0x44C7324E9d84D6534DD6f292Cc08f1816e45Ff6e); //Arbitrum address - PoolDataProvider + AaveDataProviderInterface(0x44C7324E9d84D6534DD6f292Cc08f1816e45Ff6e); // Optimism address - PoolDataProvider /** * @dev Aave Referral Code From 22728d776a14c4ba35986460c3e98254554eb16a Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Wed, 9 Mar 2022 00:12:39 +0400 Subject: [PATCH 17/30] fixed DSA v2 to v3 import logic --- .../aave/v2-to-v3-import/events.sol | 1 + .../connectors/aave/v2-to-v3-import/main.sol | 46 +++++++++++-------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol index 3aa98805..0d1ed7ae 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol @@ -3,6 +3,7 @@ pragma solidity ^0.7.0; contract Events { event LogAaveV2ImportToV3( address indexed user, + bool doImport, bool convertStable, address[] supplyTokens, address[] borrowTokens, diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol index d4574198..34001a15 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol @@ -7,14 +7,21 @@ import "./helpers.sol"; import "./events.sol"; contract _AaveV2ToV3MigrationResolver is _AaveHelper { - function _importAave(address userAccount, ImportInputData memory inputData) + function _importAave( + address userAccount, + ImportInputData memory inputData, + bool doImport + ) internal returns (string memory _eventName, bytes memory _eventParam) - { - require( - AccountInterface(address(this)).isAuth(userAccount), - "user-account-not-auth" - ); + { + if (doImport) { + // check only when we are importing from user's address + require( + AccountInterface(address(this)).isAuth(userAccount), + "user-account-not-auth" + ); + } require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); @@ -44,15 +51,17 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { userAccount ); - // transfer atokens to this address; - _TransferAtokens( - data._supplyTokens.length, - aaveV2, - data.aTokens, - data.supplyAmts, - data._supplyTokens, - userAccount - ); + if (doImport) { + // transfer atokens to user's DSA address; + _TransferAtokens( + data._supplyTokens.length, + aaveV2, + data.aTokens, + data.supplyAmts, + data._supplyTokens, + userAccount + ); + } // withdraw v2 supplied tokens _WithdrawTokensFromV2( @@ -92,9 +101,10 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { ); } - _eventName = "LogAaveV2ImportToV3(address,bool,address[],address[],uint256,uint256[],uint256[],uint256[])"; + _eventName = "LogAaveV2ImportToV3(address,bool,bool,address[],address[],uint256[],uint256[],uint256[],uint256[])"; _eventParam = abi.encode( userAccount, + doImport, inputData.convertStable, inputData.supplyTokens, inputData.borrowTokens, @@ -113,7 +123,7 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { payable returns (string memory _eventName, bytes memory _eventParam) { - (_eventName, _eventParam) = _importAave(userAccount, inputData); + (_eventName, _eventParam) = _importAave(userAccount, inputData, false); } function migrateAaveV2ToV3(ImportInputData memory inputData) @@ -121,7 +131,7 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { payable returns (string memory _eventName, bytes memory _eventParam) { - (_eventName, _eventParam) = _importAave(msg.sender, inputData); + (_eventName, _eventParam) = _importAave(msg.sender, inputData, true); } } From d59cd4fc7c79d8543ec4467b7e5cebcb16ec9676 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Wed, 9 Mar 2022 00:24:59 +0400 Subject: [PATCH 18/30] Polygon: Code refactoring --- .../aave/v2-to-v3-import/events.sol | 2 +- .../aave/v2-to-v3-import/helpers.sol | 38 +++++++++---------- .../connectors/aave/v2-to-v3-import/main.sol | 24 ++++++------ 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol index 0d1ed7ae..84bb146f 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/events.sol @@ -1,7 +1,7 @@ pragma solidity ^0.7.0; contract Events { - event LogAaveV2ImportToV3( + event LogAaveImportV2ToV3( address indexed user, bool doImport, bool convertStable, diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol index c05dc259..9b397e8c 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol @@ -39,7 +39,7 @@ abstract contract Helper is DSMath, Basic { view returns (bool isCol) { - (, , , , , , , , isCol) = aaveData.getUserReserveData(token, user); + (, , , , , , , , isCol) = aaveV2Data.getUserReserveData(token, user); } struct ImportData { @@ -65,7 +65,7 @@ abstract contract Helper is DSMath, Basic { } contract _AaveHelper is Helper { - function getBorrowAmount(address _token, address userAccount) + function getBorrowAmountV2(address _token, address userAccount) internal view returns (uint256 stableBorrow, uint256 variableBorrow) @@ -74,7 +74,7 @@ contract _AaveHelper is Helper { , address stableDebtTokenAddress, address variableDebtTokenAddress - ) = aaveData.getReserveTokensAddresses(_token); + ) = aaveV2Data.getReserveTokensAddresses(_token); stableBorrow = ATokenV2Interface(stableDebtTokenAddress).balanceOf( userAccount @@ -84,7 +84,7 @@ contract _AaveHelper is Helper { ); } - function getBorrowAmounts( + function getBorrowAmountsV2( address userAccount, AaveV2Interface aaveV2, ImportInputData memory inputData, @@ -119,7 +119,7 @@ contract _AaveHelper is Helper { ( data.stableBorrowAmts[i], data.variableBorrowAmts[i] - ) = getBorrowAmount(_token, userAccount); + ) = getBorrowAmountV2(_token, userAccount); if (data.variableBorrowAmts[i] != 0) { data.variableBorrowAmtsWithFee[i] = add( @@ -152,7 +152,7 @@ contract _AaveHelper is Helper { return data; } - function getSupplyAmounts( + function getSupplyAmountsV2( address userAccount, ImportInputData memory inputData, ImportData memory data @@ -175,7 +175,7 @@ contract _AaveHelper is Helper { address _token = inputData.supplyTokens[i] == maticAddr ? wmaticAddr : inputData.supplyTokens[i]; - (address _aToken, , ) = aaveData.getReserveTokensAddresses(_token); + (address _aToken, , ) = aaveV2Data.getReserveTokensAddresses(_token); data._supplyTokens[i] = _token; data.aTokens[i] = ATokenV2Interface(_aToken); data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount); @@ -184,7 +184,7 @@ contract _AaveHelper is Helper { return data; } - function _paybackBehalfOne( + function _paybackBehalfOneV2( AaveV2Interface aaveV2, address token, uint256 amt, @@ -194,7 +194,7 @@ contract _AaveHelper is Helper { aaveV2.repay(token, amt, rateMode, user); } - function _PaybackStable( + function _PaybackStableV2( uint256 _length, AaveV2Interface aaveV2, address[] memory tokens, @@ -203,12 +203,12 @@ contract _AaveHelper is Helper { ) internal { for (uint256 i = 0; i < _length; i++) { if (amts[i] > 0) { - _paybackBehalfOne(aaveV2, tokens[i], amts[i], 1, user); + _paybackBehalfOneV2(aaveV2, tokens[i], amts[i], 1, user); } } } - function _PaybackVariable( + function _PaybackVariableV2( uint256 _length, AaveV2Interface aaveV2, address[] memory tokens, @@ -217,12 +217,12 @@ contract _AaveHelper is Helper { ) internal { for (uint256 i = 0; i < _length; i++) { if (amts[i] > 0) { - _paybackBehalfOne(aaveV2, tokens[i], amts[i], 2, user); + _paybackBehalfOneV2(aaveV2, tokens[i], amts[i], 2, user); } } } - function _TransferAtokens( + function _TransferAtokensV2( uint256 _length, AaveV2Interface aaveV2, ATokenV2Interface[] memory atokenContracts, @@ -264,7 +264,7 @@ contract _AaveHelper is Helper { } } - function _depositTokensInV3( + function _depositTokensV3( uint256 _length, AaveV3Interface aaveV3, uint256[] memory amts, @@ -289,7 +289,7 @@ contract _AaveHelper is Helper { } } - function _BorrowVariable( + function _BorrowVariableV3( uint256 _length, AaveV3Interface aaveV3, address[] memory tokens, @@ -297,12 +297,12 @@ contract _AaveHelper is Helper { ) internal { for (uint256 i = 0; i < _length; i++) { if (amts[i] > 0) { - _borrowOne(aaveV3, tokens[i], amts[i], 2); + _borrowOneV3(aaveV3, tokens[i], amts[i], 2); } } } - function _BorrowStable( + function _BorrowStableV3( uint256 _length, AaveV3Interface aaveV3, address[] memory tokens, @@ -310,12 +310,12 @@ contract _AaveHelper is Helper { ) internal { for (uint256 i = 0; i < _length; i++) { if (amts[i] > 0) { - _borrowOne(aaveV3, tokens[i], amts[i], 1); + _borrowOneV3(aaveV3, tokens[i], amts[i], 1); } } } - function _borrowOne( + function _borrowOneV3( AaveV3Interface aaveV3, address token, uint256 amt, diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol index 34001a15..9cb1683c 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol @@ -32,18 +32,18 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { ); AaveV3Interface aaveV3 = AaveV3Interface(aaveV3Provider.getPool()); - data = getBorrowAmounts(userAccount, aaveV2, inputData, data); - data = getSupplyAmounts(userAccount, inputData, data); + data = getBorrowAmountsV2(userAccount, aaveV2, inputData, data); + data = getSupplyAmountsV2(userAccount, inputData, data); // payback borrowed amount; - _PaybackStable( + _PaybackStableV2( data._borrowTokens.length, aaveV2, data._borrowTokens, data.stableBorrowAmts, userAccount ); - _PaybackVariable( + _PaybackVariableV2( data._borrowTokens.length, aaveV2, data._borrowTokens, @@ -53,7 +53,7 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { if (doImport) { // transfer atokens to user's DSA address; - _TransferAtokens( + _TransferAtokensV2( data._supplyTokens.length, aaveV2, data.aTokens, @@ -71,7 +71,7 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { data._supplyTokens ); // deposit tokens in v3 - _depositTokensInV3( + _depositTokensV3( data._supplyTokens.length, aaveV3, data.supplyAmts, @@ -80,20 +80,20 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { // borrow assets in aave v3 after migrating position if (data.convertStable) { - _BorrowVariable( + _BorrowVariableV3( data._borrowTokens.length, aaveV3, data._borrowTokens, data.totalBorrowAmtsWithFee ); } else { - _BorrowStable( + _BorrowStableV3( data._borrowTokens.length, aaveV3, data._borrowTokens, data.stableBorrowAmtsWithFee ); - _BorrowVariable( + _BorrowVariableV3( data._borrowTokens.length, aaveV3, data._borrowTokens, @@ -101,7 +101,7 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { ); } - _eventName = "LogAaveV2ImportToV3(address,bool,bool,address[],address[],uint256[],uint256[],uint256[],uint256[])"; + _eventName = "LogAaveImportV2ToV3(address,bool,bool,address[],address[],uint256[],uint256[],uint256[],uint256[])"; _eventParam = abi.encode( userAccount, doImport, @@ -135,6 +135,6 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { } } -contract AaveV2ToV3MigrationResolverPolygon is _AaveV2ToV3MigrationResolver { - string public constant name = "Aave-v2-to-v3-import"; +contract ConnectV2AaveV2ToV3MigrationPolygon is _AaveV2ToV3MigrationResolver { + string public constant name = "Aave-Import-v2-to-v3"; } From 31a497e21b03d76f3a028fdc0fcf8d49e7357710 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Wed, 9 Mar 2022 00:25:21 +0400 Subject: [PATCH 19/30] Updated polygon addresses --- .../polygon/connectors/aave/v2-to-v3-import/helpers.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol index 9b397e8c..caf76763 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol @@ -17,7 +17,7 @@ abstract contract Helper is DSMath, Basic { */ AaveV2LendingPoolProviderInterface internal constant aaveV2Provider = AaveV2LendingPoolProviderInterface( - 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 // v2 address TODO: need to update this + 0xd05e3E715d945B59290df0ae8eF85c1BdB684744 // v2 address ); /** @@ -25,14 +25,14 @@ abstract contract Helper is DSMath, Basic { */ AaveV3PoolProviderInterface internal constant aaveV3Provider = AaveV3PoolProviderInterface( - 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 // v2 address TODO: need to update this + 0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C // Polygon address - PoolAddressesProvider ); /** * @dev Aave Protocol Data Provider */ - AaveV2DataProviderInterface internal constant aaveData = - AaveV2DataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); // TODO: need to update this + AaveV2DataProviderInterface internal constant aaveV2Data = + AaveV2DataProviderInterface(0x7551b5D2763519d4e37e8B81929D336De671d46d); // v2 address function getIsColl(address token, address user) internal From 270a3f79b9ff1a2b881add85486bd40476e8969c Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Wed, 9 Mar 2022 17:33:30 +0530 Subject: [PATCH 20/30] update v2->v3 import avax --- .../aave/v2-to-v3-import/events.sol | 3 +- .../aave/v2-to-v3-import/helpers.sol | 48 ++++++------- .../connectors/aave/v2-to-v3-import/main.sol | 69 ++++++++++--------- .../connectors/aave/v2-to-v3-import/main.sol | 5 +- 4 files changed, 65 insertions(+), 60 deletions(-) diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/events.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/events.sol index 3aa98805..84bb146f 100644 --- a/contracts/avalanche/connectors/aave/v2-to-v3-import/events.sol +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/events.sol @@ -1,8 +1,9 @@ pragma solidity ^0.7.0; contract Events { - event LogAaveV2ImportToV3( + event LogAaveImportV2ToV3( address indexed user, + bool doImport, bool convertStable, address[] supplyTokens, address[] borrowTokens, diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol index d4dab63a..36f067d9 100644 --- a/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol @@ -17,7 +17,7 @@ abstract contract Helper is DSMath, Basic { */ AaveV2LendingPoolProviderInterface internal constant aaveV2Provider = AaveV2LendingPoolProviderInterface( - 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 // v2 address TODO: need to update this + 0xb6A86025F0FE1862B372cb0ca18CE3EDe02A318f // v2 address: LendingPoolAddressProvider avax ); /** @@ -25,21 +25,21 @@ abstract contract Helper is DSMath, Basic { */ AaveV3PoolProviderInterface internal constant aaveV3Provider = AaveV3PoolProviderInterface( - 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 // v2 address TODO: need to update this + 0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C // v3 - PoolAddressesProvider Avalanche ); /** * @dev Aave Protocol Data Provider */ - AaveV2DataProviderInterface internal constant aaveData = - AaveV2DataProviderInterface(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); // TODO: need to update this + AaveV2DataProviderInterface internal constant aaveV2Data = + AaveV2DataProviderInterface(0x65285E9dfab318f57051ab2b139ccCf232945451); // aave v2 - avax function getIsColl(address token, address user) internal view returns (bool isCol) { - (, , , , , , , , isCol) = aaveData.getUserReserveData(token, user); + (, , , , , , , , isCol) = aaveV2Data.getUserReserveData(token, user); } struct ImportData { @@ -65,7 +65,7 @@ abstract contract Helper is DSMath, Basic { } contract _AaveHelper is Helper { - function getBorrowAmount(address _token, address userAccount) + function getBorrowAmountV2(address _token, address userAccount) internal view returns (uint256 stableBorrow, uint256 variableBorrow) @@ -74,7 +74,7 @@ contract _AaveHelper is Helper { , address stableDebtTokenAddress, address variableDebtTokenAddress - ) = aaveData.getReserveTokensAddresses(_token); + ) = aaveV2Data.getReserveTokensAddresses(_token); stableBorrow = ATokenV2Interface(stableDebtTokenAddress).balanceOf( userAccount @@ -84,7 +84,7 @@ contract _AaveHelper is Helper { ); } - function getBorrowAmounts( + function getBorrowAmountsV2( address userAccount, AaveV2Interface aaveV2, ImportInputData memory inputData, @@ -119,7 +119,7 @@ contract _AaveHelper is Helper { ( data.stableBorrowAmts[i], data.variableBorrowAmts[i] - ) = getBorrowAmount(_token, userAccount); + ) = getBorrowAmountV2(_token, userAccount); if (data.variableBorrowAmts[i] != 0) { data.variableBorrowAmtsWithFee[i] = add( @@ -152,7 +152,7 @@ contract _AaveHelper is Helper { return data; } - function getSupplyAmounts( + function getSupplyAmountsV2( address userAccount, ImportInputData memory inputData, ImportData memory data @@ -175,7 +175,9 @@ contract _AaveHelper is Helper { address _token = inputData.supplyTokens[i] == avaxAddr ? wavaxAddr : inputData.supplyTokens[i]; - (address _aToken, , ) = aaveData.getReserveTokensAddresses(_token); + (address _aToken, , ) = aaveV2Data.getReserveTokensAddresses( + _token + ); data._supplyTokens[i] = _token; data.aTokens[i] = ATokenV2Interface(_aToken); data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount); @@ -184,7 +186,7 @@ contract _AaveHelper is Helper { return data; } - function _paybackBehalfOne( + function _paybackBehalfOneV2( AaveV2Interface aaveV2, address token, uint256 amt, @@ -194,7 +196,7 @@ contract _AaveHelper is Helper { aaveV2.repay(token, amt, rateMode, user); } - function _PaybackStable( + function _PaybackStableV2( uint256 _length, AaveV2Interface aaveV2, address[] memory tokens, @@ -203,12 +205,12 @@ contract _AaveHelper is Helper { ) internal { for (uint256 i = 0; i < _length; i++) { if (amts[i] > 0) { - _paybackBehalfOne(aaveV2, tokens[i], amts[i], 1, user); + _paybackBehalfOneV2(aaveV2, tokens[i], amts[i], 1, user); } } } - function _PaybackVariable( + function _PaybackVariableV2( uint256 _length, AaveV2Interface aaveV2, address[] memory tokens, @@ -217,12 +219,12 @@ contract _AaveHelper is Helper { ) internal { for (uint256 i = 0; i < _length; i++) { if (amts[i] > 0) { - _paybackBehalfOne(aaveV2, tokens[i], amts[i], 2, user); + _paybackBehalfOneV2(aaveV2, tokens[i], amts[i], 2, user); } } } - function _TransferAtokens( + function _TransferAtokensV2( uint256 _length, AaveV2Interface aaveV2, ATokenV2Interface[] memory atokenContracts, @@ -264,7 +266,7 @@ contract _AaveHelper is Helper { } } - function _depositTokensInV3( + function _depositTokensV3( uint256 _length, AaveV3Interface aaveV3, uint256[] memory amts, @@ -289,7 +291,7 @@ contract _AaveHelper is Helper { } } - function _BorrowVariable( + function _BorrowVariableV3( uint256 _length, AaveV3Interface aaveV3, address[] memory tokens, @@ -297,12 +299,12 @@ contract _AaveHelper is Helper { ) internal { for (uint256 i = 0; i < _length; i++) { if (amts[i] > 0) { - _borrowOne(aaveV3, tokens[i], amts[i], 2); + _borrowOneV3(aaveV3, tokens[i], amts[i], 2); } } } - function _BorrowStable( + function _BorrowStableV3( uint256 _length, AaveV3Interface aaveV3, address[] memory tokens, @@ -310,12 +312,12 @@ contract _AaveHelper is Helper { ) internal { for (uint256 i = 0; i < _length; i++) { if (amts[i] > 0) { - _borrowOne(aaveV3, tokens[i], amts[i], 1); + _borrowOneV3(aaveV3, tokens[i], amts[i], 1); } } } - function _borrowOne( + function _borrowOneV3( AaveV3Interface aaveV3, address token, uint256 amt, diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol index a8b74e8f..f695c23f 100644 --- a/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol @@ -7,15 +7,18 @@ import "./helpers.sol"; import "./events.sol"; contract _AaveV2ToV3MigrationResolver is _AaveHelper { - function _importAave(address userAccount, ImportInputData memory inputData) - internal - returns (string memory _eventName, bytes memory _eventParam) - { - require( - AccountInterface(address(this)).isAuth(userAccount), - "user-account-not-auth" - ); - + function _importAave( + address userAccount, + ImportInputData memory inputData, + bool doImport + ) internal returns (string memory _eventName, bytes memory _eventParam) { + if (doImport) { + // check only when we are importing from user's address + require( + AccountInterface(address(this)).isAuth(userAccount), + "user-account-not-auth" + ); + } require(inputData.supplyTokens.length > 0, "0-length-not-allowed"); ImportData memory data; @@ -25,18 +28,18 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { ); AaveV3Interface aaveV3 = AaveV3Interface(aaveV3Provider.getPool()); - data = getBorrowAmounts(userAccount, aaveV2, inputData, data); - data = getSupplyAmounts(userAccount, inputData, data); + data = getBorrowAmountsV2(userAccount, aaveV2, inputData, data); + data = getSupplyAmountsV2(userAccount, inputData, data); // payback borrowed amount; - _PaybackStable( + _PaybackStableV2( data._borrowTokens.length, aaveV2, data._borrowTokens, data.stableBorrowAmts, userAccount ); - _PaybackVariable( + _PaybackVariableV2( data._borrowTokens.length, aaveV2, data._borrowTokens, @@ -44,16 +47,17 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { userAccount ); - // transfer atokens to this address; - _TransferAtokens( - data._supplyTokens.length, - aaveV2, - data.aTokens, - data.supplyAmts, - data._supplyTokens, - userAccount - ); - + if (doImport) { + // transfer atokens to this address; + _TransferAtokensV2( + data._supplyTokens.length, + aaveV2, + data.aTokens, + data.supplyAmts, + data._supplyTokens, + userAccount + ); + } // withdraw v2 supplied tokens _WithdrawTokensFromV2( data._supplyTokens.length, @@ -62,7 +66,7 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { data._supplyTokens ); // deposit tokens in v3 - _depositTokensInV3( + _depositTokensV3( data._supplyTokens.length, aaveV3, data.supplyAmts, @@ -71,20 +75,20 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { // borrow assets in aave v3 after migrating position if (data.convertStable) { - _BorrowVariable( + _BorrowVariableV3( data._borrowTokens.length, aaveV3, data._borrowTokens, data.totalBorrowAmtsWithFee ); } else { - _BorrowStable( + _BorrowStableV3( data._borrowTokens.length, aaveV3, data._borrowTokens, data.stableBorrowAmtsWithFee ); - _BorrowVariable( + _BorrowVariableV3( data._borrowTokens.length, aaveV3, data._borrowTokens, @@ -92,9 +96,10 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { ); } - _eventName = "LogAaveV2ImportToV3(address,bool,address[],address[],uint256,uint256[],uint256[],uint256[])"; + _eventName = "LogAaveImportV2ToV3(address,bool,bool,address[],address[],uint256[],uint256[],uint256[],uint256[])"; _eventParam = abi.encode( userAccount, + doImport, inputData.convertStable, inputData.supplyTokens, inputData.borrowTokens, @@ -113,7 +118,7 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { payable returns (string memory _eventName, bytes memory _eventParam) { - (_eventName, _eventParam) = _importAave(userAccount, inputData); + (_eventName, _eventParam) = _importAave(userAccount, inputData, false); } function migrateAaveV2ToV3(ImportInputData memory inputData) @@ -121,10 +126,10 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { payable returns (string memory _eventName, bytes memory _eventParam) { - (_eventName, _eventParam) = _importAave(msg.sender, inputData); + (_eventName, _eventParam) = _importAave(msg.sender, inputData, false); } } -contract AaveV2ToV3MigrationResolverAvalanche is _AaveV2ToV3MigrationResolver { - string public constant name = "Aave-v2-to-v3-import"; +contract ConnectV2AaveV2ToV3MigrationPolygon is _AaveV2ToV3MigrationResolver { + string public constant name = "Aave-Import-v2-to-v3"; } diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol index 9cb1683c..2e5dad19 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol @@ -11,10 +11,7 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { address userAccount, ImportInputData memory inputData, bool doImport - ) - internal - returns (string memory _eventName, bytes memory _eventParam) - { + ) internal returns (string memory _eventName, bytes memory _eventParam) { if (doImport) { // check only when we are importing from user's address require( From 74b0eccec06c2b74076aba7739aabf068b430b84 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Wed, 9 Mar 2022 17:33:47 +0530 Subject: [PATCH 21/30] minor script fixes --- scripts/deployment/deployConnectorsFromCmd.ts | 32 +++++++------------ scripts/tests/addLiquidity.ts | 14 +++----- 2 files changed, 16 insertions(+), 30 deletions(-) diff --git a/scripts/deployment/deployConnectorsFromCmd.ts b/scripts/deployment/deployConnectorsFromCmd.ts index 60fb880a..9ed56c14 100644 --- a/scripts/deployment/deployConnectorsFromCmd.ts +++ b/scripts/deployment/deployConnectorsFromCmd.ts @@ -24,8 +24,8 @@ async function deployRunner() { name: "chain", message: "What chain do you want to deploy on?", type: "list", - choices: ["mainnet", "polygon", "avalanche", "arbitrum"], - }, + choices: ["mainnet", "polygon", "avalanche", "arbitrum", "optimism"] + } ]); // let connector = await connectorSelect(chain); @@ -48,8 +48,8 @@ async function deployRunner() { { name: "connector", message: "Enter the connector contract name? (ex: ConnectV2Paraswap)", - type: "input", - }, + type: "input" + } ]); let { choice } = await inquirer.prompt([ @@ -57,39 +57,29 @@ async function deployRunner() { name: "choice", message: "Do you wanna try deploy on hardhat first?", type: "list", - choices: ["yes", "no"], - }, + choices: ["yes", "no"] + } ]); runchain = choice === "yes" ? "hardhat" : chain; - console.log( - `Deploying ${connector} on ${runchain}, press (ctrl + c) to stop` - ); + console.log(`Deploying ${connector} on ${runchain}, press (ctrl + c) to stop`); start = Date.now(); await execScript({ cmd: "npx", - args: [ - "hardhat", - "run", - "scripts/deployment/deploy.ts", - "--network", - `${runchain}`, - ], + args: ["hardhat", "run", "scripts/deployment/deploy.ts", "--network", `${runchain}`], env: { connectorName: connector, - networkType: chain, - }, + networkType: chain + } }); end = Date.now(); } deployRunner() .then(() => { - console.log( - `Done successfully, total time taken: ${(end - start) / 1000} sec` - ); + console.log(`Done successfully, total time taken: ${(end - start) / 1000} sec`); process.exit(0); }) .catch((err) => { diff --git a/scripts/tests/addLiquidity.ts b/scripts/tests/addLiquidity.ts index a18d172f..a1250bcc 100644 --- a/scripts/tests/addLiquidity.ts +++ b/scripts/tests/addLiquidity.ts @@ -1,4 +1,4 @@ -import { ethers } from "hardhat"; +import { ethers, network } from "hardhat"; import { impersonateAccounts } from "./impersonate"; import { tokenMapping as mainnetMapping } from "./mainnet/tokens"; @@ -12,7 +12,7 @@ const mineTx = async (tx: any) => { const tokenMapping: Record> = { mainnet: mainnetMapping, polygon: polygonMapping, - avalanche: avalancheMapping, + avalanche: avalancheMapping }; export async function addLiquidity(tokenName: string, address: any, amt: any) { @@ -20,20 +20,16 @@ export async function addLiquidity(tokenName: string, address: any, amt: any) { tokenName = tokenName.toLowerCase(); const chain = String(process.env.networkType); if (!tokenMapping[chain][tokenName]) { - throw new Error( - `Add liquidity doesn't support the following token: ${tokenName}` - ); + throw new Error(`Add liquidity doesn't support the following token: ${tokenName}`); } const token = tokenMapping[chain][tokenName]; - const [impersonatedSigner] = await impersonateAccounts([ - token.impersonateSigner, - ]); + const [impersonatedSigner] = await impersonateAccounts([token.impersonateSigner]); // send 2 eth to cover any tx costs. await network.provider.send("hardhat_setBalance", [ impersonatedSigner.address, - ethers.utils.parseEther("2").toHexString(), + ethers.utils.parseEther("2").toHexString() ]); await token.process(impersonatedSigner, address, amt); From d32c6288122fddbe76ecb83967d35cc0b5e8cac8 Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Wed, 9 Mar 2022 19:22:53 +0530 Subject: [PATCH 22/30] corrected doImport logic + added comments --- .../connectors/aave/v2-to-v3-import/main.sol | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol index 2e5dad19..28dcb312 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol @@ -112,6 +112,12 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { ); } + /** + * @dev Import aave position . + * @notice Import EOA's aave V2 position to DSA's aave v3 position + * @param userAccount The address of the EOA from which aave position will be imported + * @param inputData The struct containing all the neccessary input data + */ function importAaveV2ToV3( address userAccount, ImportInputData memory inputData @@ -120,15 +126,20 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { payable returns (string memory _eventName, bytes memory _eventParam) { - (_eventName, _eventParam) = _importAave(userAccount, inputData, false); + (_eventName, _eventParam) = _importAave(userAccount, inputData, true); } + /** + * @dev Migrate aave position . + * @notice Migrate DSA's aave V2 position to DSA's aave v3 position + * @param inputData The struct containing all the neccessary input data + */ function migrateAaveV2ToV3(ImportInputData memory inputData) external payable returns (string memory _eventName, bytes memory _eventParam) { - (_eventName, _eventParam) = _importAave(msg.sender, inputData, true); + (_eventName, _eventParam) = _importAave(msg.sender, inputData, false); } } From 766b95c7871e05a0360472496f723a894787f63e Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Wed, 9 Mar 2022 19:26:07 +0530 Subject: [PATCH 23/30] did the same changes on avalanche's --- .../connectors/aave/v2-to-v3-import/main.sol | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol index f695c23f..7a2b60b0 100644 --- a/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol @@ -110,6 +110,12 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { ); } + /** + * @dev Import aave position . + * @notice Import EOA's aave V2 position to DSA's aave v3 position + * @param userAccount The address of the EOA from which aave position will be imported + * @param inputData The struct containing all the neccessary input data + */ function importAaveV2ToV3( address userAccount, ImportInputData memory inputData @@ -118,9 +124,14 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { payable returns (string memory _eventName, bytes memory _eventParam) { - (_eventName, _eventParam) = _importAave(userAccount, inputData, false); + (_eventName, _eventParam) = _importAave(userAccount, inputData, true); } + /** + * @dev Migrate aave position . + * @notice Migrate DSA's aave V2 position to DSA's aave v3 position + * @param inputData The struct containing all the neccessary input data + */ function migrateAaveV2ToV3(ImportInputData memory inputData) external payable From 4a3382d342db848f084215392038a69b18290a0b Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Wed, 9 Mar 2022 22:06:42 +0530 Subject: [PATCH 24/30] added comments --- contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol index 7a2b60b0..f3b86f3a 100644 --- a/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol @@ -6,6 +6,10 @@ import "./interfaces.sol"; import "./helpers.sol"; import "./events.sol"; +/** + * @title Aave v2 to v3 import connector . + * @dev migrate aave V2 position to aave v3 position + */ contract _AaveV2ToV3MigrationResolver is _AaveHelper { function _importAave( address userAccount, From 8c2fab7bd58d788ce44af2ac5a097762ac4a49e4 Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Wed, 9 Mar 2022 22:08:55 +0530 Subject: [PATCH 25/30] minor fix --- contracts/polygon/connectors/aave/v2-to-v3-import/main.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol index 28dcb312..fbe6730c 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol @@ -6,6 +6,10 @@ import "./interfaces.sol"; import "./helpers.sol"; import "./events.sol"; +/** + * @title Aave v2 to v3 import connector . + * @dev migrate aave V2 position to aave v3 position + */ contract _AaveV2ToV3MigrationResolver is _AaveHelper { function _importAave( address userAccount, From ea5d7f611df589463abb6992efbf03a240d51292 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Thu, 10 Mar 2022 16:32:34 +0530 Subject: [PATCH 26/30] minor fix --- .../avalanche/connectors/aave/v2-to-v3-import/main.sol | 2 +- .../polygon/connectors/aave/v2-to-v3-import/helpers.sol | 4 +++- contracts/polygon/connectors/aave/v2-to-v3-import/main.sol | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol index f3b86f3a..8e360e81 100644 --- a/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/main.sol @@ -145,6 +145,6 @@ contract _AaveV2ToV3MigrationResolver is _AaveHelper { } } -contract ConnectV2AaveV2ToV3MigrationPolygon is _AaveV2ToV3MigrationResolver { +contract ConnectV2AaveV2ToV3MigrationAvalanche is _AaveV2ToV3MigrationResolver { string public constant name = "Aave-Import-v2-to-v3"; } diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol index caf76763..0882c791 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol @@ -175,7 +175,9 @@ contract _AaveHelper is Helper { address _token = inputData.supplyTokens[i] == maticAddr ? wmaticAddr : inputData.supplyTokens[i]; - (address _aToken, , ) = aaveV2Data.getReserveTokensAddresses(_token); + (address _aToken, , ) = aaveV2Data.getReserveTokensAddresses( + _token + ); data._supplyTokens[i] = _token; data.aTokens[i] = ATokenV2Interface(_aToken); data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount); diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol index fbe6730c..df8b273d 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol @@ -11,6 +11,13 @@ import "./events.sol"; * @dev migrate aave V2 position to aave v3 position */ contract _AaveV2ToV3MigrationResolver is _AaveHelper { + /** + * @dev Import aave position . + * @notice Import EOA's or DSA's aave V2 position to DSA's aave v3 position + * @param userAccount The address of the EOA from which aave position will be imported + * @param inputData The struct containing all the neccessary input data + * @param doImport boolean, to support DSA v2->v3 migration + */ function _importAave( address userAccount, ImportInputData memory inputData, From 251923ad3ec9989e1de22e0a11dcf852d3a36b8d Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Sat, 12 Mar 2022 13:02:35 +0530 Subject: [PATCH 27/30] updated aave v3 addresses --- contracts/arbitrum/connectors/aave/v3/helpers.sol | 4 ++-- contracts/avalanche/connectors/aave/v3/helpers.sol | 4 ++-- contracts/optimism/connectors/aave/v3/helpers.sol | 4 ++-- contracts/polygon/connectors/aave/v3/helpers.sol | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/arbitrum/connectors/aave/v3/helpers.sol b/contracts/arbitrum/connectors/aave/v3/helpers.sol index 48dd4cdc..1fff06e8 100644 --- a/contracts/arbitrum/connectors/aave/v3/helpers.sol +++ b/contracts/arbitrum/connectors/aave/v3/helpers.sol @@ -9,13 +9,13 @@ abstract contract Helpers is DSMath, Basic { * @dev Aave Pool Provider */ AavePoolProviderInterface internal constant aaveProvider = - AavePoolProviderInterface(0x7B291364Ce799edd4CD471E5C023FF965347E1E1); // Arbitrum address - PoolAddressesProvider + AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb); // Arbitrum address - PoolAddressesProvider /** * @dev Aave Pool Data Provider */ AaveDataProviderInterface internal constant aaveData = - AaveDataProviderInterface(0x224cD29570ED4Bfb2b55fF3eE27bEd28c58BBa86); //Arbitrum address - PoolDataProvider + AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); //Arbitrum address - PoolDataProvider /** * @dev Aave Referral Code diff --git a/contracts/avalanche/connectors/aave/v3/helpers.sol b/contracts/avalanche/connectors/aave/v3/helpers.sol index 171d7ac5..6c2f581e 100644 --- a/contracts/avalanche/connectors/aave/v3/helpers.sol +++ b/contracts/avalanche/connectors/aave/v3/helpers.sol @@ -9,13 +9,13 @@ abstract contract Helpers is DSMath, Basic { * @dev Aave Pool Provider */ AavePoolProviderInterface internal constant aaveProvider = - AavePoolProviderInterface(0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C); // Avalanche address - PoolAddressesProvider + AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb); // Avalanche address - PoolAddressesProvider /** * @dev Aave Pool Data Provider */ AaveDataProviderInterface internal constant aaveData = - AaveDataProviderInterface(0x44C7324E9d84D6534DD6f292Cc08f1816e45Ff6e); // Avalanche address - PoolDataProvider + AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); // Avalanche address - PoolDataProvider /** * @dev Aave Referral Code diff --git a/contracts/optimism/connectors/aave/v3/helpers.sol b/contracts/optimism/connectors/aave/v3/helpers.sol index fc896b79..f0fd9188 100644 --- a/contracts/optimism/connectors/aave/v3/helpers.sol +++ b/contracts/optimism/connectors/aave/v3/helpers.sol @@ -9,13 +9,13 @@ abstract contract Helpers is DSMath, Basic { * @dev Aave Pool Provider */ AavePoolProviderInterface internal constant aaveProvider = - AavePoolProviderInterface(0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C); // Optimism address - PoolAddressesProvider + AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb); // Optimism address - PoolAddressesProvider /** * @dev Aave Pool Data Provider */ AaveDataProviderInterface internal constant aaveData = - AaveDataProviderInterface(0x44C7324E9d84D6534DD6f292Cc08f1816e45Ff6e); // Optimism address - PoolDataProvider + AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); // Optimism address - PoolDataProvider /** * @dev Aave Referral Code diff --git a/contracts/polygon/connectors/aave/v3/helpers.sol b/contracts/polygon/connectors/aave/v3/helpers.sol index 8b2d0c50..28447ee0 100644 --- a/contracts/polygon/connectors/aave/v3/helpers.sol +++ b/contracts/polygon/connectors/aave/v3/helpers.sol @@ -9,13 +9,13 @@ abstract contract Helpers is DSMath, Basic { * @dev Aave Pool Provider */ AavePoolProviderInterface internal constant aaveProvider = - AavePoolProviderInterface(0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C); // Polygon address - PoolAddressesProvider + AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb); // Polygon address - PoolAddressesProvider /** * @dev Aave Pool Data Provider */ AaveDataProviderInterface internal constant aaveData = - AaveDataProviderInterface(0x44C7324E9d84D6534DD6f292Cc08f1816e45Ff6e); // Polygon address - PoolDataProvider + AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); // Polygon address - PoolDataProvider /** * @dev Aave Referral Code From d41b3e65aa0f4694536ce6a03a3ca8012c0987c5 Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Sat, 12 Mar 2022 13:53:38 +0530 Subject: [PATCH 28/30] updated aave v3 addresses --- contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol | 2 +- contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol | 2 +- contracts/polygon/connectors/aave/v2-to-v3-import/main.sol | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol b/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol index 36f067d9..d53dba5a 100644 --- a/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol +++ b/contracts/avalanche/connectors/aave/v2-to-v3-import/helpers.sol @@ -25,7 +25,7 @@ abstract contract Helper is DSMath, Basic { */ AaveV3PoolProviderInterface internal constant aaveV3Provider = AaveV3PoolProviderInterface( - 0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C // v3 - PoolAddressesProvider Avalanche + 0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb // v3 - PoolAddressesProvider Avalanche ); /** diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol index 0882c791..5da70943 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/helpers.sol @@ -25,7 +25,7 @@ abstract contract Helper is DSMath, Basic { */ AaveV3PoolProviderInterface internal constant aaveV3Provider = AaveV3PoolProviderInterface( - 0x7013523049CeC8b06F594edb8c5fb7F232c0Df7C // Polygon address - PoolAddressesProvider + 0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb // Polygon address - PoolAddressesProvider ); /** diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol index df8b273d..d172ff48 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol @@ -10,6 +10,7 @@ import "./events.sol"; * @title Aave v2 to v3 import connector . * @dev migrate aave V2 position to aave v3 position */ + contract _AaveV2ToV3MigrationResolver is _AaveHelper { /** * @dev Import aave position . From 64b7455896e0ece7d0f787e2ceae3b1f637dd3d2 Mon Sep 17 00:00:00 2001 From: bhavik-m Date: Sat, 12 Mar 2022 21:04:42 +0530 Subject: [PATCH 29/30] added connector on fantom --- .../avalanche/connectors/aave/v3/main.sol | 4 +- contracts/fantom/common/basic.sol | 91 ++++++ contracts/fantom/common/interfaces.sol | 35 +++ contracts/fantom/common/math.sol | 54 ++++ contracts/fantom/common/stores.sol | 40 +++ .../fantom/connectors/aave/v3/events.sol | 33 ++ .../fantom/connectors/aave/v3/helpers.sol | 66 ++++ .../fantom/connectors/aave/v3/interface.sol | 91 ++++++ contracts/fantom/connectors/aave/v3/main.sol | 296 ++++++++++++++++++ contracts/mainnet/connectors/aave/v3/main.sol | 6 +- .../optimism/connectors/aave/v3/main.sol | 6 +- contracts/polygon/connectors/aave/v3/main.sol | 4 +- hardhat.config.ts | 66 ++-- 13 files changed, 748 insertions(+), 44 deletions(-) create mode 100644 contracts/fantom/common/basic.sol create mode 100644 contracts/fantom/common/interfaces.sol create mode 100644 contracts/fantom/common/math.sol create mode 100644 contracts/fantom/common/stores.sol create mode 100644 contracts/fantom/connectors/aave/v3/events.sol create mode 100644 contracts/fantom/connectors/aave/v3/helpers.sol create mode 100644 contracts/fantom/connectors/aave/v3/interface.sol create mode 100644 contracts/fantom/connectors/aave/v3/main.sol diff --git a/contracts/avalanche/connectors/aave/v3/main.sol b/contracts/avalanche/connectors/aave/v3/main.sol index 6697810a..aa9611fb 100644 --- a/contracts/avalanche/connectors/aave/v3/main.sol +++ b/contracts/avalanche/connectors/aave/v3/main.sol @@ -64,7 +64,7 @@ abstract contract AaveResolver is Events, Helpers { /** * @dev Withdraw avax/ERC20_Token. - * @notice Withdraw deposited token from Aave v2 + * @notice Withdraw deposited token from Aave v3 * @param token The address of the token to withdraw.(For avax: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) * @param getId ID to retrieve amt. @@ -104,7 +104,7 @@ abstract contract AaveResolver is Events, Helpers { /** * @dev Borrow avax/ERC20_Token. - * @notice Borrow a token using Aave v2 + * @notice Borrow a token using Aave v3 * @param token The address of the token to borrow.(For avax: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param amt The amount of the token to borrow. * @param rateMode The type of borrow debt. (For Stable: 1, Variable: 2) diff --git a/contracts/fantom/common/basic.sol b/contracts/fantom/common/basic.sol new file mode 100644 index 00000000..ba834cfd --- /dev/null +++ b/contracts/fantom/common/basic.sol @@ -0,0 +1,91 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "./interfaces.sol"; +import { Stores } from "./stores.sol"; +import { DSMath } from "./math.sol"; + +abstract contract Basic is DSMath, Stores { + function convert18ToDec(uint256 _dec, uint256 _amt) + internal + pure + returns (uint256 amt) + { + amt = (_amt / 10**(18 - _dec)); + } + + function convertTo18(uint256 _dec, uint256 _amt) + internal + pure + returns (uint256 amt) + { + amt = mul(_amt, 10**(18 - _dec)); + } + + function getTokenBal(TokenInterface token) + internal + view + returns (uint256 _amt) + { + _amt = address(token) == ftmAddr + ? address(this).balance + : token.balanceOf(address(this)); + } + + function getTokensDec(TokenInterface buyAddr, TokenInterface sellAddr) + internal + view + returns (uint256 buyDec, uint256 sellDec) + { + buyDec = address(buyAddr) == ftmAddr ? 18 : buyAddr.decimals(); + sellDec = address(sellAddr) == ftmAddr ? 18 : sellAddr.decimals(); + } + + function encodeEvent(string memory eventName, bytes memory eventParam) + internal + pure + returns (bytes memory) + { + return abi.encode(eventName, eventParam); + } + + function approve( + TokenInterface token, + address spender, + uint256 amount + ) internal { + try token.approve(spender, amount) {} catch { + token.approve(spender, 0); + token.approve(spender, amount); + } + } + + function changeftmAddress(address buy, address sell) + internal + pure + returns (TokenInterface _buy, TokenInterface _sell) + { + _buy = buy == ftmAddr ? TokenInterface(wftmAddr) : TokenInterface(buy); + _sell = sell == ftmAddr + ? TokenInterface(wftmAddr) + : TokenInterface(sell); + } + + function convertFtmToWftm( + bool isFtm, + TokenInterface token, + uint256 amount + ) internal { + if (isFtm) token.deposit{ value: amount }(); + } + + function convertWftmToFtm( + bool isFtm, + TokenInterface token, + uint256 amount + ) internal { + if (isFtm) { + approve(token, address(token), amount); + token.withdraw(amount); + } + } +} diff --git a/contracts/fantom/common/interfaces.sol b/contracts/fantom/common/interfaces.sol new file mode 100644 index 00000000..ff92c278 --- /dev/null +++ b/contracts/fantom/common/interfaces.sol @@ -0,0 +1,35 @@ +pragma solidity ^0.7.0; + +interface TokenInterface { + function approve(address, uint256) external; + + function transfer(address, uint256) external; + + function transferFrom( + address, + address, + uint256 + ) external; + + function deposit() external payable; + + function withdraw(uint256) external; + + function balanceOf(address) external view returns (uint256); + + function decimals() external view returns (uint256); +} + +interface MemoryInterface { + function getUint(uint256 id) external returns (uint256 num); + + function setUint(uint256 id, uint256 val) external; +} + +interface AccountInterface { + function enable(address) external; + + function disable(address) external; + + function isAuth(address) external view returns (bool); +} diff --git a/contracts/fantom/common/math.sol b/contracts/fantom/common/math.sol new file mode 100644 index 00000000..81f0bd38 --- /dev/null +++ b/contracts/fantom/common/math.sol @@ -0,0 +1,54 @@ +pragma solidity ^0.7.0; + +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; + +contract DSMath { + uint256 constant WAD = 10**18; + uint256 constant RAY = 10**27; + + function add(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = SafeMath.add(x, y); + } + + function sub(uint256 x, uint256 y) + internal + pure + virtual + returns (uint256 z) + { + z = SafeMath.sub(x, y); + } + + function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = SafeMath.mul(x, y); + } + + function div(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = SafeMath.div(x, y); + } + + function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = SafeMath.add(SafeMath.mul(x, y), WAD / 2) / WAD; + } + + function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = SafeMath.add(SafeMath.mul(x, WAD), y / 2) / y; + } + + function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = SafeMath.add(SafeMath.mul(x, RAY), y / 2) / y; + } + + function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = SafeMath.add(SafeMath.mul(x, y), RAY / 2) / RAY; + } + + function toInt(uint256 x) internal pure returns (int256 y) { + y = int256(x); + require(y >= 0, "int-overflow"); + } + + function toRad(uint256 wad) internal pure returns (uint256 rad) { + rad = mul(wad, 10**27); + } +} diff --git a/contracts/fantom/common/stores.sol b/contracts/fantom/common/stores.sol new file mode 100644 index 00000000..0b261c7f --- /dev/null +++ b/contracts/fantom/common/stores.sol @@ -0,0 +1,40 @@ +pragma solidity ^0.7.0; + +import { MemoryInterface } from "./interfaces.sol"; + +abstract contract Stores { + /** + * @dev Return FTM address + */ + address internal constant ftmAddr = + 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + + /** + * @dev Return Wrapped FTM address + */ + address internal constant wftmAddr = + 0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83; + + /** + * @dev Return memory variable address + */ + MemoryInterface internal constant instaMemory = + MemoryInterface(0x56439117379A53bE3CC2C55217251e2481B7a1C8); + + /** + * @dev Get Uint value from InstaMemory Contract. + */ + function getUint(uint256 getId, uint256 val) + internal + returns (uint256 returnVal) + { + returnVal = getId == 0 ? val : instaMemory.getUint(getId); + } + + /** + * @dev Set Uint value in InstaMemory Contract. + */ + function setUint(uint256 setId, uint256 val) internal virtual { + if (setId != 0) instaMemory.setUint(setId, val); + } +} diff --git a/contracts/fantom/connectors/aave/v3/events.sol b/contracts/fantom/connectors/aave/v3/events.sol new file mode 100644 index 00000000..9f60f22b --- /dev/null +++ b/contracts/fantom/connectors/aave/v3/events.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDeposit( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogWithdraw( + address indexed token, + uint256 tokenAmt, + uint256 getId, + uint256 setId + ); + event LogBorrow( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogPayback( + address indexed token, + uint256 tokenAmt, + uint256 indexed rateMode, + uint256 getId, + uint256 setId + ); + event LogEnableCollateral(address[] tokens); + event LogSwapRateMode(address indexed token, uint256 rateMode); + event LogSetUserEMode(uint8 categoryId); +} diff --git a/contracts/fantom/connectors/aave/v3/helpers.sol b/contracts/fantom/connectors/aave/v3/helpers.sol new file mode 100644 index 00000000..8b970670 --- /dev/null +++ b/contracts/fantom/connectors/aave/v3/helpers.sol @@ -0,0 +1,66 @@ +pragma solidity ^0.7.0; + +import { DSMath } from "../../../common/math.sol"; +import { Basic } from "../../../common/basic.sol"; +import { AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + /** + * @dev Aave Pool Provider + */ + AavePoolProviderInterface internal constant aaveProvider = + AavePoolProviderInterface(0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb); // fantom address - PoolAddressesProvider + + /** + * @dev Aave Pool Data Provider + */ + AaveDataProviderInterface internal constant aaveData = + AaveDataProviderInterface(0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654); // fantom address - PoolDataProvider + + /** + * @dev Aave Referral Code + */ + uint16 internal constant referralCode = 3228; + + /** + * @dev Checks if collateral is enabled for an asset + * @param token token address of the asset.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + + function getIsColl(address token) internal view returns (bool isCol) { + (, , , , , , , , isCol) = aaveData.getUserReserveData( + token, + address(this) + ); + } + + /** + * @dev Get total debt balance & fee for an asset + * @param token token address of the debt.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Borrow rate mode (Stable = 1, Variable = 2) + */ + function getPaybackBalance(address token, uint256 rateMode) + internal + view + returns (uint256) + { + (, uint256 stableDebt, uint256 variableDebt, , , , , , ) = aaveData + .getUserReserveData(token, address(this)); + return rateMode == 1 ? stableDebt : variableDebt; + } + + /** + * @dev Get total collateral balance for an asset + * @param token token address of the collateral.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + */ + function getCollateralBalance(address token) + internal + view + returns (uint256 bal) + { + (bal, , , , , , , , ) = aaveData.getUserReserveData( + token, + address(this) + ); + } +} diff --git a/contracts/fantom/connectors/aave/v3/interface.sol b/contracts/fantom/connectors/aave/v3/interface.sol new file mode 100644 index 00000000..8ae14716 --- /dev/null +++ b/contracts/fantom/connectors/aave/v3/interface.sol @@ -0,0 +1,91 @@ +pragma solidity ^0.7.0; + +interface AaveInterface { + function supply( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + function withdraw( + address asset, + uint256 amount, + address to + ) external returns (uint256); + + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) external; + + function repay( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf + ) external returns (uint256); + + function repayWithATokens( + address asset, + uint256 amount, + uint256 interestRateMode + ) external returns (uint256); + + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) + external; + + function swapBorrowRateMode(address asset, uint256 interestRateMode) + external; + + function setUserEMode(uint8 categoryId) external; +} + +interface AavePoolProviderInterface { + function getPool() external view returns (address); +} + +interface AaveDataProviderInterface { + function getReserveTokensAddresses(address _asset) + external + view + returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); + + function getUserReserveData(address _asset, address _user) + external + view + returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); + + function getReserveEModeCategory(address asset) + external + view + returns (uint256); +} + +interface AaveAddressProviderRegistryInterface { + function getAddressesProvidersList() + external + view + returns (address[] memory); +} + +interface ATokenInterface { + function balanceOf(address _user) external view returns (uint256); +} diff --git a/contracts/fantom/connectors/aave/v3/main.sol b/contracts/fantom/connectors/aave/v3/main.sol new file mode 100644 index 00000000..66506cff --- /dev/null +++ b/contracts/fantom/connectors/aave/v3/main.sol @@ -0,0 +1,296 @@ +pragma solidity ^0.7.0; + +/** + * @title Aave v3. + * @dev Lending & Borrowing. + */ + +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"; + +abstract contract AaveResolver is Events, Helpers { + /** + * @dev Deposit Ftm/ERC20_Token. + * @notice Deposit a token to Aave v3 for lending / collaterization. + * @param token The address of the token to deposit.(For ftm: 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 deposit( + 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 isFTM = token == ftmAddr; + address _token = isFTM ? wftmAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + if (isFTM) { + _amt = _amt == uint256(-1) ? address(this).balance : _amt; + convertFtmToWftm(isFTM, 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 (!getIsColl(_token)) { + aave.setUserUseReserveAsCollateral(_token, true); + } + + setUint(setId, _amt); + + _eventName = "LogDeposit(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } + + /** + * @dev Withdraw ftm/ERC20_Token. + * @notice Withdraw deposited token from Aave v3 + * @param token The address of the token to withdraw.(For ftm: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens withdrawn. + */ + function withdraw( + 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 isFTM = token == ftmAddr; + address _token = isFTM ? wftmAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + uint256 initialBal = tokenContract.balanceOf(address(this)); + aave.withdraw(_token, _amt, address(this)); + uint256 finalBal = tokenContract.balanceOf(address(this)); + + _amt = sub(finalBal, initialBal); + + convertWftmToFtm(isFTM, tokenContract, _amt); + + setUint(setId, _amt); + + _eventName = "LogWithdraw(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, getId, setId); + } + + /** + * @dev Borrow ftm/ERC20_Token. + * @notice Borrow a token using Aave v3 + * @param token The address of the token to borrow.(For ftm: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to borrow. + * @param rateMode The type of borrow debt. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens borrowed. + */ + function borrow( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isFTM = token == ftmAddr; + address _token = isFTM ? wftmAddr : token; + + aave.borrow(_token, _amt, rateMode, referralCode, address(this)); + convertWftmToFtm(isFTM, TokenInterface(_token), _amt); + + setUint(setId, _amt); + + _eventName = "LogBorrow(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Payback borrowed ftm/ERC20_Token. + * @notice Payback debt owed. + * @param token The address of the token to payback.(For ftm: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function payback( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isFTM = token == ftmAddr; + address _token = isFTM ? wftmAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isFTM) convertFtmToWftm(isFTM, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repay(_token, _amt, rateMode, address(this)); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Payback borrowed ftm/ERC20_Token using aTokens. + * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the equivalent debt tokens. + * @param token The address of the token to payback.(For ftm: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amt The amount of the token to payback. (For max: `uint256(-1)`) + * @param rateMode The type of debt paying back. (For Stable: 1, Variable: 2) + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of tokens paid back. + */ + function paybackWithATokens( + address token, + uint256 amt, + uint256 rateMode, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amt); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + bool isFTM = token == ftmAddr; + address _token = isFTM ? wftmAddr : token; + + TokenInterface tokenContract = TokenInterface(_token); + + _amt = _amt == uint256(-1) ? getPaybackBalance(_token, rateMode) : _amt; + + if (isFTM) convertFtmToWftm(isFTM, tokenContract, _amt); + + approve(tokenContract, address(aave), _amt); + + aave.repayWithATokens(_token, _amt, rateMode); + + setUint(setId, _amt); + + _eventName = "LogPayback(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, _amt, rateMode, getId, setId); + } + + /** + * @dev Enable collateral + * @notice Enable an array of tokens as collateral + * @param tokens Array of tokens to enable collateral + */ + function enableCollateral(address[] calldata tokens) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _length = tokens.length; + require(_length > 0, "0-tokens-not-allowed"); + + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + for (uint256 i = 0; i < _length; i++) { + address token = tokens[i]; + if (getCollateralBalance(token) > 0 && !getIsColl(token)) { + aave.setUserUseReserveAsCollateral(token, true); + } + } + + _eventName = "LogEnableCollateral(address[])"; + _eventParam = abi.encode(tokens); + } + + /** + * @dev Swap borrow rate mode + * @notice Swaps user borrow rate mode between variable and stable + * @param token The address of the token to swap borrow rate.(For ftm: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param rateMode Desired borrow rate mode. (Stable = 1, Variable = 2) + */ + function swapBorrowRateMode(address token, uint256 rateMode) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + uint256 currentRateMode = rateMode == 1 ? 2 : 1; + + if (getPaybackBalance(token, currentRateMode) > 0) { + aave.swapBorrowRateMode(token, rateMode); + } + + _eventName = "LogSwapRateMode(address,uint256)"; + _eventParam = abi.encode(token, rateMode); + } + + /** + * @dev Set user e-mode + * @notice Updates the user's e-mode category + * @param categoryId The category Id of the e-mode user want to set + */ + function setUserEMode(uint8 categoryId) + external + returns (string memory _eventName, bytes memory _eventParam) + { + AaveInterface aave = AaveInterface(aaveProvider.getPool()); + + aave.setUserEMode(categoryId); + + _eventName = "LogSetUserEMode(uint8)"; + _eventParam = abi.encode(categoryId); + } +} + +contract ConnectV2AaveV3Fantom is AaveResolver { + string public constant name = "AaveV3-v1"; +} diff --git a/contracts/mainnet/connectors/aave/v3/main.sol b/contracts/mainnet/connectors/aave/v3/main.sol index 14ee9678..1c7b0a8b 100644 --- a/contracts/mainnet/connectors/aave/v3/main.sol +++ b/contracts/mainnet/connectors/aave/v3/main.sol @@ -14,7 +14,7 @@ import { AaveInterface } from "./interface.sol"; abstract contract AaveResolver is Events, Helpers { /** * @dev Deposit ETH/ERC20_Token. - * @notice Deposit a token to Aave v2 for lending / collaterization. + * @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. @@ -64,7 +64,7 @@ abstract contract AaveResolver is Events, Helpers { /** * @dev Withdraw ETH/ERC20_Token. - * @notice Withdraw deposited token from Aave v2 + * @notice Withdraw deposited token from Aave v3 * @param token The address of the token to withdraw.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) * @param getId ID to retrieve amt. @@ -104,7 +104,7 @@ abstract contract AaveResolver is Events, Helpers { /** * @dev Borrow ETH/ERC20_Token. - * @notice Borrow a token using Aave v2 + * @notice Borrow a token using Aave v3 * @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) diff --git a/contracts/optimism/connectors/aave/v3/main.sol b/contracts/optimism/connectors/aave/v3/main.sol index d778832b..62be7a41 100644 --- a/contracts/optimism/connectors/aave/v3/main.sol +++ b/contracts/optimism/connectors/aave/v3/main.sol @@ -14,7 +14,7 @@ import { AaveInterface } from "./interface.sol"; abstract contract AaveResolver is Events, Helpers { /** * @dev Deposit ETH/ERC20_Token. - * @notice Deposit a token to Aave v2 for lending / collaterization. + * @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. @@ -64,7 +64,7 @@ abstract contract AaveResolver is Events, Helpers { /** * @dev Withdraw ETH/ERC20_Token. - * @notice Withdraw deposited token from Aave v2 + * @notice Withdraw deposited token from Aave v3 * @param token The address of the token to withdraw.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) * @param getId ID to retrieve amt. @@ -104,7 +104,7 @@ abstract contract AaveResolver is Events, Helpers { /** * @dev Borrow ETH/ERC20_Token. - * @notice Borrow a token using Aave v2 + * @notice Borrow a token using Aave v3 * @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) diff --git a/contracts/polygon/connectors/aave/v3/main.sol b/contracts/polygon/connectors/aave/v3/main.sol index 39038f75..c7782667 100644 --- a/contracts/polygon/connectors/aave/v3/main.sol +++ b/contracts/polygon/connectors/aave/v3/main.sol @@ -64,7 +64,7 @@ abstract contract AaveResolver is Events, Helpers { /** * @dev Withdraw matic/ERC20_Token. - * @notice Withdraw deposited token from Aave v2 + * @notice Withdraw deposited token from Aave v3 * @param token The address of the token to withdraw.(For matic: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param amt The amount of the token to withdraw. (For max: `uint256(-1)`) * @param getId ID to retrieve amt. @@ -104,7 +104,7 @@ abstract contract AaveResolver is Events, Helpers { /** * @dev Borrow matic/ERC20_Token. - * @notice Borrow a token using Aave v2 + * @notice Borrow a token using Aave v3 * @param token The address of the token to borrow.(For matic: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param amt The amount of the token to borrow. * @param rateMode The type of borrow debt. (For Stable: 1, Variable: 2) diff --git a/hardhat.config.ts b/hardhat.config.ts index d3bd78b9..d81ccf29 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -13,6 +13,7 @@ import { HardhatUserConfig } from "hardhat/config"; import { NetworkUserConfig } from "hardhat/types"; import { utils } from "ethers"; import Web3 from "web3"; +import { network } from "hardhat"; dotenvConfig({ path: resolve(__dirname, "./.env") }); @@ -36,34 +37,30 @@ const ETHERSCAN_API = process.env.ETHERSCAN_API_KEY; const POLYGONSCAN_API = process.env.POLYGON_API_KEY; const ARBISCAN_API = process.env.ARBISCAN_API_KEY; const SNOWTRACE_API = process.env.SNOWTRACE_API_KEY; -const mnemonic = - process.env.MNEMONIC ?? - "test test test test test test test test test test test junk"; +const FANTOMSCAN_API = process.env.FANTOM_API_KEY; +const mnemonic = process.env.MNEMONIC ?? "test test test test test test test test test test test junk"; const networkGasPriceConfig: Record = { - "mainnet": "160", - "polygon": "50", - "avalanche": "50", - "arbitrum": "2" -} + mainnet: "160", + polygon: "50", + avalanche: "50", + arbitrum: "2" +}; function createConfig(network: string) { return { url: getNetworkUrl(network), - accounts: !!PRIVATE_KEY ? [`0x${PRIVATE_KEY}`] : { mnemonic }, + accounts: !!PRIVATE_KEY ? [`0x${PRIVATE_KEY}`] : { mnemonic } // gasPrice: 1000000, // 0.0001 GWEI }; } function getNetworkUrl(networkType: string) { - if (networkType === "avalanche") - return "https://api.avax.network/ext/bc/C/rpc"; - else if (networkType === "polygon") - return `https://polygon-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; - else if (networkType === "arbitrum") - return `https://arb-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; - else if (networkType === "optimism") - return `https://opt-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; + if (networkType === "avalanche") return "https://api.avax.network/ext/bc/C/rpc"; + else if (networkType === "polygon") return `https://polygon-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; + else if (networkType === "arbitrum") return `https://arb-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; + else if (networkType === "optimism") return `https://opt-mainnet.g.alchemy.com/v2/${alchemyApiKey}`; + else if (networkType === "fantom") return `https://rpc.ftm.tools/`; else return `https://eth-mainnet.alchemyapi.io/v2/${alchemyApiKey}`; } @@ -85,53 +82,54 @@ const config: HardhatUserConfig = { settings: { optimizer: { enabled: true, - runs: 200, - }, - }, + runs: 200 + } + } }, { - version: "0.6.0", + version: "0.6.0" }, { - version: "0.6.2", + version: "0.6.2" }, { - version: "0.6.5", - }, - ], + version: "0.6.5" + } + ] }, networks: { hardhat: { accounts: { - mnemonic, + mnemonic }, chainId: chainIds.hardhat, forking: { - url: String(getNetworkUrl(String(process.env.networkType))), - }, + url: String(getNetworkUrl(String(process.env.networkType))) + } }, mainnet: createConfig("mainnet"), polygon: createConfig("polygon"), avalanche: createConfig("avalanche"), arbitrum: createConfig("arbitrum"), optimism: createConfig("optimism"), + fantom: createConfig("optimism") }, paths: { artifacts: "./artifacts", cache: "./cache", sources: "./contracts", - tests: "./test", + tests: "./test" }, - etherscan: { - apiKey: getScanApiKey(String(process.env.networkType)), + etherscan: { + apiKey: getScanApiKey(String(process.env.networkType)) }, typechain: { outDir: "typechain", - target: "ethers-v5", + target: "ethers-v5" }, mocha: { - timeout: 10000 * 1000, // 10,000 seconds - }, + timeout: 10000 * 1000 // 10,000 seconds + } // tenderly: { // project: process.env.TENDERLY_PROJECT, // username: process.env.TENDERLY_USERNAME, From 21c68c3290d49e2a59e80117c7916ac4300a1fad Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Mon, 14 Mar 2022 20:58:58 +0530 Subject: [PATCH 30/30] fixed netspec comments --- .../polygon/connectors/aave/v2-to-v3-import/main.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol index d172ff48..06a7d43b 100644 --- a/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol +++ b/contracts/polygon/connectors/aave/v2-to-v3-import/main.sol @@ -1,16 +1,16 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; -import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol"; -import "./interfaces.sol"; -import "./helpers.sol"; -import "./events.sol"; - /** * @title Aave v2 to v3 import connector . * @dev migrate aave V2 position to aave v3 position */ +import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol"; +import "./interfaces.sol"; +import "./helpers.sol"; +import "./events.sol"; + contract _AaveV2ToV3MigrationResolver is _AaveHelper { /** * @dev Import aave position .