Yield AMM
Yield AMM (YAMM) pools cater to the unique requirements of principal and yield token trading. Each refractable asset has a corresponding pool, comprising cAsset and active pAsset tokens as liquidity. As time progresses and new maturity levels are introduced (or old ones expire), the amm module automatically updates the related pAssets in the respective pools.
Preliminaries
The refractor exchange rate is the ratio of the total supply of pAsset to the cAsset amount in the Refractor vault.
This rate at time is denoted as . If a user refracts a cAsset amount , they will receive of pAsset and an identical amount of yAsset.
The yield rate to maturity for a specific pAsset can be calculated using the formula
where is the pAsset's market price (in terms of the cAsset) and is the pAsset's time to maturity.
Design
YAMM utilizes Balancer's constant weighted geometric mean formula, expressed as
where, for each , and denote the balance and weight of token in the pool, respectively, and is a real number. Token represents the cAsset while tokens , , , are the pool's pAssets.
In the YAMM model, weights vary over time. We also incorporate virtual balances and leverage parameters to ensure that the balance curves for the cAsset and any pAsset progressively flatten, mirroring the balance curve of the YieldSpace AMM. YAMM trading adheres to standard Balancer formulas.
To account for a token's time to maturity, we introduce the parameter, computed as:
In this formula, signifies each pAsset, and denote the initial and maturity time of the pAsset, respectively, and represents the current time. Note that equals 0 and equals 1. For all , is set to 1. The expression represents the scaled time to maturity of token , which varies from 0 to 1.
Leverage Parameters
The YAMM utilizes leverage parameters for each pAsset in the pool to enhance pricing precision for traders and replicate the YieldSpace curve. Denoted as , these parameters are dynamic and time-dependent. For each , we define the leverage parameter as:
To avoid numerical issues when nears , it's essential to cap the leverage parameter ; we set this limit at . It's worth noting that in practice, we enforce a configurable maximum parameter to limit the alpha parameter, not the fixed value used here.
Lambda Parameter
The lambda parameter is another leverage parameter for the cAsset, denoted by . This parameter is constant for each pool and must meet the condition . A larger results in flatter curves and better trader prices, but less price discovery. We suggest a default , although this can be configured per pool.
Parameter
Parameter gauges the pool's liquidity. At all times, should equal the number of LP tokens in circulation. We also recommend that the initial number of LP tokens assigned to the pool creator—or the initial liquidity provider—should equal the quantity of cAsset deposited when the pool is established. As such, 's initial value is .
Virtual Adjustment Balances
To facilitate smooth transitions when adding or removing pAssets from the pool, we introduce virtual adjustment balances. These are amounts added to the YAMM pool's virtual balances, and are time-dependent functions. Generally zero, these balances deviate from zero when a new token is added to the pool or an existing one is removed. In these cases, the corresponding virtual adjustment balance will incrementally increase or decrease. Each pAsset in the pool has a corresponding virtual adjustment balance, denoted by .
Virtual adjustment balances are defined using parameter as follows. For each we define:
The function is defined as:
-
When pAsset is added to the pool:
Here, is when the new pAsset is added to the pool, is the time during which the virtual adjustment balance gradually decreases to , and . In the implementation, corresponds to the configurable property
introduction_virtual_balance_scaler
. can be any appropriate time duration (e.g., a week, fortnight, month) that allows a gradual decay of the virtual adjustment balance. Note that at , and at , . -
When pAsset is removed from the pool, we denote the time of maturity of the pAsset by and the length of the asset removal period by (for instance, a week). We then define as follows:
Here, and . As mentioned in the introduction, we don't use a constant in the implementation. Instead, this constant can be configured through the
expiration_virtual_balance_scaler
property. It's important to note that can be as large as possible, meaning the virtual balance continues to increase even after the interval has ended. This process continues until the token balance is zero, at which point it is removed from the pool. -
If the above conditions do not apply, then for all .
To manage the virtual adjustment balances, we store an object of the following type for introducing or removing tokens:
message VirtualBalancePoolToken {
uint64 pool_id = 1;
string denom = 2;
string target_virtual_balance = 3 [
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
int64 start_unix_millis = 4;
int64 end_unix_millis = 5;
}
The target virtual balance represents the scaler parameter used in calculating . For introducing tokens it corresponds to the parameter, set as introduction_virtual_balance_scaler
, while for expiring tokens it is set as expiration_virtual_balance_scaler
.
Virtual Balances
The pool has virtual balances for trading, defined as follows. Let