Merge pull request #208 from blockworks-foundation/ckamm/fix-index-reservation
Serum: Index reservation account has 8 bytes
This commit is contained in:
commit
3b93a38395
|
@ -38,6 +38,13 @@ impl AccountFetcher {
|
|||
let acc = self.fetch_raw(address)?;
|
||||
|
||||
let data = acc.data();
|
||||
if data.len() < 8 {
|
||||
anyhow::bail!(
|
||||
"account at {} has only {} bytes of data",
|
||||
address,
|
||||
data.len()
|
||||
);
|
||||
}
|
||||
let disc_bytes = &data[0..8];
|
||||
if disc_bytes != MangoAccount::discriminator() {
|
||||
anyhow::bail!("not a mango account at {}", address);
|
||||
|
|
|
@ -12,7 +12,7 @@ pub fn is_mango_account<'a>(
|
|||
group_id: &Pubkey,
|
||||
) -> Option<MangoAccountRefWithHeader<'a>> {
|
||||
let data = account.data();
|
||||
if account.owner() != program_id || data.is_empty() {
|
||||
if account.owner() != program_id || data.len() < 8 {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ pub fn is_mango_bank<'a>(
|
|||
group_id: &Pubkey,
|
||||
) -> Option<&'a Bank> {
|
||||
let data = account.data();
|
||||
if account.owner() != program_id || data.is_empty() {
|
||||
if account.owner() != program_id || data.len() < 8 {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ pub fn is_mint_info<'a>(
|
|||
group_id: &Pubkey,
|
||||
) -> Option<&'a MintInfo> {
|
||||
let data = account.data();
|
||||
if account.owner() != program_id || data.is_empty() {
|
||||
if account.owner() != program_id || data.len() < 8 {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ pub fn is_perp_market<'a>(
|
|||
group_id: &Pubkey,
|
||||
) -> Option<&'a PerpMarket> {
|
||||
let data = account.data();
|
||||
if account.owner() != program_id || data.is_empty() {
|
||||
if account.owner() != program_id || data.len() < 8 {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
@ -157,6 +157,9 @@ impl<A: AccountReader> LoadZeroCopy for A {
|
|||
}
|
||||
|
||||
let data = self.data();
|
||||
if data.len() < 8 {
|
||||
return Err(ErrorCode::AccountDiscriminatorNotFound.into());
|
||||
}
|
||||
let disc_bytes = array_ref![data, 0, 8];
|
||||
if disc_bytes != &T::discriminator() {
|
||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||
|
@ -178,6 +181,9 @@ impl<'info, 'a> LoadMutZeroCopy for AccountInfoRefMut<'info, 'a> {
|
|||
return Err(ErrorCode::AccountOwnedByWrongProgram.into());
|
||||
}
|
||||
|
||||
if self.data.len() < 8 {
|
||||
return Err(ErrorCode::AccountDiscriminatorNotFound.into());
|
||||
}
|
||||
let disc_bytes = array_ref![self.data, 0, 8];
|
||||
if disc_bytes != &T::discriminator() {
|
||||
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
|
||||
|
@ -202,6 +208,9 @@ impl<'info> LoadZeroCopyRef for AccountInfo<'info> {
|
|||
}
|
||||
|
||||
let data = self.try_borrow_data()?;
|
||||
if data.len() < 8 {
|
||||
return Err(ErrorCode::AccountDiscriminatorNotFound.into());
|
||||
}
|
||||
|
||||
let disc_bytes = array_ref![data, 0, 8];
|
||||
if disc_bytes != &T::discriminator() {
|
||||
|
@ -228,6 +237,9 @@ impl<'info> LoadMutZeroCopyRef for AccountInfo<'info> {
|
|||
}
|
||||
|
||||
let data = self.try_borrow_mut_data()?;
|
||||
if data.len() < 8 {
|
||||
return Err(ErrorCode::AccountDiscriminatorNotFound.into());
|
||||
}
|
||||
|
||||
let disc_bytes = array_ref![data, 0, 8];
|
||||
if disc_bytes != &T::discriminator() {
|
||||
|
|
|
@ -20,6 +20,14 @@ pub struct Serum3DeregisterMarket<'info> {
|
|||
)]
|
||||
pub serum_market: AccountLoader<'info, Serum3Market>,
|
||||
|
||||
#[account(
|
||||
mut,
|
||||
has_one = group,
|
||||
constraint = serum_market.load()?.market_index == index_reservation.load()?.market_index,
|
||||
close = sol_destination
|
||||
)]
|
||||
pub index_reservation: AccountLoader<'info, Serum3MarketIndexReservation>,
|
||||
|
||||
#[account(mut)]
|
||||
/// CHECK: target for account rent needs no checks
|
||||
pub sol_destination: UncheckedAccount<'info>,
|
||||
|
|
|
@ -31,16 +31,15 @@ pub struct Serum3RegisterMarket<'info> {
|
|||
)]
|
||||
pub serum_market: AccountLoader<'info, Serum3Market>,
|
||||
|
||||
/// CHECK: Unused account
|
||||
#[account(
|
||||
init,
|
||||
// block using the same market index twice
|
||||
seeds = [b"Serum3Index".as_ref(), group.key().as_ref(), &market_index.to_le_bytes()],
|
||||
bump,
|
||||
payer = payer,
|
||||
space = 1,
|
||||
space = 8 + std::mem::size_of::<Serum3MarketIndexReservation>(),
|
||||
)]
|
||||
pub index_reservation: UncheckedAccount<'info>,
|
||||
pub index_reservation: AccountLoader<'info, Serum3MarketIndexReservation>,
|
||||
|
||||
#[account(has_one = group)]
|
||||
pub quote_bank: AccountLoader<'info, Bank>,
|
||||
|
@ -91,5 +90,12 @@ pub fn serum3_register_market(
|
|||
reserved: [0; 128],
|
||||
};
|
||||
|
||||
let mut serum_index_reservation = ctx.accounts.index_reservation.load_init()?;
|
||||
*serum_index_reservation = Serum3MarketIndexReservation {
|
||||
group: ctx.accounts.group.key(),
|
||||
market_index,
|
||||
reserved: [0; 38],
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -189,6 +189,7 @@ fn can_load_as<'a, T: ZeroCopy + Owner>(
|
|||
match load_result {
|
||||
Err(Error::AnchorError(error))
|
||||
if error.error_code_number == ErrorCode::AccountDiscriminatorMismatch as u32
|
||||
|| error.error_code_number == ErrorCode::AccountDiscriminatorNotFound as u32
|
||||
|| error.error_code_number == ErrorCode::AccountOwnedByWrongProgram as u32 =>
|
||||
{
|
||||
return None;
|
||||
|
|
|
@ -44,6 +44,16 @@ impl Serum3Market {
|
|||
}
|
||||
}
|
||||
|
||||
#[account(zero_copy)]
|
||||
#[derive(Debug)]
|
||||
pub struct Serum3MarketIndexReservation {
|
||||
pub group: Pubkey,
|
||||
pub market_index: Serum3MarketIndex,
|
||||
pub reserved: [u8; 38],
|
||||
}
|
||||
const_assert_eq!(size_of::<Serum3MarketIndexReservation>(), 32 + 2 + 38);
|
||||
const_assert_eq!(size_of::<Serum3MarketIndexReservation>() % 8, 0);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! serum_market_seeds {
|
||||
( $acc:expr ) => {
|
||||
|
|
|
@ -1387,7 +1387,7 @@ impl<'keypair> ClientInstruction for Serum3DeregisterMarketInstruction<'keypair>
|
|||
type Instruction = mango_v4::instruction::Serum3DeregisterMarket;
|
||||
async fn to_instruction(
|
||||
&self,
|
||||
_account_loader: impl ClientAccountLoader + 'async_trait,
|
||||
account_loader: impl ClientAccountLoader + 'async_trait,
|
||||
) -> (Self::Accounts, instruction::Instruction) {
|
||||
let program_id = mango_v4::id();
|
||||
let instruction = Self::Instruction {};
|
||||
|
@ -1401,11 +1401,23 @@ impl<'keypair> ClientInstruction for Serum3DeregisterMarketInstruction<'keypair>
|
|||
&program_id,
|
||||
)
|
||||
.0;
|
||||
let serum_market_data: Serum3Market = account_loader.load(&serum_market).await.unwrap();
|
||||
|
||||
let index_reservation = Pubkey::find_program_address(
|
||||
&[
|
||||
b"Serum3Index".as_ref(),
|
||||
self.group.as_ref(),
|
||||
&serum_market_data.market_index.to_le_bytes(),
|
||||
],
|
||||
&program_id,
|
||||
)
|
||||
.0;
|
||||
|
||||
let accounts = Self::Accounts {
|
||||
group: self.group,
|
||||
admin: self.admin.pubkey(),
|
||||
serum_market,
|
||||
index_reservation,
|
||||
sol_destination: self.sol_destination,
|
||||
token_program: Token::id(),
|
||||
};
|
||||
|
|
|
@ -1394,6 +1394,11 @@ export type MangoV4 = {
|
|||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "indexReservation",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "solDestination",
|
||||
"isMut": true,
|
||||
|
@ -3657,6 +3662,31 @@ export type MangoV4 = {
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "serum3MarketIndexReservation",
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"fields": [
|
||||
{
|
||||
"name": "group",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "marketIndex",
|
||||
"type": "u16"
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
38
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"types": [
|
||||
|
@ -6678,6 +6708,11 @@ export const IDL: MangoV4 = {
|
|||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "indexReservation",
|
||||
"isMut": true,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "solDestination",
|
||||
"isMut": true,
|
||||
|
@ -8941,6 +8976,31 @@ export const IDL: MangoV4 = {
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "serum3MarketIndexReservation",
|
||||
"type": {
|
||||
"kind": "struct",
|
||||
"fields": [
|
||||
{
|
||||
"name": "group",
|
||||
"type": "publicKey"
|
||||
},
|
||||
{
|
||||
"name": "marketIndex",
|
||||
"type": "u16"
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
38
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"types": [
|
||||
|
|
Loading…
Reference in New Issue