feat: working version of the UiIncentiveDataProviderV2 with the V3 interface

This commit is contained in:
sendra 2021-12-03 19:01:22 +01:00
parent e558db406f
commit b5c06fbd52
8 changed files with 519 additions and 7 deletions

View File

@ -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 UiIncentiveDataProviderV2 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].aTokenIncentivesUserData = 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].aTokenIncentivesUserData = 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);
}
}

View File

@ -1,8 +1,12 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
contract IERC20DetailedBytes {
bytes32 public name;
bytes32 public symbol;
uint256 public decimals;
}
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
interface IERC20DetailedBytes is IERC20 {
function name() external view returns (bytes32);
function symbol() external view returns (bytes32);
function decimals() external view returns (uint8);
}

View File

@ -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);
}

View File

@ -65,8 +65,8 @@ export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork<number> = {
[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,

View File

@ -51,6 +51,7 @@ import {
WETH9MockedFactory,
WETHGatewayFactory,
FlashLiquidationAdapterFactory,
UiIncentiveDataProviderV2,
} from '../types';
import {
withSaveAndVerify,
@ -69,6 +70,15 @@ import { LendingPoolLibraryAddresses } from '../types/LendingPoolFactory';
import { UiPoolDataProvider } from '../types';
import { eNetwork } from './types';
export const deployUiIncentiveDataProviderV2 = async (verify?: boolean) => {
const id = eContractid.UiIncentiveDataProviderV2;
const instance = await deployContract<UiIncentiveDataProviderV2>(id, []);
if (verify) {
await verifyContract(id, instance, []);
}
return instance;
};
export const deployUiPoolDataProvider = async (
[incentivesController, aaveOracle]: [tEthereumAddress, tEthereumAddress],
verify?: boolean

View File

@ -98,6 +98,7 @@ export enum eContractid {
MockParaSwapAugustus = 'MockParaSwapAugustus',
MockParaSwapAugustusRegistry = 'MockParaSwapAugustusRegistry',
ParaSwapLiquiditySwapAdapter = 'ParaSwapLiquiditySwapAdapter',
UiIncentiveDataProviderV2 = 'UiIncentiveDataProviderV2',
}
/*

View File

@ -76,6 +76,9 @@
"matic:deployUIProvider": "hardhat --network matic deploy-UiPoolDataProvider",
"mumbai:deployUIProvider": "hardhat --network mumbai deploy-UiPoolDataProvider",
"fuji:deployUIProvider": "hardhat --network fuji deploy-UiPoolDataProvider",
"fuji:deployUIIncentivesV2": "hardhat --network fuji deploy-UiIncentiveDataProviderV2",
"mumbai:deployUIIncentivesV2": "hardhat --network mumbai deploy-UiIncentiveDataProviderV2 --verify",
"matic:deployUIIncentivesV2": "hardhat --network matic 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",

View File

@ -0,0 +1,21 @@
import { task } from 'hardhat/config';
import { eContractid } from '../../helpers/types';
import { deployUiIncentiveDataProviderV2 } from '../../helpers/contracts-deployments';
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`);
});