MangoAccount: Rename how tokens/serum3/perps data is stored

token_account_map -> tokens
serum3_account_map -> serum3
perp -> perps
This commit is contained in:
Christian Kamm 2022-04-02 11:21:41 +02:00
parent c567a2d330
commit cbc3cc7bbd
18 changed files with 91 additions and 98 deletions

View File

@ -32,9 +32,9 @@ pub fn create_account(ctx: Context<CreateAccount>, account_num: u8) -> Result<()
group: ctx.accounts.group.key(),
owner: ctx.accounts.owner.key(),
delegate: Pubkey::default(),
token_account_map: TokenAccountMap::new(),
serum3_account_map: Serum3AccountMap::new(),
perp: PerpData::new(),
tokens: MangoAccountTokens::new(),
serum3: MangoAccountSerum3::new(),
perps: MangoAccountPerps::new(),
being_liquidated: 0,
is_bankrupt: 0,
account_num,

View File

@ -60,7 +60,7 @@ pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
let mut account = ctx.accounts.account.load_mut()?;
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
let (position, position_index) = account.token_account_map.get_mut_or_create(token_index)?;
let (position, position_index) = account.tokens.get_mut_or_create(token_index)?;
// Update the bank and position
let position_is_active = {
@ -87,7 +87,7 @@ pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
// Deposits can deactivate a position if they cancel out a previous borrow.
//
if !position_is_active {
account.token_account_map.deactivate(position_index);
account.tokens.deactivate(position_index);
}
Ok(())

View File

@ -75,15 +75,12 @@ pub fn liq_token_with_token(
let liab_price = oracle_price(liab_oracle)?;
let liqee_assets_native = liqee
.token_account_map
.tokens
.get(asset_bank.token_index)?
.native(&asset_bank);
require!(liqee_assets_native.is_positive(), MangoError::SomeError);
let liqee_liab_native = liqee
.token_account_map
.get(liab_bank.token_index)?
.native(&liab_bank);
let liqee_liab_native = liqee.tokens.get(liab_bank.token_index)?.native(&liab_bank);
require!(liqee_liab_native.is_negative(), MangoError::SomeError);
// TODO why sum of both tokens liquidation fees? Add comment
@ -121,29 +118,17 @@ pub fn liq_token_with_token(
let asset_transfer = cm!(liab_transfer * liab_price_adjusted / asset_price);
// Apply the balance changes to the liqor and liqee accounts
liab_bank.deposit(
liqee.token_account_map.get_mut(liab_token_index)?,
liab_transfer,
)?;
liab_bank.deposit(liqee.tokens.get_mut(liab_token_index)?, liab_transfer)?;
liab_bank.withdraw(
liqor
.token_account_map
.get_mut_or_create(liab_token_index)?
.0,
liqor.tokens.get_mut_or_create(liab_token_index)?.0,
liab_transfer,
)?;
asset_bank.deposit(
liqor
.token_account_map
.get_mut_or_create(asset_token_index)?
.0,
asset_transfer,
)?;
asset_bank.withdraw(
liqee.token_account_map.get_mut(asset_token_index)?,
liqor.tokens.get_mut_or_create(asset_token_index)?.0,
asset_transfer,
)?;
asset_bank.withdraw(liqee.tokens.get_mut(asset_token_index)?, asset_transfer)?;
// Update the health cache
liqee_health_cache.adjust_token_balance(liab_token_index, liab_transfer)?;

View File

@ -39,7 +39,7 @@ pub fn margin_trade<'key, 'accounts, 'remaining, 'info>(
// total number of indexed positions, since
// user might end up withdrawing or depositing and activating a new indexed position
require!(
banks_len >= account.token_account_map.iter_active().count(),
banks_len >= account.tokens.iter_active().count(),
MangoError::SomeError // todo: SomeError
);
@ -173,10 +173,7 @@ fn adjust_for_post_cpi_amounts(
let bank_loader = AccountLoader::<'_, Bank>::try_from(bank_ai)?;
let mut bank = bank_loader.load_mut()?;
let position = account
.token_account_map
.get_mut_or_create(bank.token_index)?
.0;
let position = account.tokens.get_mut_or_create(bank.token_index)?.0;
// user has either withdrawn or deposited
bank.change(

View File

@ -50,10 +50,16 @@ pub fn perp_consume_events(ctx: Context<PerpConsumeEvents>, limit: usize) -> Res
Some(account_info) => account_info.load_mut::<MangoAccount>()?,
};
ma.perp
.execute_maker(perp_market.perp_market_index, &mut perp_market, fill)?;
ma.perp
.execute_taker(perp_market.perp_market_index, &mut perp_market, fill)?;
ma.perps.execute_maker(
perp_market.perp_market_index,
&mut perp_market,
fill,
)?;
ma.perps.execute_taker(
perp_market.perp_market_index,
&mut perp_market,
fill,
)?;
} else {
let mut maker = match mango_account_ais.iter().find(|ai| ai.key == &fill.maker)
{
@ -72,12 +78,12 @@ pub fn perp_consume_events(ctx: Context<PerpConsumeEvents>, limit: usize) -> Res
Some(account_info) => account_info.load_mut::<MangoAccount>()?,
};
maker.perp.execute_maker(
maker.perps.execute_maker(
perp_market.perp_market_index,
&mut perp_market,
fill,
)?;
taker.perp.execute_taker(
taker.perps.execute_taker(
perp_market.perp_market_index,
&mut perp_market,
fill,
@ -95,7 +101,7 @@ pub fn perp_consume_events(ctx: Context<PerpConsumeEvents>, limit: usize) -> Res
Some(account_info) => account_info.load_mut::<MangoAccount>()?,
};
ma.perp
ma.perps
.remove_order(out.owner_slot as usize, out.quantity)?;
}
EventType::Liquidate => {

View File

@ -59,7 +59,7 @@ pub fn serum3_cancel_order(
// Validate open_orders
require!(
account
.serum3_account_map
.serum3
.find(serum_market.market_index)
.ok_or_else(|| error!(MangoError::SomeError))?
.open_orders

View File

@ -50,9 +50,7 @@ pub fn serum3_create_open_orders(ctx: Context<Serum3CreateOpenOrders>) -> Result
let serum_market = ctx.accounts.serum_market.load()?;
let mut account = ctx.accounts.account.load_mut()?;
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
let serum_account = account
.serum3_account_map
.create(serum_market.market_index)?;
let serum_account = account.serum3.create(serum_market.market_index)?;
serum_account.open_orders = ctx.accounts.open_orders.key();
serum_account.base_token_index = serum_market.base_token_index;
serum_account.quote_token_index = serum_market.quote_token_index;
@ -61,11 +59,11 @@ pub fn serum3_create_open_orders(ctx: Context<Serum3CreateOpenOrders>) -> Result
// stay permanently blocked. Otherwise users may end up in situations where
// they can't settle a market because they don't have free token_account_map!
let (quote_position, _) = account
.token_account_map
.tokens
.get_mut_or_create(serum_market.quote_token_index)?;
quote_position.in_use_count += 1;
let (base_position, _) = account
.token_account_map
.tokens
.get_mut_or_create(serum_market.base_token_index)?;
base_position.in_use_count += 1;

View File

@ -71,7 +71,7 @@ pub fn serum3_liq_force_cancel_orders(
// Validate open_orders
require!(
account
.serum3_account_map
.serum3
.find(serum_market.market_index)
.ok_or_else(|| error!(MangoError::SomeError))?
.open_orders
@ -137,14 +137,14 @@ pub fn serum3_liq_force_cancel_orders(
let mut account = ctx.accounts.account.load_mut()?;
let mut base_bank = ctx.accounts.base_bank.load_mut()?;
let base_position = account.token_account_map.get_mut(base_bank.token_index)?;
let base_position = account.tokens.get_mut(base_bank.token_index)?;
base_bank.change(
base_position,
I80F48::from(after_base_vault) - I80F48::from(before_base_vault),
)?;
let mut quote_bank = ctx.accounts.quote_bank.load_mut()?;
let quote_position = account.token_account_map.get_mut(quote_bank.token_index)?;
let quote_position = account.tokens.get_mut(quote_bank.token_index)?;
quote_bank.change(
quote_position,
I80F48::from(after_quote_vault) - I80F48::from(before_quote_vault),

View File

@ -118,7 +118,7 @@ pub fn serum3_place_order(
// Validate open_orders
require!(
account
.serum3_account_map
.serum3
.find(serum_market.market_index)
.ok_or_else(|| error!(MangoError::SomeError))?
.open_orders
@ -189,14 +189,14 @@ pub fn serum3_place_order(
let mut account = ctx.accounts.account.load_mut()?;
let mut base_bank = ctx.accounts.base_bank.load_mut()?;
let base_position = account.token_account_map.get_mut(base_bank.token_index)?;
let base_position = account.tokens.get_mut(base_bank.token_index)?;
base_bank.change(
base_position,
I80F48::from(after_base_vault) - I80F48::from(before_base_vault),
)?;
let mut quote_bank = ctx.accounts.quote_bank.load_mut()?;
let quote_position = account.token_account_map.get_mut(quote_bank.token_index)?;
let quote_position = account.tokens.get_mut(quote_bank.token_index)?;
quote_bank.change(
quote_position,
I80F48::from(after_quote_vault) - I80F48::from(before_quote_vault),

View File

@ -70,7 +70,7 @@ pub fn serum3_settle_funds(ctx: Context<Serum3SettleFunds>) -> Result<()> {
// Validate open_orders
require!(
account
.serum3_account_map
.serum3
.find(serum_market.market_index)
.ok_or_else(|| error!(MangoError::SomeError))?
.open_orders
@ -124,14 +124,14 @@ pub fn serum3_settle_funds(ctx: Context<Serum3SettleFunds>) -> Result<()> {
let mut account = ctx.accounts.account.load_mut()?;
let mut base_bank = ctx.accounts.base_bank.load_mut()?;
let base_position = account.token_account_map.get_mut(base_bank.token_index)?;
let base_position = account.tokens.get_mut(base_bank.token_index)?;
base_bank.change(
base_position,
I80F48::from(after_base_vault) - I80F48::from(before_base_vault),
)?;
let mut quote_bank = ctx.accounts.quote_bank.load_mut()?;
let quote_position = account.token_account_map.get_mut(quote_bank.token_index)?;
let quote_position = account.tokens.get_mut(quote_bank.token_index)?;
quote_bank.change(
quote_position,
I80F48::from(after_quote_vault) - I80F48::from(before_quote_vault),

View File

@ -62,7 +62,7 @@ pub fn withdraw(ctx: Context<Withdraw>, amount: u64, allow_borrow: bool) -> Resu
let mut account = ctx.accounts.account.load_mut()?;
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
let (position, position_index) = account.token_account_map.get_mut_or_create(token_index)?;
let (position, position_index) = account.tokens.get_mut_or_create(token_index)?;
// The bank will also be passed in remainingAccounts. Use an explicit scope
// to drop the &mut before we borrow it immutably again later.
@ -115,7 +115,7 @@ pub fn withdraw(ctx: Context<Withdraw>, amount: u64, allow_borrow: bool) -> Resu
// deactivated.
//
if !position_is_active {
account.token_account_map.deactivate(position_index);
account.tokens.deactivate(position_index);
}
Ok(())

View File

@ -165,8 +165,8 @@ pub fn compute_health_from_fixed_accounts(
health_type: HealthType,
ais: &[AccountInfo],
) -> Result<I80F48> {
let active_token_len = account.token_account_map.iter_active().count();
let active_serum_len = account.serum3_account_map.iter_active().count();
let active_token_len = account.tokens.iter_active().count();
let active_serum_len = account.serum3.iter_active().count();
let expected_ais = active_token_len * 2 // banks + oracles
+ active_serum_len; // open_orders
require!(ais.len() == expected_ais, MangoError::SomeError);
@ -298,7 +298,7 @@ fn compute_health_detail<'a, 'b: 'a>(
) -> Result<HealthCache> {
// token contribution from token accounts
let mut token_infos = vec![];
for (i, position) in account.token_account_map.iter_active().enumerate() {
for (i, position) in account.tokens.iter_active().enumerate() {
let (bank, oracle_ai) =
retriever.bank_and_oracle(&account.group, i, position.token_index)?;
let oracle_price = oracle_price(oracle_ai)?;
@ -319,7 +319,7 @@ fn compute_health_detail<'a, 'b: 'a>(
}
// token contribution from serum accounts
for (i, serum_account) in account.serum3_account_map.iter_active().enumerate() {
for (i, serum_account) in account.serum3.iter_active().enumerate() {
let oo = retriever.serum_oo(i, &serum_account.open_orders)?;
if !allow_serum3 {
require!(

View File

@ -65,17 +65,22 @@ impl TokenAccount {
}
#[zero_copy]
pub struct TokenAccountMap {
pub struct MangoAccountTokens {
pub values: [TokenAccount; MAX_TOKEN_ACCOUNTS],
}
const_assert_eq!(
size_of::<MangoAccountTokens>(),
MAX_TOKEN_ACCOUNTS * size_of::<TokenAccount>()
);
const_assert_eq!(size_of::<MangoAccountTokens>() % 8, 0);
impl Default for TokenAccountMap {
impl Default for MangoAccountTokens {
fn default() -> Self {
Self::new()
}
}
impl TokenAccountMap {
impl MangoAccountTokens {
pub fn new() -> Self {
Self {
values: [TokenAccount {
@ -186,17 +191,22 @@ impl Default for Serum3Account {
}
#[zero_copy]
pub struct Serum3AccountMap {
pub struct MangoAccountSerum3 {
pub values: [Serum3Account; MAX_SERUM3_ACCOUNTS],
}
const_assert_eq!(
size_of::<MangoAccountSerum3>(),
MAX_SERUM3_ACCOUNTS * size_of::<Serum3Account>()
);
const_assert_eq!(size_of::<MangoAccountSerum3>() % 8, 0);
impl Default for Serum3AccountMap {
impl Default for MangoAccountSerum3 {
fn default() -> Self {
Self::new()
}
}
impl Serum3AccountMap {
impl MangoAccountSerum3 {
pub fn new() -> Self {
Self {
values: [Serum3Account::default(); MAX_SERUM3_ACCOUNTS],
@ -308,7 +318,7 @@ impl PerpAccount {
}
#[zero_copy]
pub struct PerpData {
pub struct MangoAccountPerps {
pub accounts: [PerpAccount; MAX_PERP_ACCOUNTS],
// TODO: possibly it's more convenient to store a single list of PerpOpenOrder structs?
@ -318,12 +328,12 @@ pub struct PerpData {
pub order_client_id: [u64; MAX_PERP_OPEN_ORDERS],
}
const_assert_eq!(
size_of::<PerpData>(),
size_of::<MangoAccountPerps>(),
MAX_PERP_ACCOUNTS * size_of::<PerpAccount>() + MAX_PERP_OPEN_ORDERS * (2 + 1 + 16 + 8)
);
const_assert_eq!(size_of::<PerpData>() % 8, 0);
const_assert_eq!(size_of::<MangoAccountPerps>() % 8, 0);
impl PerpData {
impl MangoAccountPerps {
pub fn new() -> Self {
Self {
accounts: [PerpAccount::default(); MAX_PERP_ACCOUNTS],
@ -491,7 +501,7 @@ impl PerpData {
}
}
impl Default for PerpData {
impl Default for MangoAccountPerps {
fn default() -> Self {
Self::new()
}
@ -507,13 +517,13 @@ pub struct MangoAccount {
// Maps token_index -> deposit/borrow account for each token
// that is active on this MangoAccount.
pub token_account_map: TokenAccountMap,
pub tokens: MangoAccountTokens,
// Maps serum_market_index -> open orders for each serum market
// that is active on this MangoAccount.
pub serum3_account_map: Serum3AccountMap,
pub serum3: MangoAccountSerum3,
pub perp: PerpData,
pub perps: MangoAccountPerps,
/// This account cannot open new positions or borrow until `init_health >= 0`
pub being_liquidated: u8,
@ -530,9 +540,9 @@ pub struct MangoAccount {
const_assert_eq!(
size_of::<MangoAccount>(),
3 * 32
+ MAX_TOKEN_ACCOUNTS * size_of::<TokenAccount>()
+ MAX_SERUM3_ACCOUNTS * size_of::<Serum3Account>()
+ size_of::<PerpData>()
+ size_of::<MangoAccountTokens>()
+ size_of::<MangoAccountSerum3>()
+ size_of::<MangoAccountPerps>()
+ 4
+ 4
);

View File

@ -336,7 +336,7 @@ impl<'a> Book<'a> {
}
let owner_slot = mango_account
.perp
.perps
.next_order_slot()
.ok_or_else(|| error!(MangoError::SomeError))?;
let new_order = LeafNode::new(
@ -397,7 +397,7 @@ fn apply_fees(
let taker_fees = taker_quote_native * market.taker_fee;
let perp_account = mango_account
.perp
.perps
.get_account_mut_or_create(market.perp_market_index)?
.0;
perp_account.quote_position_native -= taker_fees;

View File

@ -110,7 +110,7 @@ async fn derive_health_check_remaining_account_metas(
// figure out all the banks/oracles that need to be passed for the health check
let mut banks = vec![];
let mut oracles = vec![];
for position in account.token_account_map.iter_active() {
for position in account.tokens.iter_active() {
let mint_info =
get_mint_info_by_token_index(account_loader, account, position.token_index).await;
// TODO: ALTs are unavailable
@ -129,7 +129,7 @@ async fn derive_health_check_remaining_account_metas(
// If there is not yet an active position for the token, we need to pass
// the bank/oracle for health check anyway.
let new_position = account
.token_account_map
.tokens
.values
.iter()
.position(|p| !p.is_active())
@ -140,10 +140,7 @@ async fn derive_health_check_remaining_account_metas(
}
}
let serum_oos = account
.serum3_account_map
.iter_active()
.map(|&s| s.open_orders);
let serum_oos = account.serum3.iter_active().map(|&s| s.open_orders);
banks
.iter()
@ -175,9 +172,9 @@ async fn derive_liquidation_remaining_account_metas(
let mut banks = vec![];
let mut oracles = vec![];
let token_indexes = liqee
.token_account_map
.tokens
.iter_active()
.chain(liqor.token_account_map.iter_active())
.chain(liqor.tokens.iter_active())
.map(|ta| ta.token_index)
.unique();
for token_index in token_indexes {
@ -199,9 +196,9 @@ async fn derive_liquidation_remaining_account_metas(
}
let serum_oos = liqee
.serum3_account_map
.serum3
.iter_active()
.chain(liqor.serum3_account_map.iter_active())
.chain(liqor.serum3.iter_active())
.map(|&s| s.open_orders);
banks
@ -232,7 +229,7 @@ pub async fn account_position(solana: &SolanaCookie, account: Pubkey, bank: Pubk
let account_data: MangoAccount = solana.get_account(account).await;
let bank_data: Bank = solana.get_account(bank).await;
let native = account_data
.token_account_map
.tokens
.find(bank_data.token_index)
.unwrap()
.native(&bank_data);
@ -266,7 +263,7 @@ impl<'keypair> ClientInstruction for MarginTradeInstruction<'keypair> {
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
let instruction = Self::Instruction {
banks_len: account.token_account_map.iter_active().count(),
banks_len: account.tokens.iter_active().count(),
cpi_data: self.margin_trade_program_ix_cpi_data.clone(),
};
@ -876,7 +873,7 @@ impl<'keypair> ClientInstruction for Serum3PlaceOrderInstruction<'keypair> {
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap();
let open_orders = account
.serum3_account_map
.serum3
.find(serum_market.market_index)
.unwrap()
.open_orders;
@ -971,7 +968,7 @@ impl<'keypair> ClientInstruction for Serum3CancelOrderInstruction<'keypair> {
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap();
let open_orders = account
.serum3_account_map
.serum3
.find(serum_market.market_index)
.unwrap()
.open_orders;
@ -1030,7 +1027,7 @@ impl<'keypair> ClientInstruction for Serum3SettleFundsInstruction<'keypair> {
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap();
let open_orders = account
.serum3_account_map
.serum3
.find(serum_market.market_index)
.unwrap()
.open_orders;
@ -1104,7 +1101,7 @@ impl ClientInstruction for Serum3LiqForceCancelOrdersInstruction {
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap();
let open_orders = account
.serum3_account_map
.serum3
.find(serum_market.market_index)
.unwrap()
.open_orders;

View File

@ -84,7 +84,7 @@ async fn test_margin_trade() -> Result<(), TransportError> {
let account_data: MangoAccount = solana.get_account(account).await;
let bank_data: Bank = solana.get_account(bank).await;
assert!(
account_data.token_account_map.values[0].native(&bank_data)
account_data.tokens.values[0].native(&bank_data)
- I80F48::from_num(deposit_amount_initial)
< dust_threshold
);

View File

@ -120,7 +120,7 @@ async fn test_position_lifetime() -> Result<()> {
// Check that positions are fully deactivated
let account: MangoAccount = solana.get_account(account).await;
assert_eq!(account.token_account_map.iter_active().count(), 0);
assert_eq!(account.tokens.iter_active().count(), 0);
// No user tokens got lost
for &payer_token in payer_mint_accounts {
@ -199,7 +199,7 @@ async fn test_position_lifetime() -> Result<()> {
// Check that positions are fully deactivated
let account: MangoAccount = solana.get_account(account).await;
assert_eq!(account.token_account_map.iter_active().count(), 0);
assert_eq!(account.tokens.iter_active().count(), 0);
// No user tokens got lost
for &payer_token in payer_mint_accounts {

View File

@ -127,7 +127,7 @@ async fn test_serum() -> Result<(), TransportError> {
let account_data: MangoAccount = solana.get_account(account).await;
assert_eq!(
account_data
.serum3_account_map
.serum3
.iter_active()
.map(|v| (v.open_orders, v.market_index))
.collect::<Vec<_>>(),