diff --git a/contracts/misc/UiIncentiveDataProviderV2.sol b/contracts/misc/UiIncentiveDataProviderV2.sol new file mode 100644 index 00000000..56b3c0b8 --- /dev/null +++ b/contracts/misc/UiIncentiveDataProviderV2.sol @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; +import {IAaveIncentivesController} from '../interfaces/IAaveIncentivesController.sol'; +import {IUiIncentiveDataProviderV2} from './interfaces/IUiIncentiveDataProviderV2.sol'; +import {ILendingPool} from '../interfaces/ILendingPool.sol'; +import {IAToken} from '../interfaces/IAToken.sol'; +import {IVariableDebtToken} from '../interfaces/IVariableDebtToken.sol'; +import {IStableDebtToken} from '../interfaces/IStableDebtToken.sol'; +import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol'; +import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; +import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; + +contract UiIncentiveDataProviderV2 is IUiIncentiveDataProviderV2 { + using UserConfiguration for DataTypes.UserConfigurationMap; + + constructor() public {} + + function getFullReservesIncentiveData(ILendingPoolAddressesProvider provider, address user) + external + view + override + returns (AggregatedReserveIncentiveData[] memory, UserReserveIncentiveData[] memory) + { + return (_getReservesIncentivesData(provider), _getUserReservesIncentivesData(provider, user)); + } + + function getReservesIncentivesData(ILendingPoolAddressesProvider provider) + external + view + override + returns (AggregatedReserveIncentiveData[] memory) + { + return _getReservesIncentivesData(provider); + } + + function _getReservesIncentivesData(ILendingPoolAddressesProvider provider) + private + view + returns (AggregatedReserveIncentiveData[] memory) + { + ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); + address[] memory reserves = lendingPool.getReservesList(); + AggregatedReserveIncentiveData[] memory reservesIncentiveData = + new AggregatedReserveIncentiveData[](reserves.length); + + for (uint256 i = 0; i < reserves.length; i++) { + AggregatedReserveIncentiveData memory reserveIncentiveData = reservesIncentiveData[i]; + reserveIncentiveData.underlyingAsset = reserves[i]; + + DataTypes.ReserveData memory baseData = lendingPool.getReserveData(reserves[i]); + + try IStableDebtToken(baseData.aTokenAddress).getIncentivesController() returns (IAaveIncentivesController aTokenIncentiveController) { + if (address(aTokenIncentiveController) != address(0)) { + address aRewardToken = aTokenIncentiveController.REWARD_TOKEN(); + + try aTokenIncentiveController.getAssetData(baseData.aTokenAddress) returns ( + uint256 aTokenIncentivesIndex, + uint256 aEmissionPerSecond, + uint256 aIncentivesLastUpdateTimestamp + ) { + reserveIncentiveData.aIncentiveData = IncentiveData( + aEmissionPerSecond, + aIncentivesLastUpdateTimestamp, + aTokenIncentivesIndex, + aTokenIncentiveController.DISTRIBUTION_END(), + baseData.aTokenAddress, + aRewardToken, + address(aTokenIncentiveController), + IERC20Detailed(aRewardToken).decimals(), + aTokenIncentiveController.PRECISION() + ); + } catch (bytes memory /*lowLevelData*/) { + ( + uint256 aEmissionPerSecond, + uint256 aIncentivesLastUpdateTimestamp, + uint256 aTokenIncentivesIndex + ) = aTokenIncentiveController.assets(baseData.aTokenAddress); + + reserveIncentiveData.aIncentiveData = IncentiveData( + aEmissionPerSecond, + aIncentivesLastUpdateTimestamp, + aTokenIncentivesIndex, + aTokenIncentiveController.DISTRIBUTION_END(), + baseData.aTokenAddress, + aRewardToken, + address(aTokenIncentiveController), + IERC20Detailed(aRewardToken).decimals(), + aTokenIncentiveController.PRECISION() + ); + } + } + } catch(bytes memory /*lowLevelData*/) { + // Will not get here + } + + try IStableDebtToken(baseData.stableDebtTokenAddress).getIncentivesController() returns (IAaveIncentivesController sTokenIncentiveController) { + if (address(sTokenIncentiveController) != address(0)) { + + address sRewardToken = sTokenIncentiveController.REWARD_TOKEN(); + try sTokenIncentiveController.getAssetData(baseData.stableDebtTokenAddress) returns ( + uint256 sTokenIncentivesIndex, + uint256 sEmissionPerSecond, + uint256 sIncentivesLastUpdateTimestamp + ) { + reserveIncentiveData.sIncentiveData = IncentiveData( + sEmissionPerSecond, + sIncentivesLastUpdateTimestamp, + sTokenIncentivesIndex, + sTokenIncentiveController.DISTRIBUTION_END(), + baseData.stableDebtTokenAddress, + sRewardToken, + address(sTokenIncentiveController), + IERC20Detailed(sRewardToken).decimals(), + sTokenIncentiveController.PRECISION() + ); + } catch (bytes memory /*lowLevelData*/) { + ( + uint256 sEmissionPerSecond, + uint256 sIncentivesLastUpdateTimestamp, + uint256 sTokenIncentivesIndex + ) = sTokenIncentiveController.assets(baseData.stableDebtTokenAddress); + + reserveIncentiveData.sIncentiveData = IncentiveData( + sEmissionPerSecond, + sIncentivesLastUpdateTimestamp, + sTokenIncentivesIndex, + sTokenIncentiveController.DISTRIBUTION_END(), + baseData.stableDebtTokenAddress, + sRewardToken, + address(sTokenIncentiveController), + IERC20Detailed(sRewardToken).decimals(), + sTokenIncentiveController.PRECISION() + ); + } + } + } catch(bytes memory /*lowLevelData*/) { + // Will not get here + } + + try IStableDebtToken(baseData.variableDebtTokenAddress).getIncentivesController() returns (IAaveIncentivesController vTokenIncentiveController) { + if (address(vTokenIncentiveController) != address(0)) { + address vRewardToken = vTokenIncentiveController.REWARD_TOKEN(); + + try vTokenIncentiveController.getAssetData(baseData.variableDebtTokenAddress) returns ( + uint256 vTokenIncentivesIndex, + uint256 vEmissionPerSecond, + uint256 vIncentivesLastUpdateTimestamp + ) { + reserveIncentiveData.vIncentiveData = IncentiveData( + vEmissionPerSecond, + vIncentivesLastUpdateTimestamp, + vTokenIncentivesIndex, + vTokenIncentiveController.DISTRIBUTION_END(), + baseData.variableDebtTokenAddress, + vRewardToken, + address(vTokenIncentiveController), + IERC20Detailed(vRewardToken).decimals(), + vTokenIncentiveController.PRECISION() + ); + } catch (bytes memory /*lowLevelData*/) { + ( + uint256 vEmissionPerSecond, + uint256 vIncentivesLastUpdateTimestamp, + uint256 vTokenIncentivesIndex + ) = vTokenIncentiveController.assets(baseData.variableDebtTokenAddress); + + reserveIncentiveData.vIncentiveData = IncentiveData( + vEmissionPerSecond, + vIncentivesLastUpdateTimestamp, + vTokenIncentivesIndex, + vTokenIncentiveController.DISTRIBUTION_END(), + baseData.variableDebtTokenAddress, + vRewardToken, + address(vTokenIncentiveController), + IERC20Detailed(vRewardToken).decimals(), + vTokenIncentiveController.PRECISION() + ); + } + } + } catch(bytes memory /*lowLevelData*/) { + // Will not get here + } + } + return (reservesIncentiveData); + } + + function getUserReservesIncentivesData(ILendingPoolAddressesProvider provider, address user) + external + view + override + returns (UserReserveIncentiveData[] memory) + { + return _getUserReservesIncentivesData(provider, user); + } + + function _getUserReservesIncentivesData(ILendingPoolAddressesProvider provider, address user) + private + view + returns (UserReserveIncentiveData[] memory) + { + ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); + address[] memory reserves = lendingPool.getReservesList(); + + UserReserveIncentiveData[] memory userReservesIncentivesData = + new UserReserveIncentiveData[](user != address(0) ? reserves.length : 0); + + for (uint256 i = 0; i < reserves.length; i++) { + DataTypes.ReserveData memory baseData = lendingPool.getReserveData(reserves[i]); + + // user reserve data + userReservesIncentivesData[i].underlyingAsset = reserves[i]; + + IUiIncentiveDataProviderV2.UserIncentiveData memory aUserIncentiveData; + + try IAToken(baseData.aTokenAddress).getIncentivesController() returns (IAaveIncentivesController aTokenIncentiveController) { + if (address(aTokenIncentiveController) != address(0)) { + address aRewardToken = aTokenIncentiveController.REWARD_TOKEN(); + aUserIncentiveData.tokenincentivesUserIndex = aTokenIncentiveController.getUserAssetData( + user, + baseData.aTokenAddress + ); + aUserIncentiveData.userUnclaimedRewards = aTokenIncentiveController.getUserUnclaimedRewards( + user + ); + aUserIncentiveData.tokenAddress = baseData.aTokenAddress; + aUserIncentiveData.rewardTokenAddress = aRewardToken; + aUserIncentiveData.incentiveControllerAddress = address(aTokenIncentiveController); + aUserIncentiveData.rewardTokenDecimals = IERC20Detailed(aRewardToken).decimals(); + } + } catch (bytes memory /*lowLevelData*/) { + + } + + userReservesIncentivesData[i].aTokenIncentivesUserData = aUserIncentiveData; + + UserIncentiveData memory vUserIncentiveData; + + try IVariableDebtToken(baseData.variableDebtTokenAddress).getIncentivesController() returns(IAaveIncentivesController vTokenIncentiveController) { + if (address(vTokenIncentiveController) != address(0)) { + address vRewardToken = vTokenIncentiveController.REWARD_TOKEN(); + vUserIncentiveData.tokenincentivesUserIndex = vTokenIncentiveController.getUserAssetData( + user, + baseData.variableDebtTokenAddress + ); + vUserIncentiveData.userUnclaimedRewards = vTokenIncentiveController.getUserUnclaimedRewards( + user + ); + vUserIncentiveData.tokenAddress = baseData.variableDebtTokenAddress; + vUserIncentiveData.rewardTokenAddress = vRewardToken; + vUserIncentiveData.incentiveControllerAddress = address(vTokenIncentiveController); + vUserIncentiveData.rewardTokenDecimals = IERC20Detailed(vRewardToken).decimals(); + } + } catch (bytes memory /*lowLevelData*/) { + + } + + userReservesIncentivesData[i].vTokenIncentivesUserData = vUserIncentiveData; + + UserIncentiveData memory sUserIncentiveData; + + try IStableDebtToken(baseData.stableDebtTokenAddress).getIncentivesController() returns (IAaveIncentivesController sTokenIncentiveController) { + if (address(sTokenIncentiveController) != address(0)) { + address sRewardToken = sTokenIncentiveController.REWARD_TOKEN(); + sUserIncentiveData.tokenincentivesUserIndex = sTokenIncentiveController.getUserAssetData( + user, + baseData.stableDebtTokenAddress + ); + sUserIncentiveData.userUnclaimedRewards = sTokenIncentiveController.getUserUnclaimedRewards( + user + ); + sUserIncentiveData.tokenAddress = baseData.stableDebtTokenAddress; + sUserIncentiveData.rewardTokenAddress = sRewardToken; + sUserIncentiveData.incentiveControllerAddress = address(sTokenIncentiveController); + sUserIncentiveData.rewardTokenDecimals = IERC20Detailed(sRewardToken).decimals(); + } + } catch (bytes memory /*lowLevelData*/) { + + } + + userReservesIncentivesData[i].sTokenIncentivesUserData = sUserIncentiveData; + } + + return (userReservesIncentivesData); + } +} \ No newline at end of file diff --git a/contracts/misc/UiIncentiveDataProviderV2V3.sol b/contracts/misc/UiIncentiveDataProviderV2V3.sol new file mode 100644 index 00000000..5c2dff1a --- /dev/null +++ b/contracts/misc/UiIncentiveDataProviderV2V3.sol @@ -0,0 +1,398 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; +import {IAaveIncentivesController} from '../interfaces/IAaveIncentivesController.sol'; +import {IUiIncentiveDataProviderV3} from './interfaces/IUiIncentiveDataProviderV3.sol'; +import {ILendingPool} from '../interfaces/ILendingPool.sol'; +import {IAToken} from '../interfaces/IAToken.sol'; +import {IVariableDebtToken} from '../interfaces/IVariableDebtToken.sol'; +import {IStableDebtToken} from '../interfaces/IStableDebtToken.sol'; +import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol'; +import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; +import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; +import {IERC20DetailedBytes} from './interfaces/IERC20DetailedBytes.sol'; + +contract UiIncentiveDataProviderV2V3 is IUiIncentiveDataProviderV3 { + using UserConfiguration for DataTypes.UserConfigurationMap; + + address public constant MKRAddress = 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2; + + constructor() public {} + + function getFullReservesIncentiveData(ILendingPoolAddressesProvider provider, address user) + external + view + override + returns (AggregatedReserveIncentiveData[] memory, UserReserveIncentiveData[] memory) + { + return (_getReservesIncentivesData(provider), _getUserReservesIncentivesData(provider, user)); + } + + function getReservesIncentivesData(ILendingPoolAddressesProvider provider) + external + view + override + returns (AggregatedReserveIncentiveData[] memory) + { + return _getReservesIncentivesData(provider); + } + + function _getReservesIncentivesData(ILendingPoolAddressesProvider provider) + private + view + returns (AggregatedReserveIncentiveData[] memory) + { + ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); + address[] memory reserves = lendingPool.getReservesList(); + AggregatedReserveIncentiveData[] + memory reservesIncentiveData = new AggregatedReserveIncentiveData[](reserves.length); + + for (uint256 i = 0; i < reserves.length; i++) { + AggregatedReserveIncentiveData memory reserveIncentiveData = reservesIncentiveData[i]; + reserveIncentiveData.underlyingAsset = reserves[i]; + + DataTypes.ReserveData memory baseData = lendingPool.getReserveData(reserves[i]); + + try IAToken(baseData.aTokenAddress).getIncentivesController() returns ( + IAaveIncentivesController aTokenIncentiveController + ) { + RewardInfo[] memory aRewardsInformation = new RewardInfo[](1); + if (address(aTokenIncentiveController) != address(0)) { + address aRewardToken = aTokenIncentiveController.REWARD_TOKEN(); + + try aTokenIncentiveController.getAssetData(baseData.aTokenAddress) returns ( + uint256 aTokenIncentivesIndex, + uint256 aEmissionPerSecond, + uint256 aIncentivesLastUpdateTimestamp + ) { + + aRewardsInformation[0] = RewardInfo( + getSymbol(aRewardToken), + aRewardToken, + address(0), + aEmissionPerSecond, + aIncentivesLastUpdateTimestamp, + aTokenIncentivesIndex, + aTokenIncentiveController.DISTRIBUTION_END(), + 0, + IERC20Detailed(aRewardToken).decimals(), + aTokenIncentiveController.PRECISION(), + 0 + ); + reserveIncentiveData.aIncentiveData = IncentiveData( + baseData.aTokenAddress, + address(aTokenIncentiveController), + aRewardsInformation + ); + } catch ( + bytes memory /*lowLevelData*/ + ) { + ( + uint256 aEmissionPerSecond, + uint256 aIncentivesLastUpdateTimestamp, + uint256 aTokenIncentivesIndex + ) = aTokenIncentiveController.assets(baseData.aTokenAddress); + aRewardsInformation[0] = RewardInfo( + getSymbol(aRewardToken), + aRewardToken, + address(0), + aEmissionPerSecond, + aIncentivesLastUpdateTimestamp, + aTokenIncentivesIndex, + aTokenIncentiveController.DISTRIBUTION_END(), + 0, + IERC20Detailed(aRewardToken).decimals(), + aTokenIncentiveController.PRECISION(), + 0 + ); + + reserveIncentiveData.aIncentiveData = IncentiveData( + baseData.aTokenAddress, + address(aTokenIncentiveController), + aRewardsInformation + ); + } + } + } catch ( + bytes memory /*lowLevelData*/ + ) { + // Will not get here + } + + try IStableDebtToken(baseData.stableDebtTokenAddress).getIncentivesController() returns ( + IAaveIncentivesController sTokenIncentiveController + ) { + RewardInfo[] memory sRewardsInformation = new RewardInfo[](1); + if (address(sTokenIncentiveController) != address(0)) { + address sRewardToken = sTokenIncentiveController.REWARD_TOKEN(); + try sTokenIncentiveController.getAssetData(baseData.stableDebtTokenAddress) returns ( + uint256 sTokenIncentivesIndex, + uint256 sEmissionPerSecond, + uint256 sIncentivesLastUpdateTimestamp + ) { + sRewardsInformation[0] = RewardInfo( + getSymbol(sRewardToken), + sRewardToken, + address(0), + sEmissionPerSecond, + sIncentivesLastUpdateTimestamp, + sTokenIncentivesIndex, + sTokenIncentiveController.DISTRIBUTION_END(), + 0, + IERC20Detailed(sRewardToken).decimals(), + sTokenIncentiveController.PRECISION(), + 0 + ); + + reserveIncentiveData.sIncentiveData = IncentiveData( + baseData.stableDebtTokenAddress, + address(sTokenIncentiveController), + sRewardsInformation + ); + } catch ( + bytes memory /*lowLevelData*/ + ) { + ( + uint256 sEmissionPerSecond, + uint256 sIncentivesLastUpdateTimestamp, + uint256 sTokenIncentivesIndex + ) = sTokenIncentiveController.assets(baseData.stableDebtTokenAddress); + + sRewardsInformation[0] = RewardInfo( + getSymbol(sRewardToken), + sRewardToken, + address(0), + sEmissionPerSecond, + sIncentivesLastUpdateTimestamp, + sTokenIncentivesIndex, + sTokenIncentiveController.DISTRIBUTION_END(), + 0, + IERC20Detailed(sRewardToken).decimals(), + sTokenIncentiveController.PRECISION(), + 0 + ); + + reserveIncentiveData.sIncentiveData = IncentiveData( + baseData.stableDebtTokenAddress, + address(sTokenIncentiveController), + sRewardsInformation + ); + } + } + } catch ( + bytes memory /*lowLevelData*/ + ) { + // Will not get here + } + + try IVariableDebtToken(baseData.variableDebtTokenAddress).getIncentivesController() returns ( + IAaveIncentivesController vTokenIncentiveController + ) { + RewardInfo[] memory vRewardsInformation = new RewardInfo[](1); + if (address(vTokenIncentiveController) != address(0)) { + address vRewardToken = vTokenIncentiveController.REWARD_TOKEN(); + + try vTokenIncentiveController.getAssetData(baseData.variableDebtTokenAddress) returns ( + uint256 vTokenIncentivesIndex, + uint256 vEmissionPerSecond, + uint256 vIncentivesLastUpdateTimestamp + ) { + vRewardsInformation[0] = RewardInfo( + getSymbol(vRewardToken), + vRewardToken, + address(0), + vEmissionPerSecond, + vIncentivesLastUpdateTimestamp, + vTokenIncentivesIndex, + vTokenIncentiveController.DISTRIBUTION_END(), + 0, + IERC20Detailed(vRewardToken).decimals(), + vTokenIncentiveController.PRECISION(), + 0 + ); + + reserveIncentiveData.vIncentiveData = IncentiveData( + baseData.variableDebtTokenAddress, + address(vTokenIncentiveController), + vRewardsInformation + ); + } catch ( + bytes memory /*lowLevelData*/ + ) { + ( + uint256 vEmissionPerSecond, + uint256 vIncentivesLastUpdateTimestamp, + uint256 vTokenIncentivesIndex + ) = vTokenIncentiveController.assets(baseData.variableDebtTokenAddress); + + vRewardsInformation[0] = RewardInfo( + getSymbol(vRewardToken), + vRewardToken, + address(0), + vEmissionPerSecond, + vIncentivesLastUpdateTimestamp, + vTokenIncentivesIndex, + vTokenIncentiveController.DISTRIBUTION_END(), + 0, + IERC20Detailed(vRewardToken).decimals(), + vTokenIncentiveController.PRECISION(), + 0 + ); + + reserveIncentiveData.vIncentiveData = IncentiveData( + baseData.variableDebtTokenAddress, + address(vTokenIncentiveController), + vRewardsInformation + ); + } + } + } catch ( + bytes memory /*lowLevelData*/ + ) { + // Will not get here + } + } + return (reservesIncentiveData); + } + + function getUserReservesIncentivesData(ILendingPoolAddressesProvider provider, address user) + external + view + override + returns (UserReserveIncentiveData[] memory) + { + return _getUserReservesIncentivesData(provider, user); + } + + function _getUserReservesIncentivesData(ILendingPoolAddressesProvider provider, address user) + private + view + returns (UserReserveIncentiveData[] memory) + { + ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); + address[] memory reserves = lendingPool.getReservesList(); + + UserReserveIncentiveData[] memory userReservesIncentivesData = new UserReserveIncentiveData[]( + user != address(0) ? reserves.length : 0 + ); + + for (uint256 i = 0; i < reserves.length; i++) { + DataTypes.ReserveData memory baseData = lendingPool.getReserveData(reserves[i]); + + // user reserve data + userReservesIncentivesData[i].underlyingAsset = reserves[i]; + + try IAToken(baseData.aTokenAddress).getIncentivesController() returns ( + IAaveIncentivesController aTokenIncentiveController + ) { + if (address(aTokenIncentiveController) != address(0)) { + UserRewardInfo[] memory aUserRewardsInformation = new UserRewardInfo[](1); + + address aRewardToken = aTokenIncentiveController.REWARD_TOKEN(); + + aUserRewardsInformation[0] = UserRewardInfo( + getSymbol(aRewardToken), + address(0), + aRewardToken, + aTokenIncentiveController.getUserUnclaimedRewards(user), + aTokenIncentiveController.getUserAssetData(user, baseData.aTokenAddress), + 0, + 0, + IERC20Detailed(aRewardToken).decimals() + ); + + userReservesIncentivesData[i].aTokenIncentivesUserData = UserIncentiveData( + baseData.aTokenAddress, + address(aTokenIncentiveController), + aUserRewardsInformation + ); + } + } catch ( + bytes memory /*lowLevelData*/ + ) {} + + try IVariableDebtToken(baseData.variableDebtTokenAddress).getIncentivesController() returns ( + IAaveIncentivesController vTokenIncentiveController + ) { + if (address(vTokenIncentiveController) != address(0)) { + UserRewardInfo[] memory vUserRewardsInformation = new UserRewardInfo[](1); + + address vRewardToken = vTokenIncentiveController.REWARD_TOKEN(); + + vUserRewardsInformation[0] = UserRewardInfo( + getSymbol(vRewardToken), + address(0), + vRewardToken, + vTokenIncentiveController.getUserUnclaimedRewards(user), + vTokenIncentiveController.getUserAssetData(user, baseData.variableDebtTokenAddress), + 0, + 0, + IERC20Detailed(vRewardToken).decimals() + ); + + userReservesIncentivesData[i].vTokenIncentivesUserData = UserIncentiveData( + baseData.variableDebtTokenAddress, + address(vTokenIncentiveController), + vUserRewardsInformation + ); + } + } catch ( + bytes memory /*lowLevelData*/ + ) {} + + try IStableDebtToken(baseData.stableDebtTokenAddress).getIncentivesController() returns ( + IAaveIncentivesController sTokenIncentiveController + ) { + if (address(sTokenIncentiveController) != address(0)) { + UserRewardInfo[] memory sUserRewardsInformation = new UserRewardInfo[](1); + + address sRewardToken = sTokenIncentiveController.REWARD_TOKEN(); + + sUserRewardsInformation[0] = UserRewardInfo( + getSymbol(sRewardToken), + address(0), + sRewardToken, + sTokenIncentiveController.getUserUnclaimedRewards(user), + sTokenIncentiveController.getUserAssetData(user, baseData.stableDebtTokenAddress), + 0, + 0, + IERC20Detailed(sRewardToken).decimals() + ); + + userReservesIncentivesData[i].sTokenIncentivesUserData = UserIncentiveData( + baseData.stableDebtTokenAddress, + address(sTokenIncentiveController), + sUserRewardsInformation + ); + } + } catch ( + bytes memory /*lowLevelData*/ + ) {} + } + + return (userReservesIncentivesData); + } + + function getSymbol(address rewardToken) public view returns (string memory) { + if (address(rewardToken) == address(MKRAddress)) { + bytes32 symbol = IERC20DetailedBytes(rewardToken).symbol(); + return bytes32ToString(symbol); + } else { + return IERC20Detailed(rewardToken).symbol(); + } + } + + function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) { + uint8 i = 0; + while (i < 32 && _bytes32[i] != 0) { + i++; + } + bytes memory bytesArray = new bytes(i); + for (i = 0; i < 32 && _bytes32[i] != 0; i++) { + bytesArray[i] = _bytes32[i]; + } + return string(bytesArray); + } +} \ No newline at end of file diff --git a/contracts/misc/UiPoolDataProviderV2V3.sol b/contracts/misc/UiPoolDataProviderV2V3.sol new file mode 100644 index 00000000..a11c9572 --- /dev/null +++ b/contracts/misc/UiPoolDataProviderV2V3.sol @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; +import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; +import {IUiPoolDataProviderV3} from './interfaces/IUiPoolDataProviderV3.sol'; +import {ILendingPool} from '../interfaces/ILendingPool.sol'; +import {IAaveOracle} from './interfaces/IAaveOracle.sol'; +import {IAToken} from '../interfaces/IAToken.sol'; +import {IVariableDebtToken} from '../interfaces/IVariableDebtToken.sol'; +import {IStableDebtToken} from '../interfaces/IStableDebtToken.sol'; +import {WadRayMath} from '../protocol/libraries/math/WadRayMath.sol'; +import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol'; +import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol'; +import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; +import {IChainlinkAggregator} from '../interfaces/IChainlinkAggregator.sol'; +import {DefaultReserveInterestRateStrategy} from '../protocol/lendingpool/DefaultReserveInterestRateStrategy.sol'; +import {IERC20DetailedBytes} from './interfaces/IERC20DetailedBytes.sol'; + +contract UiPoolDataProviderV2V3 is IUiPoolDataProviderV3 { + using WadRayMath for uint256; + using ReserveConfiguration for DataTypes.ReserveConfigurationMap; + using UserConfiguration for DataTypes.UserConfigurationMap; + + IChainlinkAggregator public immutable networkBaseTokenPriceInUsdProxyAggregator; + IChainlinkAggregator public immutable marketReferenceCurrencyPriceInUsdProxyAggregator; + uint256 public constant ETH_CURRENCY_UNIT = 1 ether; + address public constant MKRAddress = 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2; + + constructor( + IChainlinkAggregator _networkBaseTokenPriceInUsdProxyAggregator, + IChainlinkAggregator _marketReferenceCurrencyPriceInUsdProxyAggregator + ) public { + networkBaseTokenPriceInUsdProxyAggregator = _networkBaseTokenPriceInUsdProxyAggregator; + marketReferenceCurrencyPriceInUsdProxyAggregator = _marketReferenceCurrencyPriceInUsdProxyAggregator; + } + + function getInterestRateStrategySlopes(DefaultReserveInterestRateStrategy interestRateStrategy) + internal + view + returns ( + uint256, + uint256, + uint256, + uint256 + ) + { + return ( + interestRateStrategy.variableRateSlope1(), + interestRateStrategy.variableRateSlope2(), + interestRateStrategy.stableRateSlope1(), + interestRateStrategy.stableRateSlope2() + ); + } + + function getReservesList(ILendingPoolAddressesProvider provider) + public + view + override + returns (address[] memory) + { + ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); + return lendingPool.getReservesList(); + } + + function getReservesData(ILendingPoolAddressesProvider provider) + public + view + override + returns (AggregatedReserveData[] memory, BaseCurrencyInfo memory) + { + IAaveOracle oracle = IAaveOracle(provider.getPriceOracle()); + ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); + address[] memory reserves = lendingPool.getReservesList(); + AggregatedReserveData[] memory reservesData = new AggregatedReserveData[](reserves.length); + + for (uint256 i = 0; i < reserves.length; i++) { + AggregatedReserveData memory reserveData = reservesData[i]; + reserveData.underlyingAsset = reserves[i]; + + // reserve current state + DataTypes.ReserveData memory baseData = lendingPool.getReserveData( + reserveData.underlyingAsset + ); + reserveData.liquidityIndex = baseData.liquidityIndex; + reserveData.variableBorrowIndex = baseData.variableBorrowIndex; + reserveData.liquidityRate = baseData.currentLiquidityRate; + reserveData.variableBorrowRate = baseData.currentVariableBorrowRate; + reserveData.stableBorrowRate = baseData.currentStableBorrowRate; + reserveData.lastUpdateTimestamp = baseData.lastUpdateTimestamp; + reserveData.aTokenAddress = baseData.aTokenAddress; + reserveData.stableDebtTokenAddress = baseData.stableDebtTokenAddress; + reserveData.variableDebtTokenAddress = baseData.variableDebtTokenAddress; + reserveData.interestRateStrategyAddress = baseData.interestRateStrategyAddress; + reserveData.priceInMarketReferenceCurrency = oracle.getAssetPrice( + reserveData.underlyingAsset + ); + + reserveData.availableLiquidity = IERC20Detailed(reserveData.underlyingAsset).balanceOf( + reserveData.aTokenAddress + ); + ( + reserveData.totalPrincipalStableDebt, + , + reserveData.averageStableRate, + reserveData.stableDebtLastUpdateTimestamp + ) = IStableDebtToken(reserveData.stableDebtTokenAddress).getSupplyData(); + reserveData.totalScaledVariableDebt = IVariableDebtToken(reserveData.variableDebtTokenAddress) + .scaledTotalSupply(); + + if (address(reserveData.underlyingAsset) == address(MKRAddress)) { + bytes32 symbol = IERC20DetailedBytes(reserveData.underlyingAsset).symbol(); + reserveData.symbol = bytes32ToString(symbol); + } else { + reserveData.symbol = IERC20Detailed(reserveData.underlyingAsset).symbol(); + } + + ( + reserveData.baseLTVasCollateral, + reserveData.reserveLiquidationThreshold, + reserveData.reserveLiquidationBonus, + reserveData.decimals, + reserveData.reserveFactor + ) = baseData.configuration.getParamsMemory(); + ( + reserveData.isActive, + reserveData.isFrozen, + reserveData.borrowingEnabled, + reserveData.stableBorrowRateEnabled + ) = baseData.configuration.getFlagsMemory(); + reserveData.usageAsCollateralEnabled = reserveData.baseLTVasCollateral != 0; + ( + reserveData.variableRateSlope1, + reserveData.variableRateSlope2, + reserveData.stableRateSlope1, + reserveData.stableRateSlope2 + ) = getInterestRateStrategySlopes( + DefaultReserveInterestRateStrategy(reserveData.interestRateStrategyAddress) + ); + } + + BaseCurrencyInfo memory baseCurrencyInfo; + baseCurrencyInfo.networkBaseTokenPriceInUsd = networkBaseTokenPriceInUsdProxyAggregator + .latestAnswer(); + baseCurrencyInfo.networkBaseTokenPriceDecimals = networkBaseTokenPriceInUsdProxyAggregator + .decimals(); + + try oracle.BASE_CURRENCY_UNIT() returns (uint256 baseCurrencyUnit) { + if (ETH_CURRENCY_UNIT == baseCurrencyUnit) { + baseCurrencyInfo.marketReferenceCurrencyUnit = ETH_CURRENCY_UNIT; + baseCurrencyInfo + .marketReferenceCurrencyPriceInUsd = marketReferenceCurrencyPriceInUsdProxyAggregator + .latestAnswer(); + } else { + baseCurrencyInfo.marketReferenceCurrencyUnit = baseCurrencyUnit; + baseCurrencyInfo.marketReferenceCurrencyPriceInUsd = int256(baseCurrencyUnit); + } + } catch ( + bytes memory /*lowLevelData*/ + ) { + baseCurrencyInfo.marketReferenceCurrencyUnit = ETH_CURRENCY_UNIT; + baseCurrencyInfo + .marketReferenceCurrencyPriceInUsd = marketReferenceCurrencyPriceInUsdProxyAggregator + .latestAnswer(); + } + + return (reservesData, baseCurrencyInfo); + } + + function getUserReservesData(ILendingPoolAddressesProvider provider, address user) + external + view + override + returns (UserReserveData[] memory, uint8) + { + ILendingPool lendingPool = ILendingPool(provider.getLendingPool()); + address[] memory reserves = lendingPool.getReservesList(); + DataTypes.UserConfigurationMap memory userConfig = lendingPool.getUserConfiguration(user); + + UserReserveData[] memory userReservesData = new UserReserveData[]( + user != address(0) ? reserves.length : 0 + ); + + for (uint256 i = 0; i < reserves.length; i++) { + DataTypes.ReserveData memory baseData = lendingPool.getReserveData(reserves[i]); + + // user reserve data + userReservesData[i].underlyingAsset = reserves[i]; + userReservesData[i].scaledATokenBalance = IAToken(baseData.aTokenAddress).scaledBalanceOf( + user + ); + userReservesData[i].usageAsCollateralEnabledOnUser = userConfig.isUsingAsCollateral(i); + + if (userConfig.isBorrowing(i)) { + userReservesData[i].scaledVariableDebt = IVariableDebtToken( + baseData.variableDebtTokenAddress + ).scaledBalanceOf(user); + userReservesData[i].principalStableDebt = IStableDebtToken(baseData.stableDebtTokenAddress) + .principalBalanceOf(user); + if (userReservesData[i].principalStableDebt != 0) { + userReservesData[i].stableBorrowRate = IStableDebtToken(baseData.stableDebtTokenAddress) + .getUserStableRate(user); + userReservesData[i].stableBorrowLastUpdateTimestamp = IStableDebtToken( + baseData.stableDebtTokenAddress + ).getUserLastUpdated(user); + } + } + } + + // Return 0 to be compatible with v3 userEmodeCategoryId return + return (userReservesData, 0); + } + + function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) { + uint8 i = 0; + while (i < 32 && _bytes32[i] != 0) { + i++; + } + bytes memory bytesArray = new bytes(i); + for (i = 0; i < 32 && _bytes32[i] != 0; i++) { + bytesArray[i] = _bytes32[i]; + } + return string(bytesArray); + } +} \ No newline at end of file diff --git a/contracts/misc/interfaces/IUiIncentiveDataProviderV2.sol b/contracts/misc/interfaces/IUiIncentiveDataProviderV2.sol new file mode 100644 index 00000000..f397a30c --- /dev/null +++ b/contracts/misc/interfaces/IUiIncentiveDataProviderV2.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; + +interface IUiIncentiveDataProviderV2 { + struct AggregatedReserveIncentiveData { + address underlyingAsset; + IncentiveData aIncentiveData; + IncentiveData vIncentiveData; + IncentiveData sIncentiveData; + } + + struct IncentiveData { + uint256 emissionPerSecond; + uint256 incentivesLastUpdateTimestamp; + uint256 tokenIncentivesIndex; + uint256 emissionEndTimestamp; + address tokenAddress; + address rewardTokenAddress; + address incentiveControllerAddress; + uint8 rewardTokenDecimals; + uint8 precision; + } + + struct UserReserveIncentiveData { + address underlyingAsset; + UserIncentiveData aTokenIncentivesUserData; + UserIncentiveData vTokenIncentivesUserData; + UserIncentiveData sTokenIncentivesUserData; + } + + struct UserIncentiveData { + uint256 tokenincentivesUserIndex; + uint256 userUnclaimedRewards; + address tokenAddress; + address rewardTokenAddress; + address incentiveControllerAddress; + uint8 rewardTokenDecimals; + } + + function getReservesIncentivesData(ILendingPoolAddressesProvider provider) + external + view + returns (AggregatedReserveIncentiveData[] memory); + + function getUserReservesIncentivesData(ILendingPoolAddressesProvider provider, address user) + external + view + returns (UserReserveIncentiveData[] memory); + + // generic method with full data + function getFullReservesIncentiveData(ILendingPoolAddressesProvider provider, address user) + external + view + returns (AggregatedReserveIncentiveData[] memory, UserReserveIncentiveData[] memory); +} \ No newline at end of file diff --git a/contracts/misc/interfaces/IUiIncentiveDataProviderV3.sol b/contracts/misc/interfaces/IUiIncentiveDataProviderV3.sol new file mode 100644 index 00000000..85754658 --- /dev/null +++ b/contracts/misc/interfaces/IUiIncentiveDataProviderV3.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; + +interface IUiIncentiveDataProviderV3 { + struct AggregatedReserveIncentiveData { + address underlyingAsset; + IncentiveData aIncentiveData; + IncentiveData vIncentiveData; + IncentiveData sIncentiveData; + } + + struct IncentiveData { + address tokenAddress; + address incentiveControllerAddress; + RewardInfo[] rewardsTokenInformation; + } + + struct RewardInfo { + string rewardTokenSymbol; + address rewardTokenAddress; + address rewardOracleAddress; + uint256 emissionPerSecond; + uint256 incentivesLastUpdateTimestamp; + uint256 tokenIncentivesIndex; + uint256 emissionEndTimestamp; + int256 rewardPriceFeed; + uint8 rewardTokenDecimals; + uint8 precision; + uint8 priceFeedDecimals; + } + + struct UserReserveIncentiveData { + address underlyingAsset; + UserIncentiveData aTokenIncentivesUserData; + UserIncentiveData vTokenIncentivesUserData; + UserIncentiveData sTokenIncentivesUserData; + } + + struct UserIncentiveData { + address tokenAddress; + address incentiveControllerAddress; + UserRewardInfo[] userRewardsInformation; + } + + struct UserRewardInfo { + string rewardTokenSymbol; + address rewardOracleAddress; + address rewardTokenAddress; + uint256 userUnclaimedRewards; + uint256 tokenIncentivesUserIndex; + int256 rewardPriceFeed; + uint8 priceFeedDecimals; + uint8 rewardTokenDecimals; + + } + + function getReservesIncentivesData(ILendingPoolAddressesProvider provider) + external + view + returns (AggregatedReserveIncentiveData[] memory); + + function getUserReservesIncentivesData(ILendingPoolAddressesProvider provider, address user) + external + view + returns (UserReserveIncentiveData[] memory); + + // generic method with full data + function getFullReservesIncentiveData(ILendingPoolAddressesProvider provider, address user) + external + view + returns (AggregatedReserveIncentiveData[] memory, UserReserveIncentiveData[] memory); +} \ No newline at end of file diff --git a/contracts/misc/interfaces/IUiPoolDataProviderV3.sol b/contracts/misc/interfaces/IUiPoolDataProviderV3.sol new file mode 100644 index 00000000..6153a526 --- /dev/null +++ b/contracts/misc/interfaces/IUiPoolDataProviderV3.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: agpl-3.0 +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; + +interface IUiPoolDataProviderV3 { + struct AggregatedReserveData { + address underlyingAsset; + string name; + string symbol; + uint256 decimals; + uint256 baseLTVasCollateral; + uint256 reserveLiquidationThreshold; + uint256 reserveLiquidationBonus; + uint256 reserveFactor; + bool usageAsCollateralEnabled; + bool borrowingEnabled; + bool stableBorrowRateEnabled; + bool isActive; + bool isFrozen; + // base data + uint128 liquidityIndex; + uint128 variableBorrowIndex; + uint128 liquidityRate; + uint128 variableBorrowRate; + uint128 stableBorrowRate; + uint40 lastUpdateTimestamp; + address aTokenAddress; + address stableDebtTokenAddress; + address variableDebtTokenAddress; + address interestRateStrategyAddress; + // + uint256 availableLiquidity; + uint256 totalPrincipalStableDebt; + uint256 averageStableRate; + uint256 stableDebtLastUpdateTimestamp; + uint256 totalScaledVariableDebt; + uint256 priceInMarketReferenceCurrency; + uint256 variableRateSlope1; + uint256 variableRateSlope2; + uint256 stableRateSlope1; + uint256 stableRateSlope2; + // v3 + bool isPaused; + uint128 accruedToTreasury; + uint128 unbacked; + uint128 isolationModeTotalDebt; + // + uint256 debtCeiling; + uint256 debtCeilingDecimals; + uint8 eModeCategoryId; + uint256 borrowCap; + uint256 supplyCap; + // eMode + uint16 eModeLtv; + uint16 eModeLiquidationThreshold; + uint16 eModeLiquidationBonus; + address eModePriceSource; + string eModeLabel; + bool borrowableInIsolation; + } + + struct UserReserveData { + address underlyingAsset; + uint256 scaledATokenBalance; + bool usageAsCollateralEnabledOnUser; + uint256 stableBorrowRate; + uint256 scaledVariableDebt; + uint256 principalStableDebt; + uint256 stableBorrowLastUpdateTimestamp; + } + + struct BaseCurrencyInfo { + uint256 marketReferenceCurrencyUnit; + int256 marketReferenceCurrencyPriceInUsd; + int256 networkBaseTokenPriceInUsd; + uint8 networkBaseTokenPriceDecimals; + } + + function getReservesList(ILendingPoolAddressesProvider provider) + external + view + returns (address[] memory); + + function getReservesData(ILendingPoolAddressesProvider provider) + external + view + returns ( + AggregatedReserveData[] memory, + BaseCurrencyInfo memory + ); + + function getUserReservesData(ILendingPoolAddressesProvider provider, address user) + external + view + returns ( + UserReserveData[] memory, uint8 + ); +} \ No newline at end of file diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts index 9a8fb434..88633d85 100644 --- a/helper-hardhat-config.ts +++ b/helper-hardhat-config.ts @@ -65,8 +65,8 @@ export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { [eEthereumNetwork.hardhat]: 65 * GWEI, [eEthereumNetwork.buidlerevm]: 65 * GWEI, [eEthereumNetwork.tenderly]: 1 * GWEI, - [ePolygonNetwork.mumbai]: 1 * GWEI, - [ePolygonNetwork.matic]: 1 * GWEI, + [ePolygonNetwork.mumbai]: 35 * GWEI, + [ePolygonNetwork.matic]: 35 * GWEI, [eXDaiNetwork.xdai]: 1 * GWEI, [eAvalancheNetwork.avalanche]: 225 * GWEI, [eAvalancheNetwork.fuji]: 85 * GWEI, diff --git a/helpers/constants.ts b/helpers/constants.ts index 6720a7b9..26e2c611 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -84,6 +84,9 @@ export const chainlinkAggregatorProxy = { avalanche: '0x0A77230d17318075983913bC2145DB16C7366156', fuji: '0x5498BB86BC934c8D34FDA08E81D444153d0D06aD', tenderly: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + 'arbitrum-rinkeby': '0x5f0423B1a6935dc5596e7A24d98532b67A0AeFd8', + arbitrum: '0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612', + rinkeby: '0x8A753747A1Fa494EC906cE90E9f37563A8AF630e', }; export const chainlinkEthUsdAggregatorProxy = { @@ -94,4 +97,7 @@ export const chainlinkEthUsdAggregatorProxy = { avalanche: '0x976B3D034E162d8bD72D6b9C989d545b839003b0', fuji: '0x86d67c3D38D2bCeE722E601025C25a575021c6EA', tenderly: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + 'arbitrum-rinkeby': '0x5f0423B1a6935dc5596e7A24d98532b67A0AeFd8', + arbitrum: '0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612', + rinkeby: '0x8A753747A1Fa494EC906cE90E9f37563A8AF630e', }; diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 2d29e3f2..7292a217 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -52,6 +52,9 @@ import { WETHGatewayFactory, FlashLiquidationAdapterFactory, UiPoolDataProviderV2Factory, + UiPoolDataProviderV2V3Factory, + UiIncentiveDataProviderV2V3, + UiIncentiveDataProviderV2Factory, } from '../types'; import { withSaveAndVerify, @@ -70,6 +73,23 @@ import { LendingPoolLibraryAddresses } from '../types/LendingPoolFactory'; import { UiPoolDataProvider } from '../types'; import { eNetwork } from './types'; +export const deployUiIncentiveDataProviderV2 = async (verify?: boolean) => + withSaveAndVerify( + await new UiIncentiveDataProviderV2Factory(await getFirstSigner()).deploy(), + eContractid.UiIncentiveDataProviderV2, + [], + verify + ); + +export const deployUiIncentiveDataProviderV2V3 = async (verify?: boolean) => { + const id = eContractid.UiIncentiveDataProviderV2V3; + const instance = await deployContract(id, []); + if (verify) { + await verifyContract(id, instance, []); + } + return instance; +}; + export const deployUiPoolDataProviderV2 = async ( chainlinkAggregatorProxy: string, chainlinkEthUsdAggregatorProxy: string, @@ -85,6 +105,21 @@ export const deployUiPoolDataProviderV2 = async ( verify ); +export const deployUiPoolDataProviderV2V3 = async ( + chainlinkAggregatorProxy: string, + chainlinkEthUsdAggregatorProxy: string, + verify?: boolean +) => + withSaveAndVerify( + await new UiPoolDataProviderV2V3Factory(await getFirstSigner()).deploy( + chainlinkAggregatorProxy, + chainlinkEthUsdAggregatorProxy + ), + eContractid.UiPoolDataProvider, + [chainlinkAggregatorProxy, chainlinkEthUsdAggregatorProxy], + verify + ); + export const deployUiPoolDataProvider = async ( [incentivesController, aaveOracle]: [tEthereumAddress, tEthereumAddress], verify?: boolean diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 8548eba0..87d39f03 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -381,14 +381,10 @@ export const verifyContract = async ( instance: Contract, args: (string | string[])[] ) => { - if (usingPolygon()) { - await verifyAtPolygon(id, instance, args); - } else { - if (usingTenderly()) { - await verifyAtTenderly(id, instance); - } - await verifyEtherscanContract(instance.address, args); + if (usingTenderly()) { + await verifyAtTenderly(id, instance); } + await verifyEtherscanContract(instance.address, args); return instance; }; diff --git a/helpers/etherscan-verification.ts b/helpers/etherscan-verification.ts index 3bf097d3..e8f1972e 100644 --- a/helpers/etherscan-verification.ts +++ b/helpers/etherscan-verification.ts @@ -14,7 +14,7 @@ const okErrors = [`Contract source code already verified`]; const unableVerifyError = 'Fail - Unable to verify'; -export const SUPPORTED_ETHERSCAN_NETWORKS = ['main', 'ropsten', 'kovan']; +export const SUPPORTED_ETHERSCAN_NETWORKS = ['main', 'ropsten', 'kovan', 'matic', 'mumbai']; function delay(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/helpers/types.ts b/helpers/types.ts index 3f1e82d6..71597f9c 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -85,6 +85,7 @@ export enum eContractid { ATokensAndRatesHelper = 'ATokensAndRatesHelper', UiPoolDataProvider = 'UiPoolDataProvider', UiPoolDataProviderV2 = 'UiPoolDataProviderV2', + UiPoolDataProviderV2V3 = 'UiPoolDataProviderV2V3', WETHGateway = 'WETHGateway', WETH = 'WETH', WETHMocked = 'WETHMocked', @@ -99,6 +100,8 @@ export enum eContractid { MockParaSwapAugustus = 'MockParaSwapAugustus', MockParaSwapAugustusRegistry = 'MockParaSwapAugustusRegistry', ParaSwapLiquiditySwapAdapter = 'ParaSwapLiquiditySwapAdapter', + UiIncentiveDataProviderV2V3 = 'UiIncentiveDataProviderV2V3', + UiIncentiveDataProviderV2 = 'UiIncentiveDataProviderV2', } /* diff --git a/package.json b/package.json index e6b68832..1fb3ed60 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,14 @@ "mumbai:deployUIProvider": "hardhat --network mumbai deploy-UiPoolDataProvider", "fuji:deployUIProvider": "hardhat --network fuji deploy-UiPoolDataProvider", "dev:deployUIProviderV2": "hardhat --network kovan deploy-UiPoolDataProviderV2 --verify", + "dev:deployUIProviderV2V3": "hardhat --network kovan deploy-UiPoolDataProviderV2V3 --verify", + "fuji:deployUIIncentivesV2V3": "hardhat --network fuji deploy-UiIncentiveDataProviderV2V3", + "mumbai:deployUIIncentivesV2V3": "hardhat --network mumbai deploy-UiIncentiveDataProviderV2V3 --verify", + "matic:deployUIIncentivesV2V3": "hardhat --network matic deploy-UiIncentiveDataProviderV2V3 --verify", + "dev:deployUIIncentivesProviderV2": "hardhat --network kovan deploy-UiIncentiveDataProviderV2 --verify", + "main:deployUIIncentivesProviderV2": "hardhat --network main deploy-UiIncentiveDataProviderV2 --verify", + "matic:deployUIIncentivesProviderV2": "hardhat --network matic deploy-UiIncentiveDataProviderV2 --verify", + "mumbai:deployUIIncentivesProviderV2": "hardhat --network mumbai deploy-UiIncentiveDataProviderV2 --verify", "dev:deployUniswapRepayAdapter": "hardhat --network kovan deploy-UniswapRepayAdapter --provider 0x88757f2f99175387aB4C6a4b3067c77A695b0349 --router 0xfcd87315f0e4067070ade8682fcdbc3006631441 --weth 0xd0a1e359811322d97991e03f863a0c30c2cf029c", "dev:UniswapLiquiditySwapAdapter": "hardhat --network kovan deploy-UniswapLiquiditySwapAdapter --provider 0x88757f2f99175387aB4C6a4b3067c77A695b0349 --router 0xfcd87315f0e4067070ade8682fcdbc3006631441 --weth 0xd0a1e359811322d97991e03f863a0c30c2cf029c", "main:deployUniswapRepayAdapter": "hardhat --network main deploy-UniswapRepayAdapter --provider 0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5 --router 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D --weth 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", diff --git a/tasks/deployments/deploy-UiIncentiveDataProviderV2.ts b/tasks/deployments/deploy-UiIncentiveDataProviderV2.ts new file mode 100644 index 00000000..ca3efe45 --- /dev/null +++ b/tasks/deployments/deploy-UiIncentiveDataProviderV2.ts @@ -0,0 +1,23 @@ +import { task } from 'hardhat/config'; +import { eContractid, eEthereumNetwork, eNetwork, ePolygonNetwork } from '../../helpers/types'; +import { deployUiIncentiveDataProviderV2 } from '../../helpers/contracts-deployments'; +import { exit } from 'process'; + +task( + `deploy-${eContractid.UiIncentiveDataProviderV2}`, + `Deploys the UiIncentiveDataProviderV2 contract` +) + .addFlag('verify', 'Verify UiIncentiveDataProviderV2 contract via Etherscan API.') + .setAction(async ({ verify }, localBRE) => { + await localBRE.run('set-DRE'); + if (!localBRE.network.config.chainId) { + throw new Error('INVALID_CHAIN_ID'); + } + + console.log(`\n- UiIncentiveDataProviderV2 deployment`); + + const UiIncentiveDataProviderV2 = await deployUiIncentiveDataProviderV2(verify); + + console.log('UiIncentiveDataProviderV2 deployed at:', UiIncentiveDataProviderV2.address); + console.log(`\tFinished UiIncentiveDataProviderV2 deployment`); + }); diff --git a/tasks/deployments/deploy-UiIncentiveDataProviderV2V3.ts b/tasks/deployments/deploy-UiIncentiveDataProviderV2V3.ts new file mode 100644 index 00000000..8c798db8 --- /dev/null +++ b/tasks/deployments/deploy-UiIncentiveDataProviderV2V3.ts @@ -0,0 +1,21 @@ +import { task } from 'hardhat/config'; +import { eContractid } from '../../helpers/types'; +import { deployUiIncentiveDataProviderV2V3 } from '../../helpers/contracts-deployments'; + +task( + `deploy-${eContractid.UiIncentiveDataProviderV2V3}`, + `Deploys the UiIncentiveDataProviderV2V3 contract` +) + .addFlag('verify', 'Verify UiIncentiveDataProviderV2V3 contract via Etherscan API.') + .setAction(async ({ verify }, localBRE) => { + await localBRE.run('set-DRE'); + if (!localBRE.network.config.chainId) { + throw new Error('INVALID_CHAIN_ID'); + } + console.log(`\n- UiIncentiveDataProviderV2V3 deployment`); + + const uiIncentiveDataProviderV2V3 = await deployUiIncentiveDataProviderV2V3(verify); + + console.log('UiIncentiveDataProviderV2V3 deployed at:', uiIncentiveDataProviderV2V3.address); + console.log(`\tFinished UiIncentiveDataProviderV2V3 deployment`); + }); diff --git a/tasks/deployments/deploy-UiPoolDataProviderV2V3.ts b/tasks/deployments/deploy-UiPoolDataProviderV2V3.ts new file mode 100644 index 00000000..3fee992e --- /dev/null +++ b/tasks/deployments/deploy-UiPoolDataProviderV2V3.ts @@ -0,0 +1,34 @@ +import { task } from 'hardhat/config'; +import { eContractid } from '../../helpers/types'; +import { deployUiPoolDataProviderV2V3 } from '../../helpers/contracts-deployments'; +import { chainlinkAggregatorProxy, chainlinkEthUsdAggregatorProxy } from '../../helpers/constants'; + +task(`deploy-${eContractid.UiPoolDataProviderV2V3}`, `Deploys the UiPoolDataProviderV2V3 contract`) + .addFlag('verify', 'Verify UiPoolDataProviderV2V3 contract via Etherscan API.') + .setAction(async ({ verify }, localBRE) => { + await localBRE.run('set-DRE'); + if (!localBRE.network.config.chainId) { + throw new Error('INVALID_CHAIN_ID'); + } + + console.log( + `\n- UiPoolDataProviderV2V3 price aggregator: ${ + chainlinkAggregatorProxy[localBRE.network.name] + }` + ); + console.log( + `\n- UiPoolDataProviderV2V3 eth/usd price aggregator: ${ + chainlinkAggregatorProxy[localBRE.network.name] + }` + ); + console.log(`\n- UiPoolDataProviderV2V3 deployment`); + + const UiPoolDataProviderV2V3 = await deployUiPoolDataProviderV2V3( + chainlinkAggregatorProxy[localBRE.network.name], + chainlinkEthUsdAggregatorProxy[localBRE.network.name], + verify + ); + + console.log('UiPoolDataProviderV2 deployed at:', UiPoolDataProviderV2V3.address); + console.log(`\tFinished UiPoolDataProvider deployment`); + }); diff --git a/tasks/full/6-initialize.ts b/tasks/full/6-initialize.ts index fc93600d..fa7a20cf 100644 --- a/tasks/full/6-initialize.ts +++ b/tasks/full/6-initialize.ts @@ -4,7 +4,7 @@ import { deployLendingPoolCollateralManager, deployWalletBalancerProvider, authorizeWETHGateway, - deployUiPoolDataProvider, + deployUiPoolDataProviderV2, } from '../../helpers/contracts-deployments'; import { loadPoolConfig, ConfigNames, getTreasuryAddress } from '../../helpers/configuration'; import { getWETHGateway } from '../../helpers/contracts-getters'; @@ -16,7 +16,7 @@ import { getAaveProtocolDataProvider, getLendingPoolAddressesProvider, } from '../../helpers/contracts-getters'; -import { ZERO_ADDRESS } from '../../helpers/constants'; +import { chainlinkAggregatorProxy, chainlinkEthUsdAggregatorProxy } from '../../helpers/constants'; task('full:initialize-lending-pool', 'Initialize lending pool configuration.') .addFlag('verify', 'Verify contracts at Etherscan') @@ -100,8 +100,9 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await deployWalletBalancerProvider(verify); - const uiPoolDataProvider = await deployUiPoolDataProvider( - [incentivesController, oracle], + const uiPoolDataProvider = await deployUiPoolDataProviderV2( + chainlinkAggregatorProxy[localBRE.network.name], + chainlinkEthUsdAggregatorProxy[localBRE.network.name], verify ); console.log('UiPoolDataProvider deployed at:', uiPoolDataProvider.address);