Token Yield
cToken Yield
To compute the Annual Percentage Yield (APY) of an auto-compounding asset, it's important to account for both the compounding effect and the frequency of compounding. Auto-compounding assets typically reinvest generated returns automatically, allowing the earnings to compound and potentially increasing the overall yield. Below is a general approach to calculating APY for an auto-compounding asset:
-
Determine the Periodic Return: Identify the periodic return generated by the asset. This can include factors such as interest, dividends, or other forms of income. The periodic return is typically expressed as a decimal or percentage.
-
Determine the Compounding Frequency: Establish how frequently the returns are compounded—whether it's daily, weekly, monthly, or at another interval.
-
Apply the APY Formula: Use the following formula to calculate the APY:
Where:
- is the yield rate over a period (e.g., a year),
- is the number of compounding periods within that time frame.
For instance, if the periodic return is (5%) and the compounding frequency is monthly, the APY would be calculated as follows:
pToken Yield yield
Users can earn profit by holding pTokens from the time of purchase until the maturity date. To compute the APY of a pToken, we need two key values: its price at maturity and its current price. Additionally, to calculate the APR, we need to know the time remaining until maturity (expressed in years), which can be less than or greater than one year.
Initially, the user receives:
amount of cToken. By staking, they can then obtain:
And the starting value is the current price of the pToken, therefore we can calculate the apy as:
yToken Yield
For yTokens, we first calculate the ROI (Return on Investment) as follows:
Using this ROI, we then compute the APY with the following formula:
Note: The annual yield per yToken is the annualized change in the exchange rate. If we have the exchange rate for a given interval (e.g., 3 days), we can compute the annual yield as:
Auto-Compounding Effect of yToken
The yield mechanics of yToken have several important considerations:
- Yield Accrual: The yield accrues only when there is an increase in the exchange rate:
- No action is taken when the rate decreases.
- The rate is compared only with its immediately preceding value, regardless of whether it has been higher or lower at any previous point in time.
- Yield Paid in cToken: The yield is paid out in terms of cToken, meaning it can accrue additional yield itself, creating a form of auto-compounding. However, there are some nuances:
- Note: The value of cToken changes with both increasing and decreasing rates, so the yield rate on cToken differs from that of yToken.
Addressing the Points:
- Monitoring Increasing Rates: To handle the first point, we have implemented a dedicated monitoring system for yToken rewards that only records instances of increasing exchange rates. This straightforward solution ensures that the APY/APR of the yields is computed accurately.
- Handling cToken compounding: For the second point, the explained equation in previous section does not do anything, infact we assume that users will convert their reward to baseASSET (e.g. Atom) instantly and do not hold cToken. In order to handle this if we keep in mind that slashing might have an effect on the rates the equations would have some complexity which we will discuss.
Handling cToken Yield (Converting APR to APY)
As mentioned earlier, the auto-compounding for yToken operates uniquely, as we treat the cToken rewards as staked amounts. However, the reward rate for cToken differs from that of yToken due to the possibility of slashing. To calculate the exact reward amount, we perform the calculations for a single staked yToken, using the following variables:
- Lets say the annual reward for 1 staked yToken is .
- The annual reward rate for cToken is . (note:
- The yToken reaches maturity in years.
- We have compounding periods during a year (the yield is paid out times in a year)
Now we calculate the reward for the ’th compounding: for the staked yToken user would get cToken worth of Asset of reward. Given the reward rate of cToken this cToken will worth:
at maturity of the yToken, where is the time to maturity since this reward is paid out.
To calculate the we know that in one year we have compoundings then 1 compounding period is years, meaning the passed time untill the of compounding is and the remaining time to maturity is . Hence based on the previous equation the cToken reward would worth:
Now in order to compute the total reward at maturity we can do the following:
Note that the part is for the rewards when the apr is . Meaning that the yToken rewards to maturity is simply the cToken rewards multiplied by .
This can be plugged into the ROI formula from the previous section to calculate the roi and then the apy of yToken.
Pool Yield
In this section, we outline how to compute the yield of a pool. The yield consists of three key components:
- Profit from Swap Fees: The income earned through fees generated by swaps in the pool.
- Profit from Holding Pool Tokens: If the pool contains a yield-bearing asset, users can earn a profit simply by holding liquidity. For example, if the pool includes pToken, liquidity providers (LPs) can earn profit even without any swaps being performed on the pool, just by holding the asset in the pool.
- Profit from Staking LP Tokens: Additional profit can be earned by staking the LP tokens in modules like Incentives or Alliance.
Each of these components should be calculated separately, and the total pool yield can be obtained by summing them.
Swap Fee APR
To compute the APR from swap fees, we need to measure the swap fees over a given time window. This is done by identifying the first and last data points within the window and calculating the difference between them.
timeDifference
is the difference between two data points we have found. NOTE: swap protocol fee is the protocol fee for the swap events and not the join/exit events. For swap operations the swap protocol fee is taken from the swap fee, so we need to consider that in the equation.
Pool token Yield
As previously explained, when a user holds an LP token, they essentially hold a portion of the tokens within the pool. If any of these tokens generate yield, the user gains profit by holding a share of those tokens. Suppose a pool contains tokens, and the yield of token is represented as . The overall token yield can be computed as:
Where is the weight of token in the pool. The key here is to accurately calculate the yield of each individual token in the pool.
Alliance Yield of a Pool
To compute this portion of a pool's APR, we need to examine the incentives and alliance modules to determine if the pool's LP token can be staked in these modules to earn additional yield. If staking is possible, we should include the APR associated with staking the LP token.
In the alliance module, a set of assets can be defined (whitelisted), allowing users to stake these assets and receive a portion of the block rewards.
The process of reward distribution, is based on the token weights. This is from the original documents:
The amount of rewards an Alliance asset accrues is determined by the asset’s Reward Weight. This parameter is set by governance and represents the maximum proportion of rewards an asset will earn, relative to the total rewards of the chain. Native tokens always have a Reward Weight of
1
. For instance, imagine a chain has two staking assets: a native staking asset, and an Alliance asset called "AL1". If AL1 has a Reward Weight of.3
, the rewards shared by all stakers of the staked AL1 Alliance asset will be 23% of the total rewards of the chain. The remaining 77% of rewards will be distributed to users who stake the chain's native asset. To learn more about Reward Weights and calculations, visit the In-depth staking page.
Native staking rewards
To determine the APR of an alliance asset, you need to consider the following:
- Reward Distribution per Block: Determine the amount of reward distributed per block for the alliance asset.
- APR of the Native Asset Staking: Calculate the APR for staking the native asset. This requires tracking all delegated tokens and reward distributions, which can be done using events and queries from the
x/staking
module.
Computing the alliance apr
As described earlier, we have a set of assets in the alliance module, each with the following scheme:
The important properties of an asset are:
-
reward_weight
this is used to compute reward share for the asset which helps us compute apr of the asset -
reward_start_time
this is used to see if the asset is receiving any rewards, it should be used as: -
total_tokens
this shows the total tokens staked for this asset, which is used for apr computation.
now in order to compute the apr for assets, we should first filter the assets using the reward_start_time
and then compute the sum of rewards.
NOTE: we should also consider a weight = 1 for the native asset (upryzm). This is why we have a +1 in the equation.
Given the reward history from the previous section, we can calculate the reward for each asset in each block. First, determine the rewards per token within a specific time window by subtracting the total rewards at the beginning of the window from the total rewards at the end:
where is the total reward at the end and is total rewards at the start. the we can do the following to get rewards per bonded alliance token:
Where totalBonded is the total amount of staked native tokens which can be retrieved from the previous section. TotalTokens is the asset.total_tokens
which is total amount of staked alliance tokens of this asset. now we have total amount of rewards per token for the window, we can compute the apr:
Please note that the current value of the assets can be queried from the alliance module, currently there is no event for updating assets. However, this event might be added in a pr.
Incentives APR
In this document we discuss the indexing needed for computing the apr of an incentives pool.
The following events provide information about the total bonded amount and the rewards of an incentive pool.
Using the SetPool
event, we can always access the total bonded amount from bonded_token.amount
. Each time an EventIncentivizePool
occurs, we can calculate the reward amount per bonded token. To do this, we first convert the reward amount into a stable coin value, then divide this amount by the total bonded amount to obtain the reward per bonded token.
The reward per bonded token should be indexed per block, which can be achieved in two ways:
- Total Reward So Far: Track the cumulative reward from the first event (
totalReward
). - Reward per Block: Track the reward for each block (
blockReward
).
To compute the APR, we need to define a time window. Both methods can be used, with the configuration serving as the default value.
Given the time window, starting from the current time and going back as specified (e.g., 1 month), we first compute the total reward accrued during this period. This is done by finding the first and last items in the window and calculating the difference in totalReward
. Subsequently, we can use this information to compute the APR%:
where is the first data point, and is the last data point, is the block reward for data point and total is the total reward at the end of that block.