feat: add aave v3 contracts

This commit is contained in:
Shriya Tyagi 2023-08-26 04:35:21 +05:30
parent ec99663565
commit a0ef584bd5
12 changed files with 1517 additions and 0 deletions

View File

@ -0,0 +1,13 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
contract Events {
event LogClaimed(
address[] assets,
uint256 amt,
uint256 getId,
uint256 setId
);
event LogAllClaimed(address[] assets, address[] rewards, uint256[] amts);
}

View File

@ -0,0 +1,14 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import { DSMath } from "../../../common/math.sol";
import { Basic } from "../../../common/basic.sol";
import { AaveIncentivesInterface } from "./interface.sol";
abstract contract Helpers is DSMath, Basic {
/**
* @dev Aave v3 Incentives
*/
AaveIncentivesInterface internal constant incentives =
AaveIncentivesInterface(0xf9cc4F0D883F1a1eb2c253bdb46c254Ca51E1F44);
}

View File

@ -0,0 +1,15 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
interface AaveIncentivesInterface {
function claimRewards(
address[] calldata assets,
uint256 amount,
address to,
address reward
) external returns (uint256);
function claimAllRewards(address[] calldata assets, address to)
external
returns (address[] memory rewardsList, uint256[] memory claimedAmounts);
}

View File

@ -0,0 +1,78 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
/**
* @title Aave v3 Rewards.
* @dev Claim Aave v3 rewards.
*/
import { TokenInterface } from "../../../common/interfaces.sol";
import { Stores } from "../../../common/stores.sol";
import { Helpers } from "./helpers.sol";
import { Events } from "./events.sol";
abstract contract IncentivesResolver is Helpers, Events {
/**
* @dev Claim Pending Rewards.
* @notice Claim Pending Rewards from Aave v3 incentives contract.
* @param assets The list of assets supplied and borrowed.
* @param amt The amount of reward to claim. (uint(-1) for max)
* @param reward The address of reward token to claim.
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of rewards claimed.
*/
function claim(
address[] calldata assets,
uint256 amt,
address reward,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
uint256 _amt = getUint(getId, amt);
require(assets.length > 0, "invalid-assets");
_amt = incentives.claimRewards(assets, _amt, address(this), reward);
TokenInterface weth = TokenInterface(wethAddr);
uint256 wethAmount = weth.balanceOf(address(this));
convertWethToEth(wethAmount > 0, weth, wethAmount);
setUint(setId, _amt);
_eventName = "LogClaimed(address[],uint256,uint256,uint256)";
_eventParam = abi.encode(assets, _amt, getId, setId);
}
/**
* @dev Claim All Pending Rewards.
* @notice Claim All Pending Rewards from Aave v3 incentives contract.
* @param assets The list of assets supplied and borrowed.
*/
function claimAll(address[] calldata assets)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
require(assets.length > 0, "invalid-assets");
uint256[] memory _amts = new uint256[](assets.length);
address[] memory _rewards = new address[](assets.length);
(_rewards, _amts) = incentives.claimAllRewards(assets, address(this));
TokenInterface weth = TokenInterface(wethAddr);
uint256 wethAmount = weth.balanceOf(address(this));
convertWethToEth(wethAmount > 0, weth, wethAmount);
_eventName = "LogAllClaimed(address[],address[],uint256[])";
_eventParam = abi.encode(assets, _rewards, _amts);
}
}
contract ConnectV3AaveIncentivesBase is IncentivesResolver {
string public constant name = "Aave-V3-Incentives-v1";
}

View File

@ -0,0 +1,25 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
contract Events {
event LogAaveV3Import(
address indexed user,
address[] ctokens,
string[] supplyIds,
string[] borrowIds,
uint256[] flashLoanFees,
uint256[] supplyAmts,
uint256[] borrowAmts
);
event LogAaveV3ImportWithCollateral(
address indexed user,
address[] atokens,
string[] supplyIds,
string[] borrowIds,
uint256[] flashLoanFees,
uint256[] supplyAmts,
uint256[] borrowAmts,
bool[] enableCollateral
);
}

View File

@ -0,0 +1,315 @@
//SPDX-License-Identifier: MIT
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 { AaveInterface, AavePoolProviderInterface, AaveDataProviderInterface } from "./interface.sol";
import "./events.sol";
import "./interface.sol";
abstract contract Helper is DSMath, Basic {
/**
* @dev Aave referal code
*/
uint16 internal constant referalCode = 3228;
/**
* @dev Aave Lending Pool Provider
*/
AavePoolProviderInterface internal constant aaveProvider =
AavePoolProviderInterface(0xe20fCBdBfFC4Dd138cE8b2E6FBb6CB49777ad64D);
/**
* @dev Aave Protocol Data Provider
*/
AaveDataProviderInterface internal constant aaveData =
AaveDataProviderInterface(0x2d8A3C5677189723C4cB8873CfC9C8976FDF38Ac);
function getIsColl(address token, address user)
internal
view
returns (bool isCol)
{
(, , , , , , , , isCol) = aaveData.getUserReserveData(token, user);
}
struct ImportData {
address[] _supplyTokens;
address[] _borrowTokens;
ATokenInterface[] 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 AaveHelpers is Helper {
function getBorrowAmount(address _token, address userAccount)
internal
view
returns (uint256 stableBorrow, uint256 variableBorrow)
{
(
,
address stableDebtTokenAddress,
address variableDebtTokenAddress
) = aaveData.getReserveTokensAddresses(_token);
stableBorrow = ATokenInterface(stableDebtTokenAddress).balanceOf(
userAccount
);
variableBorrow = ATokenInterface(variableDebtTokenAddress).balanceOf(
userAccount
);
}
function getBorrowAmounts(
address userAccount,
AaveInterface aave,
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.variableBorrowAmtsWithFee = new uint256[](
inputData.borrowTokens.length
);
data.stableBorrowAmts = new uint256[](
inputData.borrowTokens.length
);
data.stableBorrowAmtsWithFee = new uint256[](
inputData.borrowTokens.length
);
data.totalBorrowAmts = new uint256[](inputData.borrowTokens.length);
data.totalBorrowAmtsWithFee = 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] == ethAddr
? wethAddr
: 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(aave), _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 ATokenInterface[](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] == ethAddr
? wethAddr
: inputData.supplyTokens[i];
(address _aToken, , ) = aaveData.getReserveTokensAddresses(_token);
data._supplyTokens[i] = _token;
data.aTokens[i] = ATokenInterface(_aToken);
data.supplyAmts[i] = data.aTokens[i].balanceOf(userAccount);
}
return data;
}
function _paybackBehalfOne(
AaveInterface aave,
address token,
uint256 amt,
uint256 rateMode,
address user
) private {
aave.repay(token, amt, rateMode, user);
}
function _PaybackStable(
uint256 _length,
AaveInterface aave,
address[] memory tokens,
uint256[] memory amts,
address user
) internal {
for (uint256 i = 0; i < _length; i++) {
if (amts[i] > 0) {
_paybackBehalfOne(aave, tokens[i], amts[i], 1, user);
}
}
}
function _PaybackVariable(
uint256 _length,
AaveInterface aave,
address[] memory tokens,
uint256[] memory amts,
address user
) internal {
for (uint256 i = 0; i < _length; i++) {
if (amts[i] > 0) {
_paybackBehalfOne(aave, tokens[i], amts[i], 2, user);
}
}
}
function _TransferAtokens(
uint256 _length,
AaveInterface aave,
ATokenInterface[] 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))) {
aave.setUserUseReserveAsCollateral(tokens[i], true);
}
}
}
}
function _TransferAtokensWithCollateral(
uint256 _length,
AaveInterface aave,
ATokenInterface[] memory atokenContracts,
uint256[] memory amts,
address[] memory tokens,
bool[] memory colEnable,
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))) {
aave.setUserUseReserveAsCollateral(tokens[i], colEnable[i]);
}
}
}
}
function _BorrowVariable(
uint256 _length,
AaveInterface aave,
address[] memory tokens,
uint256[] memory amts
) internal {
for (uint256 i = 0; i < _length; i++) {
if (amts[i] > 0) {
_borrowOne(aave, tokens[i], amts[i], 2);
}
}
}
function _BorrowStable(
uint256 _length,
AaveInterface aave,
address[] memory tokens,
uint256[] memory amts
) internal {
for (uint256 i = 0; i < _length; i++) {
if (amts[i] > 0) {
_borrowOne(aave, tokens[i], amts[i], 1);
}
}
}
function _borrowOne(
AaveInterface aave,
address token,
uint256 amt,
uint256 rateMode
) private {
aave.borrow(token, amt, rateMode, referalCode, address(this));
}
}

View File

@ -0,0 +1,95 @@
//SPDX-License-Identifier: MIT
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;
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 ATokenInterface {
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);
}
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
);
}
interface AaveAddressProviderRegistryInterface {
function getAddressesProvidersList()
external
view
returns (address[] memory);
}

View File

@ -0,0 +1,209 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/**
* @title Aave v3 import connector .
* @dev Import EOA's aave V3 position to DSA's aave v3 position
*/
import { TokenInterface, AccountInterface } from "../../../common/interfaces.sol";
import { AaveInterface, ATokenInterface } from "./interface.sol";
import "./helpers.sol";
import "./events.sol";
contract AaveV3ImportResolver is AaveHelpers {
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;
AaveInterface aave = AaveInterface(aaveProvider.getPool());
data = getBorrowAmounts(userAccount, aave, inputData, data);
data = getSupplyAmounts(userAccount, inputData, data);
// payback borrowed amount;
_PaybackStable(
data._borrowTokens.length,
aave,
data._borrowTokens,
data.stableBorrowAmts,
userAccount
);
_PaybackVariable(
data._borrowTokens.length,
aave,
data._borrowTokens,
data.variableBorrowAmts,
userAccount
);
// transfer atokens to this address;
_TransferAtokens(
data._supplyTokens.length,
aave,
data.aTokens,
data.supplyAmts,
data._supplyTokens,
userAccount
);
// borrow assets after migrating position
if (data.convertStable) {
_BorrowVariable(
data._borrowTokens.length,
aave,
data._borrowTokens,
data.totalBorrowAmtsWithFee
);
} else {
_BorrowStable(
data._borrowTokens.length,
aave,
data._borrowTokens,
data.stableBorrowAmtsWithFee
);
_BorrowVariable(
data._borrowTokens.length,
aave,
data._borrowTokens,
data.variableBorrowAmtsWithFee
);
}
_eventName = "LogAaveV3Import(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 _importAaveWithCollateral(address userAccount, ImportInputData memory inputData, bool[] memory enableCollateral)
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");
require(enableCollateral.length == inputData.supplyTokens.length, "lengths-not-same");
ImportData memory data;
AaveInterface aave = AaveInterface(aaveProvider.getPool());
data = getBorrowAmounts(userAccount, aave, inputData, data);
data = getSupplyAmounts(userAccount, inputData, data);
// payback borrowed amount;
_PaybackStable(
data._borrowTokens.length,
aave,
data._borrowTokens,
data.stableBorrowAmts,
userAccount
);
_PaybackVariable(
data._borrowTokens.length,
aave,
data._borrowTokens,
data.variableBorrowAmts,
userAccount
);
// transfer atokens to this address;
_TransferAtokensWithCollateral(
data._supplyTokens.length,
aave,
data.aTokens,
data.supplyAmts,
data._supplyTokens,
enableCollateral,
userAccount
);
// borrow assets after migrating position
if (data.convertStable) {
_BorrowVariable(
data._borrowTokens.length,
aave,
data._borrowTokens,
data.totalBorrowAmtsWithFee
);
} else {
_BorrowStable(
data._borrowTokens.length,
aave,
data._borrowTokens,
data.stableBorrowAmtsWithFee
);
_BorrowVariable(
data._borrowTokens.length,
aave,
data._borrowTokens,
data.variableBorrowAmtsWithFee
);
}
_eventName = "LogAaveV3ImportWithCollateral(address,bool,address[],address[],uint256[],uint256[],uint256[],uint256[],bool[])";
_eventParam = abi.encode(
userAccount,
inputData.convertStable,
inputData.supplyTokens,
inputData.borrowTokens,
inputData.flashLoanFees,
data.supplyAmts,
data.stableBorrowAmts,
data.variableBorrowAmts,
enableCollateral
);
}
/**
* @dev Import aave V3 position .
* @notice Import EOA's aave V3 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 importAave(address userAccount, ImportInputData memory inputData)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
(_eventName, _eventParam) = _importAave(userAccount, inputData);
}
/**
* @dev Import aave V3 position (with collateral).
* @notice Import EOA's aave V3 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 enableCollateral The boolean array to enable selected collaterals in the imported position
*/
function importAaveWithCollateral(address userAccount, ImportInputData memory inputData, bool[] memory enableCollateral)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
(_eventName, _eventParam) = _importAaveWithCollateral(userAccount, inputData, enableCollateral);
}
}
contract ConnectV2AaveV3ImportBase is AaveV3ImportResolver {
string public constant name = "Aave-v3-import-v1.1";
}

View File

@ -0,0 +1,64 @@
//SPDX-License-Identifier: MIT
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);
event LogDelegateBorrow(
address token,
uint256 amount,
uint256 rateMode,
address delegateTo,
uint256 getId,
uint256 setId
);
event LogDepositWithoutCollateral(
address token,
uint256 amt,
uint256 getId,
uint256 setId
);
event LogBorrowOnBehalfOf(
address token,
uint256 amt,
uint256 rateMode,
address onBehalfOf,
uint256 getId,
uint256 setId
);
event LogPaybackOnBehalfOf(
address token,
uint256 amt,
uint256 rateMode,
address onBehalfOf,
uint256 getId,
uint256 setId
);
}

View File

@ -0,0 +1,99 @@
//SPDX-License-Identifier: MIT
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(0xe20fCBdBfFC4Dd138cE8b2E6FBb6CB49777ad64D);
/**
* @dev Aave Pool Data Provider
*/
AaveDataProviderInterface internal constant aaveData =
AaveDataProviderInterface(0x2d8A3C5677189723C4cB8873CfC9C8976FDF38Ac);
/**
* @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 OnBehalfOf user's 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 getOnBehalfOfPaybackBalance(address token, uint256 rateMode, address onBehalfOf)
internal
view
returns (uint256)
{
(, uint256 stableDebt, uint256 variableDebt, , , , , , ) = aaveData
.getUserReserveData(token, onBehalfOf);
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)
);
}
/**
* @dev Get debt token address for an asset
* @param token token address of the asset
* @param rateMode Debt type: stable-1, variable-2
*/
function getDTokenAddr(address token, uint256 rateMode)
internal
view
returns(address dToken)
{
if (rateMode == 1) {
(, dToken, ) = aaveData.getReserveTokensAddresses(token);
} else {
(, , dToken) = aaveData.getReserveTokensAddresses(token);
}
}
}

View File

@ -0,0 +1,96 @@
//SPDX-License-Identifier: MIT
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);
}
interface DTokenInterface {
function approveDelegation(address delegatee, uint256 amount) external;
}

View File

@ -0,0 +1,494 @@
//SPDX-License-Identifier: MIT
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, DTokenInterface } from "./interface.sol";
abstract contract AaveResolver is Events, Helpers {
/**
* @dev Deposit ETH/ERC20_Token.
* @notice Deposit a token to Aave v3 for lending / collaterization.
* @param token The address of the token to deposit.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to deposit. (For max: `uint256(-1)`)
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens deposited.
*/
function 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 Deposit ETH/ERC20_Token without collateral
* @notice Deposit a token to Aave v3 without enabling it as collateral.
* @param token The address of the token to deposit.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to deposit. (For max: `uint256(-1)`)
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens deposited.
*/
function depositWithoutCollateral(
address token,
uint256 amt,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
uint256 _amt = getUint(getId, amt);
AaveInterface aave = AaveInterface(aaveProvider.getPool());
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
TokenInterface tokenContract = TokenInterface(_token);
if (isEth) {
_amt = _amt == uint256(-1) ? address(this).balance : _amt;
convertEthToWeth(isEth, tokenContract, _amt);
} else {
_amt = _amt == uint256(-1)
? tokenContract.balanceOf(address(this))
: _amt;
}
approve(tokenContract, address(aave), _amt);
aave.supply(_token, _amt, address(this), referralCode);
if (getCollateralBalance(_token) > 0 && getIsColl(_token)) {
aave.setUserUseReserveAsCollateral(_token, false);
}
setUint(setId, _amt);
_eventName = "LogDepositWithoutCollateral(address,uint256,uint256,uint256)";
_eventParam = abi.encode(token, _amt, getId, setId);
}
/**
* @dev Withdraw ETH/ERC20_Token.
* @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.
* @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 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 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 Borrow ETH/ERC20_Token on behalf of a user.
* @notice Borrow a token using Aave v3 on behalf of a user
* @param token The address of the token to borrow.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
* @param amt The amount of the token to borrow.
* @param rateMode The type of debt. (For Stable: 1, Variable: 2)
* @param onBehalfOf The user who will incur the debt
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens borrowed.
*/
function borrowOnBehalfOf(
address token,
uint256 amt,
uint256 rateMode,
address onBehalfOf,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
uint256 _amt = getUint(getId, amt);
AaveInterface aave = AaveInterface(aaveProvider.getPool());
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
aave.borrow(_token, _amt, rateMode, referralCode, onBehalfOf);
convertWethToEth(isEth, TokenInterface(_token), _amt);
setUint(setId, _amt);
_eventName = "LogBorrowOnBehalfOf(address,uint256,uint256,address,uint256,uint256)";
_eventParam = abi.encode(
token,
_amt,
rateMode,
onBehalfOf,
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 Payback borrowed ETH/ERC20_Token on behalf of a user.
* @notice Payback debt owed on behalf os a user.
* @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 onBehalfOf Address of user who's debt to repay.
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens paid back.
*/
function paybackOnBehalfOf(
address token,
uint256 amt,
uint256 rateMode,
address onBehalfOf,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
uint256 _amt = getUint(getId, amt);
AaveInterface aave = AaveInterface(aaveProvider.getPool());
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
TokenInterface tokenContract = TokenInterface(_token);
_amt = _amt == uint256(-1)
? getOnBehalfOfPaybackBalance(_token, rateMode, onBehalfOf)
: _amt;
if (isEth) convertEthToWeth(isEth, tokenContract, _amt);
approve(tokenContract, address(aave), _amt);
aave.repay(_token, _amt, rateMode, onBehalfOf);
setUint(setId, _amt);
_eventName = "LogPaybackOnBehalfOf(address,uint256,uint256,address,uint256,uint256)";
_eventParam = abi.encode(
token,
_amt,
rateMode,
onBehalfOf,
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++) {
bool isEth = tokens[i] == ethAddr;
address _token = isEth ? wethAddr : 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 Current 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());
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
if (getPaybackBalance(_token, rateMode) > 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
payable
returns (string memory _eventName, bytes memory _eventParam)
{
AaveInterface aave = AaveInterface(aaveProvider.getPool());
aave.setUserEMode(categoryId);
_eventName = "LogSetUserEMode(uint8)";
_eventParam = abi.encode(categoryId);
}
/**
* @dev Approve Delegation
* @notice Gives approval to delegate debt tokens
* @param token The address of token
* @param amount The amount
* @param rateMode The type of debt
* @param delegateTo The address to whom the user is delegating
* @param getId ID to retrieve amt.
* @param setId ID stores the amount of tokens delegated.
*/
function delegateBorrow(
address token,
uint256 amount,
uint256 rateMode,
address delegateTo,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
require(rateMode == 1 || rateMode == 2, "Invalid debt type");
uint256 _amt = getUint(getId, amount);
bool isEth = token == ethAddr;
address _token = isEth ? wethAddr : token;
address _dToken = getDTokenAddr(_token, rateMode);
DTokenInterface(_dToken).approveDelegation(delegateTo, _amt);
setUint(setId, _amt);
_eventName = "LogDelegateBorrow(address,uint256,uint256,address,uint256,uint256)";
_eventParam = abi.encode(
token,
_amt,
rateMode,
delegateTo,
getId,
setId
);
}
}
contract ConnectV2AaveV3Base is AaveResolver {
string public constant name = "AaveV3-v1.0";
}