Rearrange MangoAccount to avoid padding bytes

This commit is contained in:
Christian Kamm 2022-03-31 14:01:08 +02:00
parent 5470dc998a
commit 9cf4f1a748
14 changed files with 54 additions and 28 deletions

View File

@ -39,11 +39,11 @@ pub fn create_account(ctx: Context<CreateAccount>, account_num: u8) -> Result<()
order_side: [Side::Bid; MAX_PERP_OPEN_ORDERS],
orders: [i128::MAX; MAX_PERP_OPEN_ORDERS],
client_order_ids: [u64::MAX; MAX_PERP_OPEN_ORDERS],
being_liquidated: false,
is_bankrupt: false,
being_liquidated: 0,
is_bankrupt: 0,
account_num,
bump: *ctx.bumps.get("account").ok_or(MangoError::SomeError)?,
reserved: [0; 5],
reserved: [0; 4],
};
Ok(())

View File

@ -56,7 +56,7 @@ pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
// Get the account's position for that token index
let mut account = ctx.accounts.account.load_mut()?;
require!(!account.is_bankrupt, MangoError::IsBankrupt);
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
let (position, position_index) = account.token_account_map.get_mut_or_create(token_index)?;

View File

@ -38,24 +38,24 @@ pub fn liq_token_with_token(
let account_retriever = ScanningAccountRetriever::new(ctx.remaining_accounts, group_pk)?;
let mut liqor = ctx.accounts.liqor.load_mut()?;
require!(!liqor.is_bankrupt, MangoError::IsBankrupt);
require!(liqor.is_bankrupt == 0, MangoError::IsBankrupt);
let mut liqee = ctx.accounts.liqee.load_mut()?;
require!(!liqee.is_bankrupt, MangoError::IsBankrupt);
require!(liqee.is_bankrupt == 0, MangoError::IsBankrupt);
// Initial liqee health check
let mut liqee_health_cache = health_cache_for_liqee(&liqee, &account_retriever)?;
let init_health = liqee_health_cache.health(HealthType::Init)?;
if liqee.being_liquidated {
if liqee.being_liquidated != 0 {
if init_health > I80F48::ZERO {
liqee.being_liquidated = false;
liqee.being_liquidated = 0;
msg!("Liqee init_health above zero");
return Ok(());
}
} else {
let maint_health = liqee_health_cache.health(HealthType::Maint)?;
require!(maint_health < I80F48::ZERO, MangoError::SomeError);
liqee.being_liquidated = true;
liqee.being_liquidated = 1;
}
//
@ -165,7 +165,7 @@ pub fn liq_token_with_token(
// this is equivalent to one native USDC or 1e-6 USDC
// This is used as threshold to flip flag instead of 0 because of dust issues
liqee.being_liquidated = init_health < -I80F48::ONE;
liqee.being_liquidated = if init_health < -I80F48::ONE { 1 } else { 0 };
}
// Check liqor's health

View File

@ -27,7 +27,7 @@ pub fn margin_trade<'key, 'accounts, 'remaining, 'info>(
) -> Result<()> {
let group = ctx.accounts.group.load()?;
let mut account = ctx.accounts.account.load_mut()?;
require!(!account.is_bankrupt, MangoError::IsBankrupt);
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
// remaining_accounts layout is expected as follows
// * banks_len number of banks

View File

@ -51,7 +51,7 @@ pub fn place_perp_order(
limit: u8,
) -> Result<()> {
let mut mango_account = ctx.accounts.account.load_mut()?;
require!(!mango_account.is_bankrupt, MangoError::IsBankrupt);
require!(mango_account.is_bankrupt == 0, MangoError::IsBankrupt);
let mango_account_pk = ctx.accounts.account.key();
let mut perp_market = ctx.accounts.perp_market.load_mut()?;

View File

@ -95,7 +95,7 @@ pub fn serum3_cancel_order(
//
{
let account = ctx.accounts.account.load()?;
require!(!account.is_bankrupt, MangoError::IsBankrupt);
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
let serum_market = ctx.accounts.serum_market.load()?;

View File

@ -49,7 +49,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, MangoError::IsBankrupt);
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
let serum_account = account
.serum3_account_map
.create(serum_market.market_index)?;

View File

@ -65,7 +65,7 @@ pub fn serum3_liq_force_cancel_orders(
//
{
let account = ctx.accounts.account.load()?;
require!(!account.is_bankrupt, MangoError::IsBankrupt);
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
let serum_market = ctx.accounts.serum_market.load()?;
// Validate open_orders

View File

@ -157,7 +157,7 @@ pub fn serum3_place_order(
//
{
let account = ctx.accounts.account.load()?;
require!(!account.is_bankrupt, MangoError::IsBankrupt);
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
let serum_market = ctx.accounts.serum_market.load()?;
// Validate open_orders

View File

@ -64,7 +64,7 @@ pub fn serum3_settle_funds(ctx: Context<Serum3SettleFunds>) -> Result<()> {
//
{
let account = ctx.accounts.account.load()?;
require!(!account.is_bankrupt, MangoError::IsBankrupt);
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
let serum_market = ctx.accounts.serum_market.load()?;
// Validate open_orders

View File

@ -58,7 +58,7 @@ pub fn withdraw(ctx: Context<Withdraw>, amount: u64, allow_borrow: bool) -> Resu
// Get the account's position for that token index
let mut account = ctx.accounts.account.load_mut()?;
require!(!account.is_bankrupt, MangoError::IsBankrupt);
require!(account.is_bankrupt == 0, MangoError::IsBankrupt);
let (position, position_index) = account.token_account_map.get_mut_or_create(token_index)?;

View File

@ -206,6 +206,7 @@ mod tests {
indexed_value: I80F48::ZERO,
token_index: 0,
in_use_count: if is_in_use { 1 } else { 0 },
reserved: [0; 5],
};
account.indexed_value = indexed(I80F48::from_num(start), &bank);

View File

@ -1,5 +1,7 @@
use anchor_lang::prelude::*;
use fixed::types::I80F48;
use static_assertions::const_assert_eq;
use std::mem::size_of;
use crate::error::*;
use crate::state::*;
@ -33,8 +35,11 @@ pub struct TokenAccount {
/// incremented when a market requires this position to stay alive
pub in_use_count: u8,
pub reserved: [u8; 5],
}
// TODO: static assert the size and alignment
const_assert_eq!(size_of::<TokenAccount>(), 24);
const_assert_eq!(size_of::<TokenAccount>() % 8, 0);
impl TokenAccount {
pub fn is_active(&self) -> bool {
@ -76,6 +81,7 @@ impl TokenAccountMap {
indexed_value: I80F48::ZERO,
token_index: TokenIndex::MAX,
in_use_count: 0,
reserved: [0; 5],
}; MAX_INDEXED_POSITIONS],
}
}
@ -112,6 +118,7 @@ impl TokenAccountMap {
indexed_value: I80F48::ZERO,
token_index,
in_use_count: 0,
reserved: [0; 5],
};
}
}
@ -149,8 +156,11 @@ pub struct Serum3Account {
/// uses and look up the correct oracles.
pub base_token_index: TokenIndex,
pub quote_token_index: TokenIndex,
pub reserved: [u8; 2],
}
// TODO: static assert the size and alignment
const_assert_eq!(size_of::<Serum3Account>(), 40);
const_assert_eq!(size_of::<Serum3Account>() % 8, 0);
impl Serum3Account {
pub fn is_active(&self) -> bool {
@ -169,6 +179,7 @@ impl Default for Serum3Account {
market_index: Serum3MarketIndex::MAX,
base_token_index: TokenIndex::MAX,
quote_token_index: TokenIndex::MAX,
reserved: [0; 2],
}
}
}
@ -224,6 +235,7 @@ impl Serum3AccountMap {
#[zero_copy]
pub struct PerpAccount {
pub market_index: PerpMarketIndex,
pub reserved: [u8; 6],
/// Active position size, measured in base lots
pub base_position: i64,
@ -248,6 +260,8 @@ pub struct PerpAccount {
pub taker_base: i64,
pub taker_quote: i64,
}
const_assert_eq!(size_of::<PerpAccount>(), 8 + 8 * 5 + 16);
const_assert_eq!(size_of::<PerpAccount>() % 8, 0);
impl Default for PerpAccount {
fn default() -> Self {
@ -259,6 +273,7 @@ impl Default for PerpAccount {
asks_quantity: 0,
taker_base: 0,
taker_quote: 0,
reserved: [0; 6],
}
}
}
@ -371,18 +386,28 @@ pub struct MangoAccount {
pub client_order_ids: [u64; MAX_PERP_OPEN_ORDERS],
/// This account cannot open new positions or borrow until `init_health >= 0`
pub being_liquidated: bool, // TODO: for strict Pod compat, these should be u8, not bool
pub being_liquidated: u8,
/// This account cannot do anything except go through `resolve_bankruptcy`
pub is_bankrupt: bool,
pub is_bankrupt: u8,
pub account_num: u8,
pub bump: u8,
// pub info: [u8; INFO_LEN], // TODO: Info could be in a separate PDA?
pub reserved: [u8; 5],
pub reserved: [u8; 4],
}
// TODO: static assert the size and alignment
const_assert_eq!(
size_of::<MangoAccount>(),
3 * 32
+ MAX_INDEXED_POSITIONS * size_of::<TokenAccount>()
+ MAX_SERUM_OPEN_ORDERS * size_of::<Serum3Account>()
+ MAX_PERP_OPEN_ORDERS * size_of::<PerpAccount>()
+ MAX_PERP_OPEN_ORDERS * (2 + 1 + 16 + 8)
+ 4
+ 4
);
const_assert_eq!(size_of::<MangoAccount>() % 8, 0);
impl MangoAccount {
pub fn next_order_slot(&self) -> Option<usize> {

View File

@ -374,7 +374,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
0
);
let liqee: MangoAccount = solana.get_account(account).await;
assert!(liqee.being_liquidated);
assert_eq!(liqee.being_liquidated, 1);
//
// TEST: liquidate the remaining borrow2 against collateral1,
@ -404,7 +404,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
1000 - 32
);
let liqee: MangoAccount = solana.get_account(account).await;
assert!(liqee.being_liquidated);
assert_eq!(liqee.being_liquidated, 1);
//
// TEST: liquidate borrow1 with collateral1, but place a limit
@ -433,7 +433,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
1000 - 32 - 21
);
let liqee: MangoAccount = solana.get_account(account).await;
assert!(liqee.being_liquidated);
assert_eq!(liqee.being_liquidated, 1);
//
// TEST: liquidate borrow1 with collateral1, making the account healthy again
@ -464,7 +464,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
1000 - 32 - 535
);
let liqee: MangoAccount = solana.get_account(account).await;
assert!(!liqee.being_liquidated);
assert_eq!(liqee.being_liquidated, 0);
Ok(())
}