Serum: Test for force cancel orders
This commit is contained in:
parent
d7e4fc3ea9
commit
43eba0a529
|
@ -9,10 +9,11 @@ use std::mem::size_of;
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use crate::state::*;
|
use crate::state::*;
|
||||||
|
|
||||||
|
/// Serum padding is "serum" + data + "padding"
|
||||||
fn strip_dex_padding<'a>(acc: &'a AccountInfo) -> Result<Ref<'a, [u8]>> {
|
fn strip_dex_padding<'a>(acc: &'a AccountInfo) -> Result<Ref<'a, [u8]>> {
|
||||||
require!(acc.data_len() >= 12, MangoError::SomeError);
|
require!(acc.data_len() >= 12, MangoError::SomeError);
|
||||||
Ok(Ref::map(acc.try_borrow_data()?, |data| {
|
Ok(Ref::map(acc.try_borrow_data()?, |data| {
|
||||||
&data[5..data.len() - 12]
|
&data[5..data.len() - 7]
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ fn strip_dex_padding_mut<'a>(acc: &'a AccountInfo) -> Result<RefMut<'a, [u8]>> {
|
||||||
require!(acc.data_len() >= 12, MangoError::SomeError);
|
require!(acc.data_len() >= 12, MangoError::SomeError);
|
||||||
Ok(RefMut::map(acc.try_borrow_mut_data()?, |data| {
|
Ok(RefMut::map(acc.try_borrow_mut_data()?, |data| {
|
||||||
let len = data.len();
|
let len = data.len();
|
||||||
&mut data[5..len - 12]
|
&mut data[5..len - 7]
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +315,6 @@ impl<'a> CancelOrder<'a> {
|
||||||
let mut cancels = vec![];
|
let mut cancels = vec![];
|
||||||
{
|
{
|
||||||
let open_orders = load_open_orders(&self.open_orders)?;
|
let open_orders = load_open_orders(&self.open_orders)?;
|
||||||
|
|
||||||
let market = load_market_state(&self.market, self.program.key)?;
|
let market = load_market_state(&self.market, self.program.key)?;
|
||||||
let bids = load_bids_mut(&market, &self.bids)?;
|
let bids = load_bids_mut(&market, &self.bids)?;
|
||||||
let asks = load_asks_mut(&market, &self.asks)?;
|
let asks = load_asks_mut(&market, &self.asks)?;
|
||||||
|
|
|
@ -1045,6 +1045,10 @@ impl ClientInstruction for Serum3LiqForceCancelOrdersInstruction {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let health_check_metas =
|
||||||
|
derive_health_check_remaining_account_metas(&account_loader, &account, None, false)
|
||||||
|
.await;
|
||||||
|
|
||||||
let accounts = Self::Accounts {
|
let accounts = Self::Accounts {
|
||||||
group: account.group,
|
group: account.group,
|
||||||
account: self.account,
|
account: self.account,
|
||||||
|
@ -1065,7 +1069,9 @@ impl ClientInstruction for Serum3LiqForceCancelOrdersInstruction {
|
||||||
token_program: Token::id(),
|
token_program: Token::id(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let instruction = make_instruction(program_id, &accounts, instruction);
|
let mut instruction = make_instruction(program_id, &accounts, instruction);
|
||||||
|
instruction.accounts.extend(health_check_metas.into_iter());
|
||||||
|
|
||||||
(accounts, instruction)
|
(accounts, instruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,209 @@
|
||||||
|
#![cfg(feature = "test-bpf")]
|
||||||
|
|
||||||
|
use solana_program_test::*;
|
||||||
|
use solana_sdk::{signature::Keypair, transport::TransportError};
|
||||||
|
|
||||||
|
use program_test::*;
|
||||||
|
|
||||||
|
mod program_test;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_liq_tokens_force_cancel() -> 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..2];
|
||||||
|
let payer_mint_accounts = &context.users[1].token_accounts[0..2];
|
||||||
|
|
||||||
|
//
|
||||||
|
// SETUP: Create a group and an account to fill the vaults
|
||||||
|
//
|
||||||
|
|
||||||
|
let mango_setup::GroupWithTokens { group, tokens } = mango_setup::GroupWithTokensConfig {
|
||||||
|
admin,
|
||||||
|
payer,
|
||||||
|
mints,
|
||||||
|
}
|
||||||
|
.create(solana)
|
||||||
|
.await;
|
||||||
|
let base_token = &tokens[0];
|
||||||
|
let quote_token = &tokens[1];
|
||||||
|
|
||||||
|
// deposit some funds, to the vaults aren't empty
|
||||||
|
let vault_account = send_tx(
|
||||||
|
solana,
|
||||||
|
CreateAccountInstruction {
|
||||||
|
account_num: 2,
|
||||||
|
group,
|
||||||
|
owner,
|
||||||
|
payer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.account;
|
||||||
|
for &token_account in payer_mint_accounts {
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
DepositInstruction {
|
||||||
|
amount: 10000,
|
||||||
|
account: vault_account,
|
||||||
|
token_account,
|
||||||
|
token_authority: payer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// SETUP: Create serum market
|
||||||
|
//
|
||||||
|
let serum_market_cookie = context
|
||||||
|
.serum
|
||||||
|
.list_spot_market(&base_token.mint, "e_token.mint)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let serum_market = send_tx(
|
||||||
|
solana,
|
||||||
|
Serum3RegisterMarketInstruction {
|
||||||
|
group,
|
||||||
|
admin,
|
||||||
|
serum_program: context.serum.program_id,
|
||||||
|
serum_market_external: serum_market_cookie.market,
|
||||||
|
market_index: 0,
|
||||||
|
base_token_index: base_token.index,
|
||||||
|
quote_token_index: quote_token.index,
|
||||||
|
payer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.serum_market;
|
||||||
|
|
||||||
|
//
|
||||||
|
// SETUP: Make an account and deposit some quote
|
||||||
|
//
|
||||||
|
let account = send_tx(
|
||||||
|
solana,
|
||||||
|
CreateAccountInstruction {
|
||||||
|
account_num: 0,
|
||||||
|
group,
|
||||||
|
owner,
|
||||||
|
payer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.account;
|
||||||
|
|
||||||
|
let deposit_amount = 1000;
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
DepositInstruction {
|
||||||
|
amount: deposit_amount,
|
||||||
|
account,
|
||||||
|
token_account: payer_mint_accounts[1],
|
||||||
|
token_authority: payer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
//
|
||||||
|
// SETUP: Create an open orders account and an order
|
||||||
|
//
|
||||||
|
let _open_orders = send_tx(
|
||||||
|
solana,
|
||||||
|
Serum3CreateOpenOrdersInstruction {
|
||||||
|
account,
|
||||||
|
serum_market,
|
||||||
|
owner,
|
||||||
|
payer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.open_orders;
|
||||||
|
|
||||||
|
// short some base
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
Serum3PlaceOrderInstruction {
|
||||||
|
side: 1, // TODO: Ask
|
||||||
|
limit_price: 10, // in quote_lot (10) per base lot (100)
|
||||||
|
max_base_qty: 5, // in base lot (100)
|
||||||
|
max_native_quote_qty_including_fees: 600,
|
||||||
|
self_trade_behavior: 0,
|
||||||
|
order_type: 0, // TODO: Limit
|
||||||
|
client_order_id: 0,
|
||||||
|
limit: 10,
|
||||||
|
account,
|
||||||
|
owner,
|
||||||
|
serum_market,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
//
|
||||||
|
// TEST: Change the oracle to make health go negative
|
||||||
|
//
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
SetStubOracle {
|
||||||
|
mint: base_token.mint.pubkey,
|
||||||
|
payer,
|
||||||
|
price: "10.0",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// can't withdraw
|
||||||
|
assert!(send_tx(
|
||||||
|
solana,
|
||||||
|
WithdrawInstruction {
|
||||||
|
amount: 1,
|
||||||
|
allow_borrow: false,
|
||||||
|
account,
|
||||||
|
owner,
|
||||||
|
token_account: payer_mint_accounts[1],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.is_err());
|
||||||
|
|
||||||
|
//
|
||||||
|
// TEST: force cancel orders, making the account healthy again
|
||||||
|
//
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
Serum3LiqForceCancelOrdersInstruction {
|
||||||
|
account,
|
||||||
|
serum_market,
|
||||||
|
limit: 10,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// can withdraw again
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
WithdrawInstruction {
|
||||||
|
amount: 2,
|
||||||
|
allow_borrow: false,
|
||||||
|
account,
|
||||||
|
owner,
|
||||||
|
token_account: payer_mint_accounts[1],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue