Merge pull request #208 from blockworks-foundation/ckamm/fix-index-reservation

Serum: Index reservation account has 8 bytes
This commit is contained in:
Christian Kamm 2022-09-01 13:23:27 +02:00 committed by GitHub
commit 3b93a38395
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 124 additions and 8 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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() {

View File

@ -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>,

View File

@ -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(())
}

View File

@ -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;

View File

@ -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 ) => {

View File

@ -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(),
};

View File

@ -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": [