primitivo-vault 0.0.1

Shared vault logic and account types for Primitivo
Documentation
use anchor_lang::prelude::*;
use primitivo_macro::Ownership;

include!(concat!(env!("OUT_DIR"), "/primitivo_vault_program_id.rs"));

#[account]
#[derive(InitSpace)]
pub struct VaultConfig {
    pub ownership: Ownership,
    pub seed_authority: Pubkey,
    pub underlying_mint: Pubkey,
    pub derivative_mint: Pubkey,
    pub underlying_vault: Pubkey,
    pub id: u64,
    pub underlying_assets: u64,
    pub derivative_decimals: u8,
    pub bump: u8,
    pub underlying_vault_bump: u8,
    pub derivative_mint_bump: u8,
}

#[error_code]
pub enum VaultError {
    #[msg("Amount must be greater than 0")]
    InvalidAmount,
    #[msg("Arithmetic overflow")]
    ArithmeticOverflow,
    #[msg("Invalid state")]
    InvalidState,
    #[msg("Computed amount is zero")]
    ZeroAmountOut,
}

pub fn quote_deposit_shares(
    amount_in: u64,
    underlying_assets: u64,
    derivative_supply: u64,
) -> Result<u64> {
    require!(amount_in > 0, VaultError::InvalidAmount);

    if derivative_supply == 0 || underlying_assets == 0 {
        return Ok(amount_in);
    }

    let shares = (amount_in as u128)
        .checked_mul(derivative_supply as u128)
        .ok_or(VaultError::ArithmeticOverflow)?
        .checked_div(underlying_assets as u128)
        .ok_or(VaultError::ArithmeticOverflow)?;

    let shares = u64::try_from(shares).map_err(|_| error!(VaultError::ArithmeticOverflow))?;
    require!(shares > 0, VaultError::ZeroAmountOut);
    Ok(shares)
}

pub fn quote_redeem_underlying(
    derivative_in: u64,
    underlying_assets: u64,
    derivative_supply: u64,
) -> Result<u64> {
    require!(derivative_in > 0, VaultError::InvalidAmount);
    require!(derivative_supply > 0, VaultError::InvalidState);
    require!(underlying_assets > 0, VaultError::InvalidState);

    let underlying_out = (derivative_in as u128)
        .checked_mul(underlying_assets as u128)
        .ok_or(VaultError::ArithmeticOverflow)?
        .checked_div(derivative_supply as u128)
        .ok_or(VaultError::ArithmeticOverflow)?;

    let underlying_out =
        u64::try_from(underlying_out).map_err(|_| error!(VaultError::ArithmeticOverflow))?;
    require!(underlying_out > 0, VaultError::ZeroAmountOut);
    Ok(underlying_out)
}

pub fn increase_underlying_assets(underlying_assets: &mut u64, amount: u64) -> Result<()> {
    *underlying_assets = underlying_assets
        .checked_add(amount)
        .ok_or(VaultError::ArithmeticOverflow)?;
    Ok(())
}

pub fn decrease_underlying_assets(underlying_assets: &mut u64, amount: u64) -> Result<()> {
    *underlying_assets = underlying_assets
        .checked_sub(amount)
        .ok_or(VaultError::ArithmeticOverflow)?;
    Ok(())
}