diff --git a/contracts/protocols/1proto.sol b/contracts/protocols/mainnet/1proto.sol similarity index 100% rename from contracts/protocols/1proto.sol rename to contracts/protocols/mainnet/1proto.sol diff --git a/contracts/protocols/1split.sol b/contracts/protocols/mainnet/1split.sol similarity index 100% rename from contracts/protocols/1split.sol rename to contracts/protocols/mainnet/1split.sol diff --git a/contracts/protocols/aave.sol b/contracts/protocols/mainnet/aave.sol similarity index 100% rename from contracts/protocols/aave.sol rename to contracts/protocols/mainnet/aave.sol diff --git a/contracts/protocols/aave_v2.sol b/contracts/protocols/mainnet/aave_v2.sol similarity index 100% rename from contracts/protocols/aave_v2.sol rename to contracts/protocols/mainnet/aave_v2.sol diff --git a/contracts/protocols/chainlink.sol b/contracts/protocols/mainnet/chainlink.sol similarity index 100% rename from contracts/protocols/chainlink.sol rename to contracts/protocols/mainnet/chainlink.sol diff --git a/contracts/protocols/chainlink_aggregator.sol b/contracts/protocols/mainnet/chainlink_aggregator.sol similarity index 100% rename from contracts/protocols/chainlink_aggregator.sol rename to contracts/protocols/mainnet/chainlink_aggregator.sol diff --git a/contracts/protocols/compound.sol b/contracts/protocols/mainnet/compound.sol similarity index 100% rename from contracts/protocols/compound.sol rename to contracts/protocols/mainnet/compound.sol diff --git a/contracts/protocols/curveGauge.sol b/contracts/protocols/mainnet/curveGauge.sol similarity index 100% rename from contracts/protocols/curveGauge.sol rename to contracts/protocols/mainnet/curveGauge.sol diff --git a/contracts/protocols/curve_3pool.sol b/contracts/protocols/mainnet/curve_3pool.sol similarity index 100% rename from contracts/protocols/curve_3pool.sol rename to contracts/protocols/mainnet/curve_3pool.sol diff --git a/contracts/protocols/curve_sbtc.sol b/contracts/protocols/mainnet/curve_sbtc.sol similarity index 100% rename from contracts/protocols/curve_sbtc.sol rename to contracts/protocols/mainnet/curve_sbtc.sol diff --git a/contracts/protocols/curve_susd.sol b/contracts/protocols/mainnet/curve_susd.sol similarity index 100% rename from contracts/protocols/curve_susd.sol rename to contracts/protocols/mainnet/curve_susd.sol diff --git a/contracts/protocols/curve_vesting.sol b/contracts/protocols/mainnet/curve_vesting.sol similarity index 100% rename from contracts/protocols/curve_vesting.sol rename to contracts/protocols/mainnet/curve_vesting.sol diff --git a/contracts/protocols/curve_y.sol b/contracts/protocols/mainnet/curve_y.sol similarity index 100% rename from contracts/protocols/curve_y.sol rename to contracts/protocols/mainnet/curve_y.sol diff --git a/contracts/protocols/dydx.sol b/contracts/protocols/mainnet/dydx.sol similarity index 100% rename from contracts/protocols/dydx.sol rename to contracts/protocols/mainnet/dydx.sol diff --git a/contracts/protocols/erc20.sol b/contracts/protocols/mainnet/erc20.sol similarity index 100% rename from contracts/protocols/erc20.sol rename to contracts/protocols/mainnet/erc20.sol diff --git a/contracts/protocols/instapool.sol b/contracts/protocols/mainnet/instapool.sol similarity index 100% rename from contracts/protocols/instapool.sol rename to contracts/protocols/mainnet/instapool.sol diff --git a/contracts/protocols/kyber.sol b/contracts/protocols/mainnet/kyber.sol similarity index 100% rename from contracts/protocols/kyber.sol rename to contracts/protocols/mainnet/kyber.sol diff --git a/contracts/protocols/maker.sol b/contracts/protocols/mainnet/maker.sol similarity index 100% rename from contracts/protocols/maker.sol rename to contracts/protocols/mainnet/maker.sol diff --git a/contracts/protocols/oasis.sol b/contracts/protocols/mainnet/oasis.sol similarity index 100% rename from contracts/protocols/oasis.sol rename to contracts/protocols/mainnet/oasis.sol diff --git a/contracts/protocols/reflexer.sol b/contracts/protocols/mainnet/reflexer.sol similarity index 100% rename from contracts/protocols/reflexer.sol rename to contracts/protocols/mainnet/reflexer.sol diff --git a/contracts/protocols/swerve.sol b/contracts/protocols/mainnet/swerve.sol similarity index 100% rename from contracts/protocols/swerve.sol rename to contracts/protocols/mainnet/swerve.sol diff --git a/contracts/protocols/synthetix_staking.sol b/contracts/protocols/mainnet/synthetix_staking.sol similarity index 100% rename from contracts/protocols/synthetix_staking.sol rename to contracts/protocols/mainnet/synthetix_staking.sol diff --git a/contracts/protocols/uniswapV2.sol b/contracts/protocols/mainnet/uniswapV2.sol similarity index 100% rename from contracts/protocols/uniswapV2.sol rename to contracts/protocols/mainnet/uniswapV2.sol diff --git a/contracts/protocols/uniswap_lp.sol b/contracts/protocols/mainnet/uniswap_lp.sol similarity index 100% rename from contracts/protocols/uniswap_lp.sol rename to contracts/protocols/mainnet/uniswap_lp.sol diff --git a/contracts/protocols/polygon/aave_v2.sol b/contracts/protocols/polygon/aave_v2.sol new file mode 100644 index 0000000..f7e989e --- /dev/null +++ b/contracts/protocols/polygon/aave_v2.sol @@ -0,0 +1,336 @@ +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +interface AaveProtocolDataProvider { + 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 getReserveData(address asset) external view returns ( + uint256 availableLiquidity, + uint256 totalStableDebt, + uint256 totalVariableDebt, + uint256 liquidityRate, + uint256 variableBorrowRate, + uint256 stableBorrowRate, + uint256 averageStableBorrowRate, + uint256 liquidityIndex, + uint256 variableBorrowIndex, + uint40 lastUpdateTimestamp + ); + + function getReserveTokensAddresses(address asset) external view returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); +} + +interface AaveLendingPool { + function getUserAccountData(address user) external view returns ( + uint256 totalCollateralETH, + uint256 totalDebtETH, + uint256 availableBorrowsETH, + uint256 currentLiquidationThreshold, + uint256 ltv, + uint256 healthFactor + ); +} + +interface AaveAddressProvider { + function getLendingPool() external view returns (address); + function getPriceOracle() external view returns (address); +} + +interface AavePriceOracle { + 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(uint256); + function getFallbackOracle() external view returns(uint256); +} + +interface AaveIncentivesInterface { + function getRewardsBalance( + address[] calldata assets, + address user + ) external view returns (uint256); +} + +interface ChainLinkInterface { + function latestAnswer() external view returns (int256); + function decimals() 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 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 AaveHelpers is DSMath { + /** + * @dev Return ethereum address + */ + function getEthAddr() internal pure returns (address) { + return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // MATIC Address + } + + /** + * @dev Return Weth address + */ + function getWethAddr() internal pure returns (address) { + return 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270; // polygon mainnet WMATIC Address + } + + /** + * @dev get Aave Provider Address + */ + function getAaveAddressProvider() internal pure returns (address) { + return 0xd05e3E715d945B59290df0ae8eF85c1BdB684744; // polygon mainnet + } + + /** + * @dev get Aave Protocol Data Provider + */ + function getAaveProtocolDataProvider() internal pure returns (address) { + return 0x7551b5D2763519d4e37e8B81929D336De671d46d; // polygon mainnet + } + + /** + * @dev get Chainlink ETH price feed Address + */ + function getChainlinkEthFeed() internal pure returns (address) { + return 0xF9680D99D6C9589e2a93a78A04A279e509205945; // polygon mainnet + } + + /** + * @dev Aave Incentives address + */ + function getAaveIncentivesAddress() internal pure returns (address) { + return 0x357D51124f59836DeD84c8a1730D72B749d8BC23; // polygon mainnet + } + + struct AaveUserTokenData { + uint tokenPriceInEth; + uint tokenPriceInUsd; + uint supplyBalance; + uint stableBorrowBalance; + uint variableBorrowBalance; + uint supplyRate; + uint stableBorrowRate; + uint userStableBorrowRate; + uint variableBorrowRate; + bool isCollateral; + AaveTokenData aaveTokenData; + } + + struct AaveUserData { + uint totalCollateralETH; + uint totalBorrowsETH; + uint availableBorrowsETH; + uint currentLiquidationThreshold; + uint ltv; + uint healthFactor; + uint ethPriceInUsd; + uint pendingRewards; + } + + struct AaveTokenData { + uint ltv; + uint threshold; + uint reserveFactor; + bool usageAsCollEnabled; + bool borrowEnabled; + bool stableBorrowEnabled; + bool isActive; + bool isFrozen; + uint availableLiquidity; + uint totalStableDebt; + uint totalVariableDebt; + } + + struct TokenPrice { + uint priceInEth; + uint priceInUsd; + } + + function getTokensPrices(AaveAddressProvider aaveAddressProvider, address[] memory tokens) + internal view returns(TokenPrice[] memory tokenPrices, uint ethPrice) { + 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 collateralData( + AaveProtocolDataProvider aaveData, + address token + ) internal view returns (AaveTokenData memory aaveTokenData) { + ( + , + aaveTokenData.ltv, + aaveTokenData.threshold, + , + aaveTokenData.reserveFactor, + aaveTokenData.usageAsCollEnabled, + aaveTokenData.borrowEnabled, + aaveTokenData.stableBorrowEnabled, + aaveTokenData.isActive, + aaveTokenData.isFrozen + ) = aaveData.getReserveConfigurationData(token); + } + + function getTokenData( + AaveProtocolDataProvider aaveData, + address user, + address token, + uint tokenPriceInEth, + uint tokenPriceInUsd + ) internal view returns(AaveUserTokenData memory tokenData) { + AaveTokenData memory aaveTokenData = collateralData(aaveData, token); + + ( + tokenData.supplyBalance, + tokenData.stableBorrowBalance, + tokenData.variableBorrowBalance, + ,, + tokenData.userStableBorrowRate, + ,, + tokenData.isCollateral + ) = aaveData.getUserReserveData(token, user); + + ( + aaveTokenData.availableLiquidity, + aaveTokenData.totalStableDebt, + aaveTokenData.totalVariableDebt, + tokenData.supplyRate, + tokenData.variableBorrowRate, + tokenData.stableBorrowRate, + ,,, + ) = aaveData.getReserveData(token); + + tokenData.tokenPriceInEth = tokenPriceInEth; + tokenData.tokenPriceInUsd = tokenPriceInUsd; + tokenData.aaveTokenData = aaveTokenData; + } + + function getPendingRewards(address[] memory _tokens, address user) internal view returns (uint rewards) { + address[] memory _atokens = new address[](_tokens.length); + AaveProtocolDataProvider aaveData = AaveProtocolDataProvider(getAaveProtocolDataProvider()); + for (uint i = 0; i < _tokens.length; i++) { + (_atokens[i],,) = aaveData.getReserveTokensAddresses(_tokens[i]); + } + rewards = AaveIncentivesInterface(getAaveIncentivesAddress()).getRewardsBalance(_atokens, user); + } + + function getUserData(AaveLendingPool aave, address user, uint ethPriceInUsd, address[] memory tokens) + internal view returns (AaveUserData memory userData) { + ( + uint256 totalCollateralETH, + uint256 totalDebtETH, + uint256 availableBorrowsETH, + uint256 currentLiquidationThreshold, + uint256 ltv, + uint256 healthFactor + ) = aave.getUserAccountData(user); + + uint256 pendingRewards = getPendingRewards(tokens, user); + + userData = AaveUserData( + totalCollateralETH, + totalDebtETH, + availableBorrowsETH, + currentLiquidationThreshold, + ltv, + healthFactor, + ethPriceInUsd, + pendingRewards + ); + } +} + +contract Resolver is AaveHelpers { + function getPosition(address user, address[] memory tokens) public view returns(AaveUserTokenData[] memory, AaveUserData memory) { + AaveAddressProvider addrProvider = AaveAddressProvider(getAaveAddressProvider()); + uint length = tokens.length; + address[] memory _tokens = new address[](length); + + for (uint i = 0; i < length; i++) { + _tokens[i] = tokens[i] == getEthAddr() ? getWethAddr() : tokens[i]; + } + + AaveUserTokenData[] memory tokensData = new AaveUserTokenData[](length); + (TokenPrice[] memory tokenPrices, uint ethPrice) = getTokensPrices(addrProvider, _tokens); + + for (uint i = 0; i < length; i++) { + tokensData[i] = getTokenData( + AaveProtocolDataProvider(getAaveProtocolDataProvider()), + user, + _tokens[i], + tokenPrices[i].priceInEth, + tokenPrices[i].priceInUsd + ); + } + + return (tokensData, getUserData(AaveLendingPool(addrProvider.getLendingPool()), user, ethPrice, _tokens)); + } +} + +contract InstaAaveV2Resolver is Resolver { + string public constant name = "AaveV2-Resolver-v1.5"; +}