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;
|
2022-02-26 03:04:42 -08:00
|
|
|
use fixed_macro::types::I80F48;
|
2022-02-22 01:09:09 -08:00
|
|
|
|
2022-03-31 00:25:47 -07:00
|
|
|
// TODO: ALTs are unavailable
|
|
|
|
//use crate::address_lookup_table;
|
2022-05-19 04:45:46 -07:00
|
|
|
use crate::error::*;
|
2022-02-22 01:09:09 -08:00
|
|
|
use crate::state::*;
|
2022-04-12 11:23:45 -07:00
|
|
|
use crate::util::fill16_from_str;
|
2022-02-22 01:09:09 -08:00
|
|
|
|
2022-06-27 02:27:17 -07:00
|
|
|
pub const INDEX_START: I80F48 = I80F48!(1_000_000);
|
2022-02-26 03:04:42 -08:00
|
|
|
|
2022-02-22 01:09:09 -08:00
|
|
|
#[derive(Accounts)]
|
2022-06-27 02:27:17 -07:00
|
|
|
#[instruction(token_index: TokenIndex, bank_num: u64)]
|
2022-06-09 09:27:31 -07:00
|
|
|
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,
|
2022-03-14 05:47:34 -07:00
|
|
|
// using the token_index in this seed guards against reusing it
|
2022-06-27 02:27:17 -07:00
|
|
|
seeds = [group.key().as_ref(), b"Bank".as_ref(), &token_index.to_le_bytes(), &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,
|
2022-06-27 02:27:17 -07:00
|
|
|
seeds = [group.key().as_ref(), b"Vault".as_ref(), &token_index.to_le_bytes(), &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,
|
2022-03-14 05:47:34 -07:00
|
|
|
// using the mint in this seed guards against registering the same mint twice
|
2022-03-11 11:10:15 -08:00
|
|
|
seeds = [group.key().as_ref(), b"MintInfo".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>,
|
|
|
|
|
2022-06-22 03:45:42 -07:00
|
|
|
/// CHECK: The oracle can be one of several different account types
|
2022-02-28 05:44:08 -08:00
|
|
|
pub oracle: UncheckedAccount<'info>,
|
|
|
|
|
2022-03-03 05:30:44 -08:00
|
|
|
// Creating an address lookup table needs a recent valid slot as an
|
|
|
|
// input argument. That makes creating ALTs from governance instructions
|
|
|
|
// impossible. Hence the ALT that this instruction uses must be created
|
|
|
|
// externally and the admin is responsible for placing banks/oracles into
|
|
|
|
// sensible address lookup tables.
|
|
|
|
// constraint: must be created, have the admin authority and have free space
|
2022-03-31 00:25:47 -07:00
|
|
|
// TODO: ALTs are unavailable
|
|
|
|
//#[account(mut)]
|
|
|
|
//pub address_lookup_table: UncheckedAccount<'info>, // TODO: wrapper?
|
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>,
|
2022-03-31 00:25:47 -07:00
|
|
|
|
|
|
|
// TODO: ALTs are unavailable
|
|
|
|
//pub address_lookup_table_program: UncheckedAccount<'info>, // TODO: force address?
|
2022-02-22 01:09:09 -08:00
|
|
|
pub rent: Sysvar<'info, Rent>,
|
|
|
|
}
|
|
|
|
|
2022-04-12 07:53:45 -07:00
|
|
|
#[derive(AnchorSerialize, AnchorDeserialize, Default)]
|
|
|
|
pub struct InterestRateParams {
|
2022-04-12 08:33:42 -07:00
|
|
|
pub util0: f32,
|
|
|
|
pub rate0: f32,
|
|
|
|
pub util1: f32,
|
|
|
|
pub rate1: f32,
|
|
|
|
pub max_rate: f32,
|
2022-04-12 07:53:45 -07:00
|
|
|
}
|
|
|
|
|
2022-02-22 01:09:09 -08:00
|
|
|
// TODO: should this be "configure_mint", we pass an explicit index, and allow
|
|
|
|
// overwriting config as long as the mint account stays the same?
|
2022-04-09 07:53:30 -07:00
|
|
|
#[allow(clippy::too_many_arguments)]
|
2022-06-09 09:27:31 -07:00
|
|
|
pub fn token_register(
|
|
|
|
ctx: Context<TokenRegister>,
|
2022-03-14 05:19:50 -07:00
|
|
|
token_index: TokenIndex,
|
2022-06-27 02:27:17 -07:00
|
|
|
bank_num: u64,
|
2022-04-12 07:19:58 -07:00
|
|
|
name: String,
|
2022-06-18 07:38:46 -07:00
|
|
|
oracle_config: OracleConfig,
|
2022-04-12 07:53:45 -07:00
|
|
|
interest_rate_params: InterestRateParams,
|
2022-05-09 02:14:50 -07:00
|
|
|
loan_fee_rate: f32,
|
|
|
|
loan_origination_fee_rate: f32,
|
2022-02-25 09:29:54 -08:00
|
|
|
maint_asset_weight: f32,
|
|
|
|
init_asset_weight: f32,
|
|
|
|
maint_liab_weight: f32,
|
|
|
|
init_liab_weight: f32,
|
2022-03-26 11:34:44 -07:00
|
|
|
liquidation_fee: f32,
|
2022-02-25 09:29:54 -08:00
|
|
|
) -> Result<()> {
|
2022-03-31 00:25:47 -07:00
|
|
|
// TODO: Error if mint is already configured (technically, init of vault will fail)
|
2022-02-26 03:04:42 -08:00
|
|
|
|
2022-06-27 02:27:17 -07:00
|
|
|
require_eq!(bank_num, 0);
|
|
|
|
|
2022-02-26 03:04:42 -08:00
|
|
|
let mut bank = ctx.accounts.bank.load_init()?;
|
2022-03-07 07:16:34 -08:00
|
|
|
*bank = Bank {
|
2022-04-12 11:23:45 -07:00
|
|
|
name: fill16_from_str(name)?,
|
2022-02-26 03:17:20 -08:00
|
|
|
group: ctx.accounts.group.key(),
|
|
|
|
mint: ctx.accounts.mint.key(),
|
|
|
|
vault: ctx.accounts.vault.key(),
|
2022-02-28 05:44:08 -08:00
|
|
|
oracle: ctx.accounts.oracle.key(),
|
2022-06-18 07:38:46 -07:00
|
|
|
oracle_config,
|
2022-02-26 03:04:42 -08:00
|
|
|
deposit_index: INDEX_START,
|
|
|
|
borrow_index: INDEX_START,
|
|
|
|
indexed_total_deposits: I80F48::ZERO,
|
|
|
|
indexed_total_borrows: I80F48::ZERO,
|
2022-06-27 02:27:17 -07:00
|
|
|
indexed_deposits: I80F48::ZERO,
|
|
|
|
indexed_borrows: I80F48::ZERO,
|
2022-04-09 07:53:30 -07:00
|
|
|
last_updated: Clock::get()?.unix_timestamp,
|
2022-04-12 07:53:45 -07:00
|
|
|
// TODO: add a require! verifying relation between the parameters
|
|
|
|
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),
|
2022-05-09 02:14:50 -07:00
|
|
|
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),
|
2022-02-25 09:29:54 -08:00
|
|
|
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),
|
2022-03-26 11:34:44 -07:00
|
|
|
liquidation_fee: I80F48::from_num(liquidation_fee),
|
2022-03-04 04:33:27 -08:00
|
|
|
dust: I80F48::ZERO,
|
2022-03-14 05:19:50 -07:00
|
|
|
token_index,
|
2022-05-19 04:45:46 -07:00
|
|
|
bump: *ctx.bumps.get("bank").ok_or(MangoError::SomeError)?,
|
2022-05-27 05:52:03 -07:00
|
|
|
mint_decimals: ctx.accounts.mint.decimals,
|
2022-06-27 02:27:17 -07:00
|
|
|
bank_num: 0,
|
|
|
|
reserved: Default::default(),
|
2022-02-22 01:09:09 -08:00
|
|
|
};
|
2022-02-26 03:04:42 -08:00
|
|
|
|
2022-03-31 00:25:47 -07:00
|
|
|
// TODO: ALTs are unavailable
|
|
|
|
// let alt_previous_size =
|
|
|
|
// address_lookup_table::addresses(&ctx.accounts.address_lookup_table.try_borrow_data()?)
|
|
|
|
// .len();
|
|
|
|
let address_lookup_table = Pubkey::default();
|
|
|
|
let alt_previous_size = 0;
|
2022-03-03 05:30:44 -08:00
|
|
|
let mut mint_info = ctx.accounts.mint_info.load_init()?;
|
|
|
|
*mint_info = MintInfo {
|
2022-04-03 10:07:43 -07:00
|
|
|
group: ctx.accounts.group.key(),
|
2022-03-03 05:30:44 -08:00
|
|
|
mint: ctx.accounts.mint.key(),
|
2022-06-27 02:27:17 -07:00
|
|
|
banks: Default::default(),
|
|
|
|
vaults: Default::default(),
|
2022-03-03 05:30:44 -08:00
|
|
|
oracle: ctx.accounts.oracle.key(),
|
2022-04-01 01:42:33 -07:00
|
|
|
address_lookup_table,
|
2022-04-03 10:07:43 -07:00
|
|
|
token_index,
|
2022-03-03 05:30:44 -08:00
|
|
|
address_lookup_table_bank_index: alt_previous_size as u8,
|
|
|
|
address_lookup_table_oracle_index: alt_previous_size as u8 + 1,
|
2022-03-31 05:37:05 -07:00
|
|
|
reserved: Default::default(),
|
2022-03-03 05:30:44 -08:00
|
|
|
};
|
|
|
|
|
2022-06-27 02:27:17 -07:00
|
|
|
mint_info.banks[0] = ctx.accounts.bank.key();
|
|
|
|
mint_info.vaults[0] = ctx.accounts.vault.key();
|
|
|
|
|
2022-03-31 00:25:47 -07:00
|
|
|
// TODO: ALTs are unavailable
|
|
|
|
/*
|
2022-03-03 05:30:44 -08:00
|
|
|
address_lookup_table::extend(
|
|
|
|
ctx.accounts.address_lookup_table.to_account_info(),
|
|
|
|
// TODO: is using the admin as ALT authority a good idea?
|
|
|
|
ctx.accounts.admin.to_account_info(),
|
|
|
|
ctx.accounts.payer.to_account_info(),
|
|
|
|
&[],
|
|
|
|
vec![ctx.accounts.bank.key(), ctx.accounts.oracle.key()],
|
|
|
|
)?;
|
2022-03-31 00:25:47 -07:00
|
|
|
*/
|
2022-03-03 05:30:44 -08:00
|
|
|
|
2022-02-22 01:09:09 -08:00
|
|
|
Ok(())
|
|
|
|
}
|