Tests: Send perp markets as health accounts

This commit is contained in:
Christian Kamm 2022-05-25 11:27:58 +02:00
parent 4984bba71e
commit 65a5139db7
2 changed files with 193 additions and 23 deletions

View File

@ -103,6 +103,18 @@ async fn get_mint_info_by_token_index(
get_mint_info_by_mint(account_loader, account, bank.mint).await
}
fn get_perp_market_address_by_index(group: Pubkey, perp_market_index: PerpMarketIndex) -> Pubkey {
Pubkey::find_program_address(
&[
group.as_ref(),
b"PerpMarket".as_ref(),
&perp_market_index.to_le_bytes(),
],
&mango_v4::id(),
)
.0
}
// all the accounts that instructions like deposit/withdraw need to compute account health
async fn derive_health_check_remaining_account_metas(
account_loader: &impl ClientAccountLoader,
@ -143,8 +155,18 @@ async fn derive_health_check_remaining_account_metas(
}
}
let perp_markets = account
.perps
.iter_active_accounts()
.map(|perp| get_perp_market_address_by_index(account.group, perp.market_index));
let serum_oos = account.serum3.iter_active().map(|&s| s.open_orders);
let to_account_meta = |pubkey| AccountMeta {
pubkey,
is_writable: false,
is_signer: false,
};
banks
.iter()
.map(|&pubkey| AccountMeta {
@ -152,16 +174,9 @@ async fn derive_health_check_remaining_account_metas(
is_writable: writable_banks,
is_signer: false,
})
.chain(oracles.iter().map(|&pubkey| AccountMeta {
pubkey,
is_writable: false,
is_signer: false,
}))
.chain(serum_oos.map(|pubkey| AccountMeta {
pubkey,
is_writable: false,
is_signer: false,
}))
.chain(oracles.into_iter().map(to_account_meta))
.chain(perp_markets.map(to_account_meta))
.chain(serum_oos.map(to_account_meta))
.collect()
}
@ -198,12 +213,25 @@ async fn derive_liquidation_remaining_account_metas(
oracles.push(mint_info.oracle);
}
let perp_markets = liqee
.perps
.iter_active_accounts()
.chain(liqee.perps.iter_active_accounts())
.map(|perp| get_perp_market_address_by_index(liqee.group, perp.market_index))
.unique();
let serum_oos = liqee
.serum3
.iter_active()
.chain(liqor.serum3.iter_active())
.map(|&s| s.open_orders);
let to_account_meta = |pubkey| AccountMeta {
pubkey,
is_writable: false,
is_signer: false,
};
banks
.iter()
.map(|(pubkey, is_writable)| AccountMeta {
@ -211,16 +239,9 @@ async fn derive_liquidation_remaining_account_metas(
is_writable: *is_writable,
is_signer: false,
})
.chain(oracles.iter().map(|&pubkey| AccountMeta {
pubkey,
is_writable: false,
is_signer: false,
}))
.chain(serum_oos.map(|pubkey| AccountMeta {
pubkey,
is_writable: false,
is_signer: false,
}))
.chain(oracles.into_iter().map(to_account_meta))
.chain(perp_markets.map(to_account_meta))
.chain(serum_oos.map(to_account_meta))
.collect()
}

View File

@ -1,5 +1,6 @@
#![cfg(feature = "test-bpf")]
use mango_v4::state::*;
use solana_program_test::*;
use solana_sdk::{signature::Keypair, transport::TransportError};
@ -65,7 +66,7 @@ async fn test_health_compute_tokens() -> Result<(), TransportError> {
}
// TODO: actual explicit CU comparisons.
// On 2022-3-29 the final deposit costs 43900 CU and each new token increases it by roughly 1800 CU
// On 2022-5-25 the final deposit costs 36905 CU and each new token increases it by roughly 1600 CU
Ok(())
}
@ -166,7 +167,7 @@ async fn test_health_compute_serum() -> Result<(), TransportError> {
DepositInstruction {
amount: 10,
account,
token_account: payer_mint_accounts[i],
token_account: payer_mint_accounts[0],
token_authority: payer,
},
)
@ -175,7 +176,155 @@ async fn test_health_compute_serum() -> Result<(), TransportError> {
}
// TODO: actual explicit CU comparisons.
// On 2022-3-29 the final deposit costs 60380 CU and each new market increases it by roughly 5000 CU
// On 2022-5-25 the final deposit costs 52252 CU and each new market increases it by roughly 4400 CU
Ok(())
}
// Try to reach compute limits in health checks by having many perp markets in an account
#[tokio::test]
async fn test_health_compute_perp() -> Result<(), TransportError> {
let context = TestContext::new().await;
let solana = &context.solana.clone();
let admin = &Keypair::new();
let owner = &context.users[0].key;
let payer = &context.users[1].key;
let mints = &context.mints[0..8];
let payer_mint_accounts = &context.users[1].token_accounts[0..mints.len()];
//
// SETUP: Create a group and an account
//
let mango_setup::GroupWithTokens { group, tokens } = mango_setup::GroupWithTokensConfig {
admin,
payer,
mints,
}
.create(solana)
.await;
let account = send_tx(
solana,
CreateAccountInstruction {
account_num: 0,
group,
owner,
payer,
},
)
.await
.unwrap()
.account;
// Give the account some quote currency
send_tx(
solana,
DepositInstruction {
amount: 1000,
account,
token_account: payer_mint_accounts[0],
token_authority: payer,
},
)
.await
.unwrap();
//
// SETUP: Create perp markets
//
let quote_token = &tokens[0];
let mut perp_markets = vec![];
for (perp_market_index, token) in tokens[1..].iter().enumerate() {
let mango_v4::accounts::PerpCreateMarket {
perp_market,
asks,
bids,
event_queue,
..
} = send_tx(
solana,
PerpCreateMarketInstruction {
group,
admin,
oracle: token.oracle,
asks: context
.solana
.create_account_for_type::<BookSide>(&mango_v4::id())
.await,
bids: context
.solana
.create_account_for_type::<BookSide>(&mango_v4::id())
.await,
event_queue: {
context
.solana
.create_account_for_type::<EventQueue>(&mango_v4::id())
.await
},
payer,
perp_market_index: perp_market_index as PerpMarketIndex,
base_token_index: quote_token.index,
quote_token_index: token.index,
quote_lot_size: 10,
base_lot_size: 100,
maint_asset_weight: 0.975,
init_asset_weight: 0.95,
maint_liab_weight: 1.025,
init_liab_weight: 1.05,
liquidation_fee: 0.012,
maker_fee: 0.0002,
taker_fee: 0.000,
},
)
.await
.unwrap();
perp_markets.push((perp_market, asks, bids, event_queue));
}
//
// TEST: Create a perp order for each market
//
for (i, &(perp_market, asks, bids, event_queue)) in perp_markets.iter().enumerate() {
println!("adding market {}", i);
send_tx(
solana,
PerpPlaceOrderInstruction {
group,
account,
perp_market,
asks,
bids,
event_queue,
oracle: tokens[i + 1].oracle,
owner,
side: Side::Bid,
price_lots: 1,
max_base_lots: 1,
max_quote_lots: i64::MAX,
client_order_id: 0,
},
)
.await
.unwrap();
send_tx(
solana,
DepositInstruction {
amount: 10,
account,
token_account: payer_mint_accounts[0],
token_authority: payer,
},
)
.await
.unwrap();
}
// TODO: actual explicit CU comparisons.
// On 2022-5-25 the final deposit costs 32700 CU and each new market increases it by roughly 1500 CU
Ok(())
}