Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/ui-stake-helpers #32

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 45 additions & 66 deletions contracts/interfaces/IStakedTokenDataProvider.sol
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarify the format and unit denomination of oracles on every @param please.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface IStakedTokenDataProvider {
uint256 rewardTokenPriceEth;
uint256 stakeApy;
uint128 distributionPerSecond;
bool inPostSlashingPeriod;
uint256 distributionEnd;
}

Expand All @@ -40,12 +41,6 @@ interface IStakedTokenDataProvider {
*/
function AAVE_PRICE_FEED() external returns (address);

/**
* @notice Return the address of the BPT price feed, ETH denominated
* @return The address of the BPT price feed, ETH denominated, expressed with 18 decimals
*/
function BPT_PRICE_FEED() external returns (address);

/**
* @notice Return the address of the AAVE token
* @return The address of the AAVE token
Expand All @@ -59,83 +54,67 @@ interface IStakedTokenDataProvider {
function STAKED_AAVE() external returns (address);

/**
* @notice Return the address of the BPT token
* @return The address of the BPT token
*/
function BPT() external returns (address);

/**
* @notice Return the address of the Staked BPT token
* @return The address of the StkBPT token
* @notice Returns data of Staked assets
* @param stakedAsset The address of the stakedAsset
* @param oracleAddress The address of the oracle denominated in 18 decimals
* @return stakedAssetData An object with staked asset data
*/
function STAKED_BPT() external returns (address);

/**
* @notice Returns data of all Staked Tokens
* @return stkAaveData An object with StkAave data
* @return stkBptData An object with StkBpt data
* @return ethPrice The price of ETH, USD denominated (expressed with 8 decimals)
*/
function getAllStakedTokenData()
function getStakedAssetData(address stakedAsset, address oracleAddress)
external
view
returns (
StakedTokenData memory stkAaveData,
StakedTokenData memory stkBptData,
uint256 ethPrice
);

/**
* @notice Returns data of Staked Aave
* @return stkAaveData An object with StkAave data
*/
function getStkAaveData() external view returns (StakedTokenData memory stkAaveData);
returns (StakedTokenData memory stakedAssetData);

/**
* @notice Returns data of Staked Bpt Aave
* @return stkBptData An object with StkBpt data
* @notice Retrieves staked token data and user-specific data for a given user, staked asset, and its associated oracle.
* @param user The address of the user for whom the data is to be fetched.
* @param stakedAsset The address representing the staked token.
* @param oracleAddress The address representing the oracle associated with the staked token denominated in 18 decimals.
* @return stakedTokenData `StakedTokenData` struct with details about the staked asset.
* @return stakedUserData `StakedTokenUserData` struct containing user-specific details related to the staked asset.
*/
function getStkBptData() external view returns (StakedTokenData memory stkBptData);
function getStakedUserData(
address user,
address stakedAsset,
address oracleAddress
)
external
view
returns (StakedTokenData memory stakedTokenData, StakedTokenUserData memory stakedUserData);

/**
* @notice Returns user data of all Staked Tokens
* @param user The address of the user
* @return stkAaveData An object with StkAave data
* @return stkAaveUserData An object with user data of StkAave
* @return stkBptData An object with StkBpt data
* @return stkBptUserData An object with user data of StkBpt
* @return ethPrice The price of ETH, USD denominated (expressed with 8 decimals)
* @notice Retrieves data for a batch of staked assets given their addresses and the addresses of their associated oracles.
* @param stakedTokens An array of addresses representing the staked tokens.
* @param oracleAddresses An array of addresses representing the oracles associated with the staked tokens denominated as 18 decimals.
* @return stakedData An array containing data about the staked assets.
* @return prices An array containing the latest price data from the oracles for the staked tokens.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this array needed? stakedData contains the price of the reward already iirc

* @return ethPrice A uint256 with the latest ETH price for the staked tokens.
*/
function getAllStakedTokenUserData(address user)
function getStakedAssetDataBatch(
address[] calldata stakedTokens,
address[] calldata oracleAddresses
)
external
view
returns (
StakedTokenData memory stkAaveData,
StakedTokenUserData memory stkAaveUserData,
StakedTokenData memory stkBptData,
StakedTokenUserData memory stkBptUserData,
StakedTokenData[] memory stakedData,
uint256[] memory prices,
uint256 ethPrice
);

/**
* @notice Returns user data of Staked Aave
* @param user The address of the user
* @return stkAaveData An object with StkAave data
* @return stkAaveUserData An object with user data of StkAave
*/
function getStkAaveUserData(address user)
external
view
returns (StakedTokenData memory stkAaveData, StakedTokenUserData memory stkAaveUserData);

/**
* @notice Returns user data of Staked Bpt Aave
* @param user The address of the user
* @return stkBptData An object with StkBpt data
* @return stkBptUserData An object with user data of StkBpt
* @notice Retrieves data for a batch of staked users and their assets given the addresses of staked tokens, associated oracles, and users.
* @param stakedTokens An array of addresses representing the staked tokens.
* @param oracleAddresses An array of addresses representing the oracles associated with the staked tokens denominated as 18 decimals.
* @param userAddress An addresses representing the user whose data should be retrieved.
* @return stakedTokenData An array containing data about the staked assets.
* @return stakedUserData An array containing user-specific data about the staked assets.
*/
function getStkBptAaveUserData(address user)
function getStakedUserDataBatch(
address[] calldata stakedTokens,
address[] calldata oracleAddresses,
address userAddress
)
external
view
returns (StakedTokenData memory stkBptData, StakedTokenUserData memory stkBptUserData);
returns (StakedTokenData[] memory stakedTokenData, StakedTokenUserData[] memory stakedUserData);
}
124 changes: 55 additions & 69 deletions contracts/misc/StakedTokenDataProvider.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,12 @@ contract StakedTokenDataProvider is IStakedTokenDataProvider {
/// @inheritdoc IStakedTokenDataProvider
address public immutable override AAVE_PRICE_FEED;

/// @inheritdoc IStakedTokenDataProvider
address public immutable override BPT_PRICE_FEED;

/// @inheritdoc IStakedTokenDataProvider
address public immutable override AAVE;

/// @inheritdoc IStakedTokenDataProvider
address public immutable override STAKED_AAVE;

/// @inheritdoc IStakedTokenDataProvider
address public immutable override BPT;

/// @inheritdoc IStakedTokenDataProvider
address public immutable override STAKED_BPT;

uint256 private constant SECONDS_PER_YEAR = 365 days;

uint256 private constant APY_PRECISION = 10000;
Expand All @@ -42,104 +33,98 @@ contract StakedTokenDataProvider is IStakedTokenDataProvider {
* @dev Constructor
* @param aave The address of the AAVE token
* @param stkAave The address of the StkAAVE token
* @param bpt The address of the BPT AAVE / ETH token
* @param stkBpt The address of the StkBptAAVE token
* @param ethUsdPriceFeed The address of ETH price feed (USD denominated, with 8 decimals)
* @param aavePriceFeed The address of AAVE price feed (ETH denominated, with 18 decimals)
* @param bptPriceFeed The address of StakedBpt price feed (ETH denominated, with 18 decimals)
*/
constructor(
address aave,
address stkAave,
address bpt,
address stkBpt,
address ethUsdPriceFeed,
address aavePriceFeed,
address bptPriceFeed
address aavePriceFeed
) public {
AAVE = aave;
STAKED_AAVE = stkAave;
BPT = bpt;
STAKED_BPT = stkBpt;
ETH_USD_PRICE_FEED = ethUsdPriceFeed;
AAVE_PRICE_FEED = aavePriceFeed;
BPT_PRICE_FEED = bptPriceFeed;
}

/// @inheritdoc IStakedTokenDataProvider
function getAllStakedTokenData()
function getStakedAssetDataBatch(
address[] calldata stakedTokens,
address[] calldata oracleAddresses
)
external
view
override
returns (
StakedTokenData memory stkAaveData,
StakedTokenData memory stkBptData,
uint256 ethPrice
StakedTokenData[] memory,
uint256[] memory,
uint256
)
{
stkAaveData = _getStakedTokenData(AggregatedStakedAaveV3(STAKED_AAVE));
stkBptData = _getStakedTokenData(AggregatedStakedAaveV3(STAKED_BPT));
ethPrice = uint256(AggregatorInterface(ETH_USD_PRICE_FEED).latestAnswer());
}

/// @inheritdoc IStakedTokenDataProvider
function getStkAaveData() external view override returns (StakedTokenData memory stkAaveData) {
stkAaveData = _getStakedTokenData(AggregatedStakedAaveV3(STAKED_AAVE));
}

/// @inheritdoc IStakedTokenDataProvider
function getStkBptData() external view override returns (StakedTokenData memory stkBptData) {
stkBptData = _getStakedTokenData(AggregatedStakedAaveV3(STAKED_BPT));
require(stakedTokens.length == oracleAddresses.length, 'Arrays must be of the same length');

StakedTokenData[] memory stakedData = new StakedTokenData[](stakedTokens.length);
uint256[] memory prices = new uint256[](oracleAddresses.length);
uint256 ethPrice = uint256(AggregatorInterface(ETH_USD_PRICE_FEED).latestAnswer());
for (uint256 i = 0; i < stakedTokens.length; i++) {
stakedData[i] = _getStakedTokenData(
AggregatedStakedAaveV3(stakedTokens[i]),
oracleAddresses[i]
);
prices[i] = uint256(AggregatorInterface(oracleAddresses[i]).latestAnswer());
}
return (stakedData, prices, ethPrice);
}

/// @inheritdoc IStakedTokenDataProvider
function getAllStakedTokenUserData(address user)
external
view
override
returns (
StakedTokenData memory stkAaveData,
StakedTokenUserData memory stkAaveUserData,
StakedTokenData memory stkBptData,
StakedTokenUserData memory stkBptUserData,
uint256 ethPrice
)
{
stkAaveData = _getStakedTokenData(AggregatedStakedAaveV3(STAKED_AAVE));
stkAaveUserData = _getStakedTokenUserData(AggregatedStakedAaveV3(STAKED_AAVE), user);
stkBptData = _getStakedTokenData(AggregatedStakedAaveV3(STAKED_BPT));
stkBptUserData = _getStakedTokenUserData(AggregatedStakedAaveV3(STAKED_BPT), user);
ethPrice = uint256(AggregatorInterface(ETH_USD_PRICE_FEED).latestAnswer());
function getStakedUserDataBatch(
address[] calldata stakedTokens,
address[] calldata oracleAddresses,
address userAddress
) external view override returns (StakedTokenData[] memory, StakedTokenUserData[] memory) {
require(stakedTokens.length == oracleAddresses.length, 'All arrays must be of the same length');
StakedTokenData[] memory stakedData = new StakedTokenData[](stakedTokens.length);
StakedTokenUserData[] memory userData = new StakedTokenUserData[](stakedTokens.length);

for (uint256 i = 0; i < stakedTokens.length; i++) {
stakedData[i] = _getStakedTokenData(
AggregatedStakedAaveV3(stakedTokens[i]),
oracleAddresses[i]
);
userData[i] = _getStakedTokenUserData(AggregatedStakedAaveV3(stakedTokens[i]), userAddress);
}
return (stakedData, userData);
}

/// @inheritdoc IStakedTokenDataProvider
function getStkAaveUserData(address user)
function getStakedAssetData(address stakedAsset, address oracleAddress)
external
view
override
returns (StakedTokenData memory stkAaveData, StakedTokenUserData memory stkAaveUserData)
returns (StakedTokenData memory)
{
stkAaveData = _getStakedTokenData(AggregatedStakedAaveV3(STAKED_AAVE));
stkAaveUserData = _getStakedTokenUserData(AggregatedStakedAaveV3(STAKED_AAVE), user);
return _getStakedTokenData(AggregatedStakedAaveV3(stakedAsset), oracleAddress);
}

/// @inheritdoc IStakedTokenDataProvider
function getStkBptAaveUserData(address user)
external
view
override
returns (StakedTokenData memory stkBptData, StakedTokenUserData memory stkBptUserData)
{
stkBptData = _getStakedTokenData(AggregatedStakedAaveV3(STAKED_BPT));
stkBptUserData = _getStakedTokenUserData(AggregatedStakedAaveV3(STAKED_BPT), user);
function getStakedUserData(
address user,
address stakedAsset,
address oracleAddress
) external view override returns (StakedTokenData memory, StakedTokenUserData memory) {
return (
_getStakedTokenData(AggregatedStakedAaveV3(stakedAsset), oracleAddress),
_getStakedTokenUserData(AggregatedStakedAaveV3(stakedAsset), user)
);
}

/**
* @notice Returns data of the Staked Token passed as parameter
* @param stakedToken The address of the StakedToken (eg. stkAave, stkBptAave)
* @return data An object with general data of the StakedToken
*/
function _getStakedTokenData(AggregatedStakedAaveV3 stakedToken)
function _getStakedTokenData(AggregatedStakedAaveV3 stakedToken, address oracleAddress)
internal
view
returns (StakedTokenData memory data)
Expand All @@ -150,6 +135,7 @@ contract StakedTokenDataProvider is IStakedTokenDataProvider {
data.stakeUnstakeWindow = stakedToken.UNSTAKE_WINDOW();
data.rewardTokenPriceEth = uint256(AggregatorInterface(AAVE_PRICE_FEED).latestAnswer());
data.distributionEnd = stakedToken.DISTRIBUTION_END();
data.inPostSlashingPeriod = stakedToken.inPostSlashingPeriod();

data.distributionPerSecond = block.timestamp < data.distributionEnd
? stakedToken.assets(address(stakedToken)).emissionPerSecond
Expand All @@ -161,9 +147,9 @@ contract StakedTokenDataProvider is IStakedTokenDataProvider {
// assumes AAVE and stkAAVE have the same value
data.stakeApy = _calculateApy(data.distributionPerSecond, data.stakedTokenTotalSupply);

// stkBptAave
} else if (address(stakedToken) == STAKED_BPT) {
data.stakedTokenPriceEth = uint256(AggregatorInterface(BPT_PRICE_FEED).latestAnswer());
// other wrapped assets
} else {
data.stakedTokenPriceEth = uint256(AggregatorInterface(oracleAddress).latestAnswer());
data.stakeApy = _calculateApy(
data.distributionPerSecond * data.rewardTokenPriceEth,
data.stakedTokenTotalSupply * data.stakedTokenPriceEth
Expand Down
1 change: 1 addition & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ const config: HardhatUserConfig = {
ropsten: getCommonNetworkConfig(eEthereumNetwork.ropsten, 3),
goerli: getCommonNetworkConfig(eEthereumNetwork.goerli, 5),
main: getCommonNetworkConfig(eEthereumNetwork.main, 1),
sepolia: getCommonNetworkConfig(eEthereumNetwork.sepolia, 11155111),
hardhat: {
hardfork: 'london',
blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT,
Expand Down
13 changes: 13 additions & 0 deletions helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ export const PROXY_CRP_ADMIN = SHORT_EXECUTOR;
export const RESERVE_CONTROLER = '0x1E506cbb6721B83B1549fa1558332381Ffa61A93';
export const ZERO_ADDRESS: tEthereumAddress = '0x0000000000000000000000000000000000000000';

export const STK_BPT = '0xa1116930326d21fb917d5a27f1e9943a9595fb47';
export const AAVE_BPT_POOL_TOKEN = '0x41a08648c3766f9f9d85598ff102a08f4ef84f84';
export const STK_WSTEH = '0xa1116930326d21fb917d5a27f1e9943a9595fb47'; // TODO change for actual token
export const STAKED_AAVE = '0x4da27a545c0c5b758a6ba100e3a049001de870f5';
export const ETH_USD_PRICE_FEED = '0x5f4ec3df9cbd43714fe2740f5e3616155c5b8419';
export const AAVE_ORACLE = '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012';
export const BPT_PRICE_FEED = '0x0De156f178a20114eeec0eBF71d7772064476b0D';
export const STK_WHALE = '0xaFDAbFb6227507fF6522b8a242168F6b5F353a6E';
export const BPT_WHALE = '0x741AA7CFB2c7bF2A1E7D4dA2e3Df6a56cA4131F3';
export const STK_WSTEH_WHALE = '0x741AA7CFB2c7bF2A1E7D4dA2e3Df6a56cA4131F3';
export const COLLECTOR = '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c';
export const STK_WSTEH_PRICE_FEED = BPT_PRICE_FEED; // TODO change

// PEI constants
export const PSM_STAKER_PREMIUM = '2';

Expand Down
Loading
Loading