mango-v4/programs/mango-v4/src/instructions/token_register.rs

173 lines
5.7 KiB
Rust
Raw Normal View History

2022-02-22 01:09:09 -08:00
use anchor_lang::prelude::*;
2022-05-24 04:00:32 -07:00
use anchor_spl::token::{Mint, Token, TokenAccount};
2022-02-23 01:15:33 -08:00
use fixed::types::I80F48;
use fixed_macro::types::I80F48;
2022-02-22 01:09:09 -08:00
use crate::error::*;
2022-02-22 01:09:09 -08:00
use crate::state::*;
use crate::util::fill_from_str;
2022-02-22 01:09:09 -08:00
use crate::logs::TokenMetaDataLog;
pub const INDEX_START: I80F48 = I80F48!(1_000_000);
const FIRST_BANK_NUM: u32 = 0;
2022-02-22 01:09:09 -08:00
#[derive(Accounts)]
#[instruction(token_index: TokenIndex)]
pub struct TokenRegister<'info> {
2022-02-22 01:09:09 -08:00
#[account(
2022-02-23 01:19:54 -08:00
has_one = admin,
2022-02-22 01:09:09 -08:00
)]
2022-03-07 07:16:34 -08:00
pub group: AccountLoader<'info, Group>,
2022-02-23 01:19:54 -08:00
pub admin: Signer<'info>,
2022-02-22 01:09:09 -08:00
pub mint: Account<'info, Mint>,
2022-02-22 04:31:18 -08:00
#[account(
init,
// using the token_index in this seed guards against reusing it
seeds = [b"Bank".as_ref(), group.key().as_ref(), &token_index.to_le_bytes(), &FIRST_BANK_NUM.to_le_bytes()],
2022-02-22 04:31:18 -08:00
bump,
payer = payer,
2022-03-07 07:16:34 -08:00
space = 8 + std::mem::size_of::<Bank>(),
2022-02-22 04:31:18 -08:00
)]
2022-03-07 07:16:34 -08:00
pub bank: AccountLoader<'info, Bank>,
2022-02-22 04:31:18 -08:00
#[account(
init,
seeds = [b"Vault".as_ref(), group.key().as_ref(), &token_index.to_le_bytes(), &FIRST_BANK_NUM.to_le_bytes()],
2022-02-22 05:23:13 -08:00
bump,
token::authority = group,
token::mint = mint,
2022-02-22 04:31:18 -08:00
payer = payer
)]
pub vault: Account<'info, TokenAccount>,
2022-03-03 05:30:44 -08:00
#[account(
init,
// using the mint in this seed guards against registering the same mint twice
seeds = [b"MintInfo".as_ref(), group.key().as_ref(), mint.key().as_ref()],
2022-03-03 05:30:44 -08:00
bump,
payer = payer,
space = 8 + std::mem::size_of::<MintInfo>(),
)]
pub mint_info: AccountLoader<'info, MintInfo>,
/// CHECK: The oracle can be one of several different account types
pub oracle: UncheckedAccount<'info>,
2022-02-22 01:09:09 -08:00
#[account(mut)]
pub payer: Signer<'info>,
2022-02-22 04:31:18 -08:00
pub token_program: Program<'info, Token>,
2022-02-22 01:09:09 -08:00
pub system_program: Program<'info, System>,
pub rent: Sysvar<'info, Rent>,
}
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct InterestRateParams {
pub util0: f32,
pub rate0: f32,
pub util1: f32,
pub rate1: f32,
pub max_rate: f32,
pub adjustment_factor: f32,
}
#[allow(clippy::too_many_arguments)]
pub fn token_register(
ctx: Context<TokenRegister>,
token_index: TokenIndex,
name: String,
oracle_config: OracleConfigParams,
interest_rate_params: InterestRateParams,
loan_fee_rate: f32,
loan_origination_fee_rate: f32,
maint_asset_weight: f32,
init_asset_weight: f32,
maint_liab_weight: f32,
init_liab_weight: f32,
liquidation_fee: f32,
) -> Result<()> {
2022-07-04 04:13:11 -07:00
// Require token 0 to be in the insurance token
if token_index == QUOTE_TOKEN_INDEX {
require_keys_eq!(
ctx.accounts.group.load()?.insurance_mint,
ctx.accounts.mint.key()
);
}
let mut bank = ctx.accounts.bank.load_init()?;
2022-03-07 07:16:34 -08:00
*bank = Bank {
group: ctx.accounts.group.key(),
name: fill_from_str(&name)?,
mint: ctx.accounts.mint.key(),
vault: ctx.accounts.vault.key(),
oracle: ctx.accounts.oracle.key(),
deposit_index: INDEX_START,
borrow_index: INDEX_START,
cached_indexed_total_deposits: I80F48::ZERO,
cached_indexed_total_borrows: I80F48::ZERO,
indexed_deposits: I80F48::ZERO,
indexed_borrows: I80F48::ZERO,
index_last_updated: Clock::get()?.unix_timestamp,
bank_rate_last_updated: Clock::get()?.unix_timestamp,
// TODO: add a require! verifying relation between the parameters
avg_utilization: I80F48::ZERO,
adjustment_factor: I80F48::from_num(interest_rate_params.adjustment_factor),
util0: I80F48::from_num(interest_rate_params.util0),
rate0: I80F48::from_num(interest_rate_params.rate0),
util1: I80F48::from_num(interest_rate_params.util1),
rate1: I80F48::from_num(interest_rate_params.rate1),
max_rate: I80F48::from_num(interest_rate_params.max_rate),
collected_fees_native: I80F48::ZERO,
loan_origination_fee_rate: I80F48::from_num(loan_origination_fee_rate),
loan_fee_rate: I80F48::from_num(loan_fee_rate),
maint_asset_weight: I80F48::from_num(maint_asset_weight),
init_asset_weight: I80F48::from_num(init_asset_weight),
maint_liab_weight: I80F48::from_num(maint_liab_weight),
init_liab_weight: I80F48::from_num(init_liab_weight),
liquidation_fee: I80F48::from_num(liquidation_fee),
dust: I80F48::ZERO,
flash_loan_token_account_initial: u64::MAX,
flash_loan_approved_amount: 0,
token_index,
bump: *ctx.bumps.get("bank").ok_or(MangoError::SomeError)?,
mint_decimals: ctx.accounts.mint.decimals,
bank_num: 0,
oracle_conf_filter: oracle_config.to_oracle_config().conf_filter,
oracle_config: oracle_config.to_oracle_config(),
reserved: [0; 2464],
2022-02-22 01:09:09 -08:00
};
require_gt!(bank.max_rate, MINIMUM_MAX_RATE);
2022-03-03 05:30:44 -08:00
let mut mint_info = ctx.accounts.mint_info.load_init()?;
*mint_info = MintInfo {
group: ctx.accounts.group.key(),
token_index,
group_insurance_fund: 1,
padding1: Default::default(),
2022-03-03 05:30:44 -08:00
mint: ctx.accounts.mint.key(),
banks: Default::default(),
vaults: Default::default(),
2022-03-03 05:30:44 -08:00
oracle: ctx.accounts.oracle.key(),
registration_time: Clock::get()?.unix_timestamp.try_into().unwrap(),
reserved: [0; 2560],
2022-03-03 05:30:44 -08:00
};
mint_info.banks[0] = ctx.accounts.bank.key();
mint_info.vaults[0] = ctx.accounts.vault.key();
emit!(TokenMetaDataLog {
mango_group: ctx.accounts.group.key(),
mint: ctx.accounts.mint.key(),
token_index,
mint_decimals: ctx.accounts.mint.decimals,
oracle: ctx.accounts.oracle.key(),
mint_info: ctx.accounts.mint_info.key(),
});
2022-02-22 01:09:09 -08:00
Ok(())
}