vaults.fyi
  • General
    • 🏦Overview
    • 💡Use Cases
      • For Wallets and Apps
      • For Analysts
      • For Protocols & Product Teams
    • 🔎Methodology
      • vaults.fyi USD benchmark rate
      • vaults.fyi ETH benchmark rate
    • ❓FAQ
      • Vault requirements for inclusion on vaults.fyi
    • 🤖AI
  • API
    • vaults.fyi API Overview
      • Insights API
      • Earn API
        • Product demo
        • Flow diagrams
      • Plans
        • Credits
    • Endpoints
      • Market data
        • Get historical data
          • Get historical APY and TVL data on single vault over timestamp range
          • Get historical APY on single vault over timestamp range
          • Get historical TVL on single vault at single timestamp
          • Get historical APY on single vault at single timestamp
        • Get data for multiple vaults
        • Get data on single vault
          • Get APY on single vault
        • Get benchmark rates
        • Get supported vaults, networks & tokens
          • /vaults
          • /networks
          • /tokens
          • /tags
      • Contextual insights
        • Top vault options for address
        • Get single top option for address
        • [Etherscan cards] Get top USD, top ETH vault for address
      • Generate payloads (Earn API)
        • Prepare calldata
          • Supply/Deposit
          • Withdraw/Redeem
            • Request redeem
            • Claim redeem
          • Claim rewards
        • Get contract interaction details
        • Get supported assets
        • Get supported vaults
      • Position tracking (Portfolio API)
        • Get user balances
        • Get user positions
        • Get list of past vault txns by user address
        • Get estimated returns for user's vault position
  • Case Studies
    • Kraken Wallet
    • Etherscan Cards
  • Links
    • vaults.fyi
    • X
    • Farcaster
    • Wallfacer Labs
Powered by GitBook
On this page
  • Calculating APY from historical data
  • Simple interest
  • Compounding interest
  • Interest Rate Calculation
  • Range APY
  • Weighting Mechanism for Range APY
  • Rewards APY
  • Obtaining the data we need
  • ERC-4626
  • Not ERC-4626
  • Liquid staking tokens
  • Rebasing supply vaults
  • Staking mechanism vaults
  • Real-world assets
  1. General

Methodology

PreviousFor Protocols & Product TeamsNextvaults.fyi USD benchmark rate

Last updated 8 months ago

utilizes onchain data to track yields over a given period of time. We query blockchains hourly and obtain the share price of the specific DeFi vaults curated on our platform. This share price, indicative of a lender’s stake in a vault, can be used to calculate yield over time. By sourcing data directly and avoiding external API endpoints, we strive for accuracy and dependability.

For example, when calculating a vault’s 7-day APY on January 7th, we compare the share price on that day with the share price from January 1st and then extrapolate this difference over an entire year. This method is similarly applied when determining 1-day and 30-day APYs.

To efficiently automate this process, we implement specialized smart contracts that fetch and transform data using a single function. These contracts are deployed in a static call, which is temporary and does not affect blockchain storage, thereby incurring any cost. This method allows us to read data directly from the blockchain. Our approach saves on calls and enables the use of one result to calculate the next within the same call, a technique not possible with standard multi-call processes. We use services like Infura, Alchemy, and Ankr RPCs to execute these calls. Once the data is retrieved, it is stored in our backend database.

Calculating APY from historical data

Due to the vast amount of data involved and the limitations in indexing speed, it is impractical to query blockchains every time a new block is added. Instead, we calculate yield using accrued interest, an obtainable figure for most yield-bearing products. This allows APY to be extrapolated from limited data points.

Simple interest

We use the following formula to calculate APY for simple (i.e., not compounding) interest:

APY=interest rate×yeartime \text{APY} = \text{interest rate} \times \frac{\text{year}}{\text{time}} APY=interest rate×timeyear​

Compounding interest

To determine compounding interest, we use the following formula:

APY=[(1+interest rate)yeartime]−1\text{APY} = \left[ \left(1 + \text{interest rate}\right)^\frac{\text{year}}{\text{time}} \right] - 1APY=[(1+interest rate)timeyear​]−1

Interest Rate Calculation

The interest rate at any given point in time is determined by:

Where the share price is:

Range APY

To offer a more representative APY, especially in scenarios with fluctuating yields, we compute a range APY. This involves calculating a weighted average of interest rates over a specified period (x days).

Weighting Mechanism for Range APY

Rationale

The TVL between two consecutive points in time (t_{i} and t_{i-1}) is inherently uncertain. To maintain a conservative approach and avoid overestimating the yield, we choose to underestimate the TVL during that interval by selecting the lower of the two TVL values. This ensures that the calculated APY reflects a more realistic, if not slightly lower, yield.

With this weighting method the average interest rate over a given period is determined by

Rewards APY

To calculate the rewards APY for a desired time range (1 day, 7 days, 30 days), we:

  1. Estimate the number of reward tokens distributed per token deposited in the vault during the chosen period by taking a weighted average of emissions based on the TVL.

  2. Calculate the average price ratio between the reward token and the deposited token for that period.

  3. Use this ratio to convert the accumulated reward tokens' value to a single deposited token's value.

  4. Compare this converted value to the initial deposit to determine the APY.

The average of the reward token price (PIT - Price In Token) to deposited token price is calculated using the formula:

The APY at time range of xday is calculated using the formula:

Obtaining the data we need

In order to execute the calculations outlined above, accessing onchain data is essential. Our method of obtaining a vault's share price depends on the type of vault. You can read more about each method below.

ERC-4626

In the case of ERC-4626 vaults, we can call the totalSupply and totalAssets smart contract functions to calculate share price.

totalSupply = total shares

totalAssets = total shares value

Not ERC-4626

If a vault is not ERC-4626 compliant, proxies for the above functions can usually be found in the following functions:

  • mint

  • deposit

  • burn

  • redeem

You can see an example of this in the code snippets below.

function deposit(uint256 _amount, address _receiver) 
    external 
    nonReentrant 
    isNotPastMaturity 
    whenNotPaused 
    approvedLender(_receiver) 
    returns (uint256 _sharesReceived)
{
    _addInterest();
    VaultAccount memory _totalAsset = totalAsset;
    _sharesReceived = _totalAsset.toShares(_amount, false);
    _deposit(_totalAsset, _amount.toUint128(), _sharesReceived, _receiver);
}
function toShares(
    VaultAccount memory total,
    uint256 amount,
    bool roundUp
) internal pure returns (uint256 shares) {
    if (total.amount == 0) {
        shares = amount;
    } else {
        shares = (amount * total.shares) / total.amount;
        if (roundUp && (shares * total.amount) / total.shares < amount) {
            shares = shares + 1;
        }
    }
}

The functions provided are typical examples and not an exhaustive list; some vaults may require individual solutions.

Liquid staking tokens

totalSupply = total shares

getEthValue(totalSupply)= total shares value

One challenge we face is accounting for the irregular intervals at which some vaults update their earnings — leading to sudden and significant fluctuations in APY. Understanding this nuance is essential for accurately interpreting discrepancies on vaults.fyi.

Rebasing supply vaults

scaledTotalSupply = total shares

totalSupply = total shares value

Staking mechanism vaults

Instead, we can ascertain the actual share price with the following formulas:

These formulas result in a simulated calculation of totalSupply. It is not directly fetched from the blockchain.

Real-world assets

  • The totalSupply function to calculate total shares.

  • The RWAOracle.price function to fetch share price.

  • The StablecoinOracle.price function to fetch the underlying asset's (i.e, a stablecoin) price.

These functions are used in the following formulas to calculate yield:

interest rate=current share priceprevious share price−1\text{interest rate} = \frac{\text{current share price}}{\text{previous share price}} - 1 interest rate=previous share pricecurrent share price​−1
share price=total shares valuetotal shares\text{share price} = \frac{\text{total shares value}}{\text{total shares}}share price=total sharestotal shares value​

In calculating the weighted average interest rate for the range APY, each point in time within the range is assigned a weight. This weight is determined by taking the minimum of the TVL at that specific time (TVLti)(TVL_{t_{i}})(TVLti​​) and the TVL at the preceding time (TVLti−1)(TVL_{t_{i-1}})(TVLti−1​​).

weightti=min(TVLti,TVLti−1)\text{weight}_{t_{i}}=min(\text{TVL}_{t_{i}},\text{TVL}_{t_{i-1}})weightti​​=min(TVLti​​,TVLti−1​​)
interest rateti,xday=(∑j:ti−tj=xdayishare pricetjshare pricetj−1∗weighttj∑j:ti−tj=xdayiweighttj)i−j−1\text{interest rate}_{t_{i},xday}=(\frac{\sum_{j:t_{i}-t_{j}=xday}^{i}\frac{\text{share price}_{t_{j}}}{\text{share price}_{t_{j-1}}}*weight_{t_{j}}}{\sum_{j:t_{i}-t_{j}=xday}^{i}weight_{t_{j}}})^{i-j} - 1interest rateti​,xday​=(∑j:ti​−tj​=xdayi​weighttj​​∑j:ti​−tj​=xdayi​share pricetj−1​​share pricetj​​​∗weighttj​​​)i−j−1
PIT‾ti,xday=∑j:ti−tj=xdayirewardTokenPriceInUSDtj−1underlyingTokenPriceInUSDtj−1∗(tj−tj−1)ti−tj\overline{PIT}_{t_{i},xday}=\frac{\sum_{j:t_{i}-t_{j}=xday}^{i}\frac{rewardTokenPriceInUSD_{t_{j-1}}}{underlyingTokenPriceInUSD_{t_{j-1}}} * (t_{j}-t_{j-1})}{t_{i}-t_{j}}PITti​,xday​=ti​−tj​∑j:ti​−tj​=xdayi​underlyingTokenPriceInUSDtj−1​​rewardTokenPriceInUSDtj−1​​​∗(tj​−tj−1​)​
APYti,xday=∑j:ti−tj=xdayiemissionsPerSecondtj−1×year×PIT‾tj,xday×(tj−tj−1)∑j:ti−tj=xdayiTVLtj×(tj−tj−1)\text{APY}_{t_{i},xday}=\frac{\sum_{j:t_{i}-t_{j}=xday}^{i}emissionsPerSecond_{t_{j-1}}\times year\times\overline{PIT}_{t_{j},xday}\times (t_{j}-t_{j-1}) }{\sum_{j:t_{i}-t_{j}=xday}^{i}TVL_{t_{j}}\times (t_{j}-t_{j-1}) }APYti​,xday​=∑j:ti​−tj​=xdayi​TVLtj​​×(tj​−tj−1​)∑j:ti​−tj​=xdayi​emissionsPerSecondtj−1​​×year×PITtj​,xday​×(tj​−tj−1​)​

To calculate APY for LSTs (e.g., ) and other vaults that periodically update their earnings (e.g., ), we use the totalSupply and getEthValue(totalSupply)functions.

Vaults that gradually increase the user's LP token balance, such as those on , are known as rebasing supply vaults. We calculate the share price for rebasing supply vaults with the totalSupply and scaledTotalSupply functions.

Vaults that do not compound automatically (e.g., ) are known as staking mechanism vaults. These vaults do not compound interest automatically, instead making users periodically harvest and redeposit it to maximize yield. Calculating returns in such scenarios can be complex, as the total shares:value ratio does not reflect share price accurately.

total principal value=sETH2.totalSupply()total rewards value=rETH2.totalSupply()TVL=total principal value+total rewards valueshare price=1+rETH2.rewardPerToken()totalSupply=TVLshare price\text{total principal value} = \text{sETH2.totalSupply()} \\ \text{total rewards value} = \text{rETH2.totalSupply()} \\ \text{TVL} = \text{total principal value} + \text{total rewards value} \\ \text{share price} = 1 + \text{rETH2.rewardPerToken()} \\ \text{totalSupply} = \frac{\text{TVL}}{\text{share price}} total principal value=sETH2.totalSupply()total rewards value=rETH2.totalSupply()TVL=total principal value+total rewards valueshare price=1+rETH2.rewardPerToken()totalSupply=share priceTVL​

are ERC-20 tokens that reflect investments in offchain financial assets. To assess the yield of RWAs we use:

total shares=totalSupply()share asset price=RWAOracle.price()underlying asset price=StablecoinOracle.price()total shares in USD=total shares×share asset pricetotal shares in asset=total shares in USDunderlying asset pricetotal shares value=total shares in asset\begin{align*} \text{total shares} &= \text{totalSupply()} \\ \text{share asset price} &= \text{RWAOracle.price()} \\ \text{underlying asset price} &= \text{StablecoinOracle.price()} \\ \text{total shares in USD} &= \text{total shares} \times \text{share asset price} \\ \text{total shares in asset} &= \frac{\text{total shares in USD}}{\text{underlying asset price}} \\ \text{total shares value} &= \text{total shares in asset} \end{align*} total sharesshare asset priceunderlying asset pricetotal shares in USDtotal shares in assettotal shares value​=totalSupply()=RWAOracle.price()=StablecoinOracle.price()=total shares×share asset price=underlying asset pricetotal shares in USD​=total shares in asset​
🔎
Lido
Yearn vaults
Aave
StakeWise
RWAs on vaults.fyi
vaults.fyi