The Liquidity Provider Lifecycle
Earning Yield
Ultimately the goal of the LP is to earn yield on their crypto. Currently we only offer support for yield on stablecoins, but look to support non-stables in the future. On the Imperial website, there is a Liquidity tab where any LP provider can swab USDT/C for LP tokens. There are a fixed number of LP tokens in existence, created de-novo for specifically this task and each Pool uses the same LP token and has a USDT and USDC Custody.
While each Pool started with some number of LP tokens and stables in it's Custodies, we expect due to fluctuating rates of returns between the Pools (which represent different volatility products) to cause net flows of stables and LP tokens between them by arbitrageurs overtime, leading to an overall average rate of return between all of the Pools.
Infrastructure
The actual swapping is done against the VolPerp contract, using the swap endpoint, which takes the following accounts and signature:
pub struct Swap<'info> {
#[account(mut)]
pub user: AccountInfo<'info>,
#[account(mut, associated_token::mint = custody_token_account.mint, associated_token::authority = custody)]
pub custody_token_account: Account<'info, TokenAccount>,
#[account(mut, associated_token::mint = custody_token_account.mint, associated_token::authority = user)]
pub user_custody_token_account: Account<'info, TokenAccount>,
#[account(mut, associated_token::mint = lp_token_account.mint, associated_token::authority = user)]
pub user_lp_token_account: Account<'info, TokenAccount>,
#[account(mut, associated_token::mint = lp_token_account.mint, associated_token::authority = pool)]
pub lp_token_account: Account<'info, TokenAccount>,
#[account(has_one = lp_token_account, seeds=[b"pool", pool.name.as_bytes().as_ref(), pool.state.key().as_ref(), pool.lp_mint.key().as_ref()], bump)]
pub pool: Account<'info, Pool>,
#[account(mut, has_one = pool, has_one = custody_token_account, seeds=[b"custody", pool.key().as_ref(), custody.mint.key().as_ref()], bump)]
pub custody: Account<'info, Custody>,
pub transfer_authority: Signer<'info>,
pub token_program: Program<'info, Token>,
}
pub fn handle_swap<'info>(
ctx: Context<'_, '_, 'info, 'info, Swap<'info>>,
amount_in: u64,
min_amount_out: u64,
lp_in: bool,
) -> Result<()> { /*..*/ }
Using this instruction, any LP can swap LP tokens in or out for stablecoins against a specific Pool and Custody using a constant product K = xy curve.
How is Yield Generated?
Concretely, yield is generated in primarily in two ways.
When certain fees are collected such as opening, closing, trade impact, or borrowing fees.
Opening and closing fees have identical settings and closely adhere to the constants set by the industry, ie Jupiter Perps
Borrowing fees are set by periodically checking T-bill rates and setting a min-max range for the dual slope model based on a reasonable range for a secured instrument in an offsetted window off the T-bill (say, +2 to +10)
For now trade impact is set to 0.
Last updated