Rearrange MangoAccount to avoid padding bytes
This commit is contained in:
parent
5470dc998a
commit
9cf4f1a748
|
@ -39,11 +39,11 @@ pub fn create_account(ctx: Context<CreateAccount>, account_num: u8) -> Result<()
|
||||||
order_side: [Side::Bid; MAX_PERP_OPEN_ORDERS],
|
order_side: [Side::Bid; MAX_PERP_OPEN_ORDERS],
|
||||||
orders: [i128::MAX; MAX_PERP_OPEN_ORDERS],
|
orders: [i128::MAX; MAX_PERP_OPEN_ORDERS],
|
||||||
client_order_ids: [u64::MAX; MAX_PERP_OPEN_ORDERS],
|
client_order_ids: [u64::MAX; MAX_PERP_OPEN_ORDERS],
|
||||||
being_liquidated: false,
|
being_liquidated: 0,
|
||||||
is_bankrupt: false,
|
is_bankrupt: 0,
|
||||||
account_num,
|
account_num,
|
||||||
bump: *ctx.bumps.get("account").ok_or(MangoError::SomeError)?,
|
bump: *ctx.bumps.get("account").ok_or(MangoError::SomeError)?,
|
||||||
reserved: [0; 5],
|
reserved: [0; 4],
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
|
||||||
|
|
||||||
// Get the account's position for that token index
|
// Get the account's position for that token index
|
||||||
let mut account = ctx.accounts.account.load_mut()?;
|
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)?;
|
let (position, position_index) = account.token_account_map.get_mut_or_create(token_index)?;
|
||||||
|
|
||||||
|
|
|
@ -38,24 +38,24 @@ pub fn liq_token_with_token(
|
||||||
let account_retriever = ScanningAccountRetriever::new(ctx.remaining_accounts, group_pk)?;
|
let account_retriever = ScanningAccountRetriever::new(ctx.remaining_accounts, group_pk)?;
|
||||||
|
|
||||||
let mut liqor = ctx.accounts.liqor.load_mut()?;
|
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()?;
|
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
|
// Initial liqee health check
|
||||||
let mut liqee_health_cache = health_cache_for_liqee(&liqee, &account_retriever)?;
|
let mut liqee_health_cache = health_cache_for_liqee(&liqee, &account_retriever)?;
|
||||||
let init_health = liqee_health_cache.health(HealthType::Init)?;
|
let init_health = liqee_health_cache.health(HealthType::Init)?;
|
||||||
if liqee.being_liquidated {
|
if liqee.being_liquidated != 0 {
|
||||||
if init_health > I80F48::ZERO {
|
if init_health > I80F48::ZERO {
|
||||||
liqee.being_liquidated = false;
|
liqee.being_liquidated = 0;
|
||||||
msg!("Liqee init_health above zero");
|
msg!("Liqee init_health above zero");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let maint_health = liqee_health_cache.health(HealthType::Maint)?;
|
let maint_health = liqee_health_cache.health(HealthType::Maint)?;
|
||||||
require!(maint_health < I80F48::ZERO, MangoError::SomeError);
|
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 equivalent to one native USDC or 1e-6 USDC
|
||||||
// This is used as threshold to flip flag instead of 0 because of dust issues
|
// 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
|
// Check liqor's health
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub fn margin_trade<'key, 'accounts, 'remaining, 'info>(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let group = ctx.accounts.group.load()?;
|
let group = ctx.accounts.group.load()?;
|
||||||
let mut account = ctx.accounts.account.load_mut()?;
|
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
|
// remaining_accounts layout is expected as follows
|
||||||
// * banks_len number of banks
|
// * banks_len number of banks
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub fn place_perp_order(
|
||||||
limit: u8,
|
limit: u8,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut mango_account = ctx.accounts.account.load_mut()?;
|
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 mango_account_pk = ctx.accounts.account.key();
|
||||||
|
|
||||||
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub fn serum3_cancel_order(
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
let account = ctx.accounts.account.load()?;
|
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()?;
|
let serum_market = ctx.accounts.serum_market.load()?;
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ pub fn serum3_create_open_orders(ctx: Context<Serum3CreateOpenOrders>) -> Result
|
||||||
|
|
||||||
let serum_market = ctx.accounts.serum_market.load()?;
|
let serum_market = ctx.accounts.serum_market.load()?;
|
||||||
let mut account = ctx.accounts.account.load_mut()?;
|
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
|
let serum_account = account
|
||||||
.serum3_account_map
|
.serum3_account_map
|
||||||
.create(serum_market.market_index)?;
|
.create(serum_market.market_index)?;
|
||||||
|
|
|
@ -65,7 +65,7 @@ pub fn serum3_liq_force_cancel_orders(
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
let account = ctx.accounts.account.load()?;
|
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()?;
|
let serum_market = ctx.accounts.serum_market.load()?;
|
||||||
|
|
||||||
// Validate open_orders
|
// Validate open_orders
|
||||||
|
|
|
@ -157,7 +157,7 @@ pub fn serum3_place_order(
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
let account = ctx.accounts.account.load()?;
|
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()?;
|
let serum_market = ctx.accounts.serum_market.load()?;
|
||||||
|
|
||||||
// Validate open_orders
|
// Validate open_orders
|
||||||
|
|
|
@ -64,7 +64,7 @@ pub fn serum3_settle_funds(ctx: Context<Serum3SettleFunds>) -> Result<()> {
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
let account = ctx.accounts.account.load()?;
|
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()?;
|
let serum_market = ctx.accounts.serum_market.load()?;
|
||||||
|
|
||||||
// Validate open_orders
|
// Validate open_orders
|
||||||
|
|
|
@ -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
|
// Get the account's position for that token index
|
||||||
let mut account = ctx.accounts.account.load_mut()?;
|
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)?;
|
let (position, position_index) = account.token_account_map.get_mut_or_create(token_index)?;
|
||||||
|
|
||||||
|
|
|
@ -206,6 +206,7 @@ mod tests {
|
||||||
indexed_value: I80F48::ZERO,
|
indexed_value: I80F48::ZERO,
|
||||||
token_index: 0,
|
token_index: 0,
|
||||||
in_use_count: if is_in_use { 1 } else { 0 },
|
in_use_count: if is_in_use { 1 } else { 0 },
|
||||||
|
reserved: [0; 5],
|
||||||
};
|
};
|
||||||
|
|
||||||
account.indexed_value = indexed(I80F48::from_num(start), &bank);
|
account.indexed_value = indexed(I80F48::from_num(start), &bank);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use anchor_lang::prelude::*;
|
use anchor_lang::prelude::*;
|
||||||
use fixed::types::I80F48;
|
use fixed::types::I80F48;
|
||||||
|
use static_assertions::const_assert_eq;
|
||||||
|
use std::mem::size_of;
|
||||||
|
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use crate::state::*;
|
use crate::state::*;
|
||||||
|
@ -33,8 +35,11 @@ pub struct TokenAccount {
|
||||||
|
|
||||||
/// incremented when a market requires this position to stay alive
|
/// incremented when a market requires this position to stay alive
|
||||||
pub in_use_count: u8,
|
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 {
|
impl TokenAccount {
|
||||||
pub fn is_active(&self) -> bool {
|
pub fn is_active(&self) -> bool {
|
||||||
|
@ -76,6 +81,7 @@ impl TokenAccountMap {
|
||||||
indexed_value: I80F48::ZERO,
|
indexed_value: I80F48::ZERO,
|
||||||
token_index: TokenIndex::MAX,
|
token_index: TokenIndex::MAX,
|
||||||
in_use_count: 0,
|
in_use_count: 0,
|
||||||
|
reserved: [0; 5],
|
||||||
}; MAX_INDEXED_POSITIONS],
|
}; MAX_INDEXED_POSITIONS],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +118,7 @@ impl TokenAccountMap {
|
||||||
indexed_value: I80F48::ZERO,
|
indexed_value: I80F48::ZERO,
|
||||||
token_index,
|
token_index,
|
||||||
in_use_count: 0,
|
in_use_count: 0,
|
||||||
|
reserved: [0; 5],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,8 +156,11 @@ pub struct Serum3Account {
|
||||||
/// uses and look up the correct oracles.
|
/// uses and look up the correct oracles.
|
||||||
pub base_token_index: TokenIndex,
|
pub base_token_index: TokenIndex,
|
||||||
pub quote_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 {
|
impl Serum3Account {
|
||||||
pub fn is_active(&self) -> bool {
|
pub fn is_active(&self) -> bool {
|
||||||
|
@ -169,6 +179,7 @@ impl Default for Serum3Account {
|
||||||
market_index: Serum3MarketIndex::MAX,
|
market_index: Serum3MarketIndex::MAX,
|
||||||
base_token_index: TokenIndex::MAX,
|
base_token_index: TokenIndex::MAX,
|
||||||
quote_token_index: TokenIndex::MAX,
|
quote_token_index: TokenIndex::MAX,
|
||||||
|
reserved: [0; 2],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,6 +235,7 @@ impl Serum3AccountMap {
|
||||||
#[zero_copy]
|
#[zero_copy]
|
||||||
pub struct PerpAccount {
|
pub struct PerpAccount {
|
||||||
pub market_index: PerpMarketIndex,
|
pub market_index: PerpMarketIndex,
|
||||||
|
pub reserved: [u8; 6],
|
||||||
|
|
||||||
/// Active position size, measured in base lots
|
/// Active position size, measured in base lots
|
||||||
pub base_position: i64,
|
pub base_position: i64,
|
||||||
|
@ -248,6 +260,8 @@ pub struct PerpAccount {
|
||||||
pub taker_base: i64,
|
pub taker_base: i64,
|
||||||
pub taker_quote: 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 {
|
impl Default for PerpAccount {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
@ -259,6 +273,7 @@ impl Default for PerpAccount {
|
||||||
asks_quantity: 0,
|
asks_quantity: 0,
|
||||||
taker_base: 0,
|
taker_base: 0,
|
||||||
taker_quote: 0,
|
taker_quote: 0,
|
||||||
|
reserved: [0; 6],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,18 +386,28 @@ pub struct MangoAccount {
|
||||||
pub client_order_ids: [u64; MAX_PERP_OPEN_ORDERS],
|
pub client_order_ids: [u64; MAX_PERP_OPEN_ORDERS],
|
||||||
|
|
||||||
/// This account cannot open new positions or borrow until `init_health >= 0`
|
/// 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`
|
/// This account cannot do anything except go through `resolve_bankruptcy`
|
||||||
pub is_bankrupt: bool,
|
pub is_bankrupt: u8,
|
||||||
|
|
||||||
pub account_num: u8,
|
pub account_num: u8,
|
||||||
pub bump: u8,
|
pub bump: u8,
|
||||||
|
|
||||||
// pub info: [u8; INFO_LEN], // TODO: Info could be in a separate PDA?
|
// 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 {
|
impl MangoAccount {
|
||||||
pub fn next_order_slot(&self) -> Option<usize> {
|
pub fn next_order_slot(&self) -> Option<usize> {
|
||||||
|
|
|
@ -374,7 +374,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
let liqee: MangoAccount = solana.get_account(account).await;
|
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,
|
// TEST: liquidate the remaining borrow2 against collateral1,
|
||||||
|
@ -404,7 +404,7 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
|
||||||
1000 - 32
|
1000 - 32
|
||||||
);
|
);
|
||||||
let liqee: MangoAccount = solana.get_account(account).await;
|
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
|
// 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
|
1000 - 32 - 21
|
||||||
);
|
);
|
||||||
let liqee: MangoAccount = solana.get_account(account).await;
|
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
|
// 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
|
1000 - 32 - 535
|
||||||
);
|
);
|
||||||
let liqee: MangoAccount = solana.get_account(account).await;
|
let liqee: MangoAccount = solana.get_account(account).await;
|
||||||
assert!(!liqee.being_liquidated);
|
assert_eq!(liqee.being_liquidated, 0);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue