From 2ac476c48b1a1ff17e62222ed1dda59c96758531 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 2 Mar 2021 15:51:27 +0530 Subject: [PATCH] Updated Aave power resolvers --- contracts/powerResolver/aave.sol | 98 ++++++++++++++++++-- contracts/powerResolver/aave_v2.sol | 139 +++++++++++++++++++++++++++- 2 files changed, 222 insertions(+), 15 deletions(-) diff --git a/contracts/powerResolver/aave.sol b/contracts/powerResolver/aave.sol index 5cc0b63..211ae6c 100644 --- a/contracts/powerResolver/aave.sol +++ b/contracts/powerResolver/aave.sol @@ -29,6 +29,13 @@ interface AaveInterface { interface AaveProviderInterface { function getLendingPool() external view returns (address); + function getLendingPoolCore() external view returns (address); + function getPriceOracle() external view returns (address); +} + +interface AaveCoreInterface { + function getReserveATokenAddress(address _reserve) external view returns (address); + function getUserBorrowBalances(address _reserve, address _user) external view returns (uint256, uint256, uint256); } interface ChainLinkInterface { @@ -36,7 +43,54 @@ interface ChainLinkInterface { function decimals() external view returns (uint256); } -contract Helpers { +interface ATokenInterface { + function balanceOf(address _user) external view returns(uint256); +} + +interface AavePriceInterface { + function getAssetPrice(address _asset) external view returns (uint256); + function getAssetsPrices(address[] calldata _assets) external view returns(uint256[] memory); + function getSourceOfAsset(address _asset) external view returns(address); + function getFallbackOracle() external view returns(address); +} + +contract DSMath { + + function add(uint x, uint y) internal pure returns (uint z) { + require((z = x + y) >= x, "math-not-safe"); + } + + function sub(uint x, uint y) internal pure returns (uint z) { + z = x - y <= x ? x - y : 0; + } + + function mul(uint x, uint y) internal pure returns (uint z) { + require(y == 0 || (z = x * y) / y == x, "math-not-safe"); + } + + uint constant WAD = 10 ** 18; + uint constant RAY = 10 ** 27; + + function rmul(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, y), RAY / 2) / RAY; + } + + function wmul(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, y), WAD / 2) / WAD; + } + + function rdiv(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, RAY), y / 2) / y; + } + + function wdiv(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, WAD), y / 2) / y; + } + +} + + +contract Helpers is DSMath { struct AaveData { uint collateral; @@ -67,19 +121,41 @@ contract Helpers { return 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419; //mainnet // return 0x9326BFA02ADD2366b30bacB125260Af641031331; //kovan } + + + struct TokenPrice { + uint priceInEth; + uint priceInUsd; + } + } contract InstaAaveV1PowerResolver is Helpers { function getEthPrice() public view returns (uint ethPrice) { ethPrice = uint(ChainLinkInterface(getChainlinkEthFeed()).latestAnswer()); } + + function getTokensPrices(address[] memory tokens) + public view returns(TokenPrice[] memory tokenPrices, uint ethPrice) { + AaveProviderInterface AaveProvider = AaveProviderInterface(getAaveProviderAddress()); + uint[] memory _tokenPrices = AavePriceInterface(AaveProvider.getPriceOracle()).getAssetsPrices(tokens); + ethPrice = uint(ChainLinkInterface(getChainlinkEthFeed()).latestAnswer()); + tokenPrices = new TokenPrice[](_tokenPrices.length); + for (uint i = 0; i < _tokenPrices.length; i++) { + tokenPrices[i] = TokenPrice( + _tokenPrices[i], + wmul(_tokenPrices[i], uint(ethPrice) * 10 ** 10) + ); + } + } - function getAaveDataByReserve(address[] memory owners, address reserve, AaveInterface aave) public view returns (AaveData[] memory) { + function getAaveDataByReserve(address[] memory owners, address reserve, address atoken, AaveCoreInterface aaveCore) public view returns (AaveData[] memory) { AaveData[] memory tokensData = new AaveData[](owners.length); + ATokenInterface atokenContract = ATokenInterface(atoken); for (uint i = 0; i < owners.length; i++) { - (uint collateral, uint debt,,,,,,,,) = aave.getUserReserveData(reserve, owners[i]); + (,uint debt,) = aaveCore.getUserBorrowBalances(reserve, owners[i]); tokensData[i] = AaveData( - collateral, + atokenContract.balanceOf(owners[i]), debt ); } @@ -87,20 +163,22 @@ contract InstaAaveV1PowerResolver is Helpers { return tokensData; } - function getPositionByAddress( - address[] memory owners, - address[] memory reserves + function getPositionByReserves( + address[] calldata owners, + address[] calldata reserves, + address[] calldata atokens ) - public + external view returns (datas[] memory) { AaveProviderInterface AaveProvider = AaveProviderInterface(getAaveProviderAddress()); - AaveInterface aave = AaveInterface(AaveProvider.getLendingPool()); + AaveCoreInterface aaveCore = AaveCoreInterface(AaveProvider.getLendingPoolCore()); + // AaveInterface aave = AaveInterface(AaveProvider.getLendingPool()); datas[] memory _data = new datas[](reserves.length); for (uint i = 0; i < reserves.length; i++) { _data[i] = datas( - getAaveDataByReserve(owners, reserves[i], aave) + getAaveDataByReserve(owners, reserves[i], atokens[i], aaveCore) ); } return _data; diff --git a/contracts/powerResolver/aave_v2.sol b/contracts/powerResolver/aave_v2.sol index d9484db..704f4c5 100644 --- a/contracts/powerResolver/aave_v2.sol +++ b/contracts/powerResolver/aave_v2.sol @@ -13,6 +13,12 @@ interface AaveProtocolDataProvider { uint40 stableRateLastUpdated, bool usageAsCollateralEnabled ); + + function getReserveTokensAddresses(address _asset) external view returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); } interface AaveLendingPool { @@ -36,9 +42,42 @@ interface ChainLinkInterface { function decimals() external view returns (uint256); } -contract Helpers { +interface AavePriceOracle { + function getAssetsPrices(address[] calldata _assets) external view returns(uint256[] memory); +} + +interface ATokenInterface { + function balanceOf(address _user) external view returns(uint256); +} + +contract DSMath { + + function add(uint x, uint y) internal pure returns (uint z) { + require((z = x + y) >= x, "math-not-safe"); + } + + function mul(uint x, uint y) internal pure returns (uint z) { + require(y == 0 || (z = x * y) / y == x, "math-not-safe"); + } + + uint constant WAD = 10 ** 18; + + function wmul(uint x, uint y) internal pure returns (uint z) { + z = add(mul(x, y), WAD / 2) / WAD; + } +} + + +contract Helpers is DSMath { struct AaveData { + uint collateral; + uint stableDebt; + uint variableDebt; + } + + + struct AaveEthData { uint collateral; uint debt; } @@ -52,6 +91,18 @@ contract Helpers { AaveData[] tokensData; } + struct AtokenAddress { + address token; + address atoken; + address stableDebtToken; + address variableDebtToken; + } + + struct TokenPrice { + uint priceInEth; + uint priceInUsd; + } + /** * @dev get Aave Provider Address */ @@ -60,6 +111,12 @@ contract Helpers { // return 0x652B2937Efd0B5beA1c8d54293FC1289672AFC6b; // Kovan } + + function getAaveProtocolDataProvider() internal pure returns (address) { + return 0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d; // Mainnet + // return 0x744C1aaA95232EeF8A9994C4E0b3a89659D9AB79; // Kovan + } + /** * @dev get Chainlink ETH price feed Address */ @@ -68,26 +125,98 @@ contract Helpers { // return 0x9326BFA02ADD2366b30bacB125260Af641031331; //kovan } + /** + * @dev Return ether address + */ + function getEthAddr() internal pure returns (address) { + return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // ETH Address + } + + /** + * @dev Return Weth address + */ + function getWethAddr() internal pure returns (address) { + return 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // Mainnet WETH Address + // return 0xd0A1E359811322d97991E03f863a0C30C2cF029C; // Kovan WETH Address + } + } -contract Resolver is Helpers { +contract InstaAaveV2PowerResolver is Helpers { + function getAtokenAddresses(address[] calldata reserves) external view returns (AtokenAddress[] memory atokenAddress) { + AaveProtocolDataProvider aaveProtocolDataProvider = AaveProtocolDataProvider(getAaveProtocolDataProvider()); + atokenAddress = new AtokenAddress[](reserves.length); + for (uint i = 0; i < reserves.length; i++) { + address _reserve = reserves[i] == getEthAddr() ? getWethAddr() : reserves[i]; + (address atoken, address stableDebtToken, address variableDebtToken) = aaveProtocolDataProvider.getReserveTokensAddresses(_reserve); + atokenAddress[i] = AtokenAddress(_reserve, atoken, stableDebtToken, variableDebtToken); + } + } + + function getTokensPrices(address[] calldata tokens) + external view returns(TokenPrice[] memory tokenPrices, uint ethPrice) { + AaveAddressProvider aaveAddressProvider = AaveAddressProvider(getAaveAddressProvider()); + uint[] memory _tokenPrices = AavePriceOracle(aaveAddressProvider.getPriceOracle()).getAssetsPrices(tokens); + ethPrice = uint(ChainLinkInterface(getChainlinkEthFeed()).latestAnswer()); + tokenPrices = new TokenPrice[](_tokenPrices.length); + for (uint i = 0; i < _tokenPrices.length; i++) { + tokenPrices[i] = TokenPrice( + _tokenPrices[i], + wmul(_tokenPrices[i], uint(ethPrice) * 10 ** 10) + ); + } + } + function getEthPrice() public view returns (uint ethPrice) { ethPrice = uint(ChainLinkInterface(getChainlinkEthFeed()).latestAnswer()); } + function getAaveDataByReserve(address[] memory owners, AtokenAddress memory atokenAddress) public view returns (AaveData[] memory) { + AaveData[] memory tokensData = new AaveData[](owners.length); + ATokenInterface atokenContract = ATokenInterface(atokenAddress.atoken); + ATokenInterface stableDebtTokenContract = ATokenInterface(atokenAddress.stableDebtToken); + ATokenInterface variableDebtContract = ATokenInterface(atokenAddress.variableDebtToken); + for (uint i = 0; i < owners.length; i++) { + tokensData[i] = AaveData( + atokenContract.balanceOf(owners[i]), + stableDebtTokenContract.balanceOf(owners[i]), + variableDebtContract.balanceOf(owners[i]) + ); + } + + return tokensData; + } + + function getPositionByReserves( + address[] calldata owners, + AtokenAddress[] calldata atokenAddress + ) + external + view + returns (datas[] memory) + { + datas[] memory _data = new datas[](atokenAddress.length); + for (uint i = 0; i < atokenAddress.length; i++) { + _data[i] = datas( + getAaveDataByReserve(owners, atokenAddress[i]) + ); + } + return _data; + } + function getPositionByAddress( address[] memory owners ) public view - returns (AaveData[] memory tokensData) + returns (AaveEthData[] memory tokensData) { AaveAddressProvider addrProvider = AaveAddressProvider(getAaveAddressProvider()); AaveLendingPool aave = AaveLendingPool(addrProvider.getLendingPool()); - tokensData = new AaveData[](owners.length); + tokensData = new AaveEthData[](owners.length); for (uint i = 0; i < owners.length; i++) { (uint256 collateral,uint256 debt,,,,) = aave.getUserAccountData(owners[i]); - tokensData[i] = AaveData( + tokensData[i] = AaveEthData( collateral, debt );