diff --git a/CHANGELOG.md b/CHANGELOG.md index 83931920be..563a0b82ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,10 @@ incremented for features. * cli: Fix rust template ([#1488](https://github.com/project-serum/anchor/pull/1488)). +### Breaking + +* lang: Remove space calculation using [`#[derive(Default)]`] (https://github.com/project-serum/anchor/pull/1519). + ## [0.22.0] - 2022-02-20 ### Features diff --git a/lang/derive/accounts/src/lib.rs b/lang/derive/accounts/src/lib.rs index 02704f5628..66fbdfec80 100644 --- a/lang/derive/accounts/src/lib.rs +++ b/lang/derive/accounts/src/lib.rs @@ -89,7 +89,6 @@ use syn::parse_macro_input; /// ///
#[account(init, payer = <target_account>)]
#[account(init, payer = <target_account>, space = <num_bytes>)]
/// system_program
.
///
/// space
constraint is specified
-/// or, if creating an Account
type, the T
of Account
-/// to implement the rust std Default
trait.space
constraint is specified.
/// When using the space
constraint, one must remember to add 8 to it
-/// which is the size of the account discriminator.Vec
should use the space
-/// constraint instead of using the Default
trait and allocate sufficient space for all items that may
+/// which is the size of the account discriminator. This only has to be done
+/// for accounts owned by anchor programs.Vec
should allocate sufficient space for all items that may
/// be added to the data structure because account size is fixed. Check out the borsh library
/// (which anchor uses under the hood for serialization) specification to learn how much
/// space different data structures require.
@@ -126,20 +123,13 @@ use syn::parse_macro_input;
/// Example:
/// /// #[account] -/// #[derive(Default)] /// pub struct MyData { /// pub data: u64 /// } -/// #[account] -/// pub struct OtherData { -/// pub data: u64 -/// } /// #[derive(Accounts)] /// pub struct Initialize<'info> { -/// #[account(init, payer = payer)] -/// pub data_account: Account<'info, MyData>, /// #[account(init, payer = payer, space = 8 + 8)] -/// pub data_account_two: Account<'info, OtherData>, +/// pub data_account_two: Account<'info, MyData>, /// #[account(mut)] /// pub payer: Signer<'info>, /// pub system_program: Program<'info, System>, @@ -172,7 +162,7 @@ use syn::parse_macro_input; /// #[instruction(bump: u8)] /// pub struct Initialize<'info> { /// #[account( -/// init, payer = payer, +/// init, payer = payer, space = 8 + 8 /// seeds = [b"example_seed".as_ref()], bump = bump /// )] /// pub pda_data_account: Account<'info, MyData>, @@ -182,7 +172,7 @@ use syn::parse_macro_input; /// )] /// pub account_for_other_program: AccountInfo<'info>, /// #[account( -/// init,payer = payer, space = 8 + 8, +/// init, payer = payer, space = 8 + 8, /// owner = other_program.key(), /// seeds = [b"other_seed".as_ref()], bump /// )] diff --git a/lang/syn/src/codegen/accounts/constraints.rs b/lang/syn/src/codegen/accounts/constraints.rs index fc9dc79255..95afd3d1dc 100644 --- a/lang/syn/src/codegen/accounts/constraints.rs +++ b/lang/syn/src/codegen/accounts/constraints.rs @@ -480,29 +480,7 @@ fn generate_constraint_init_group(f: &Field, c: &ConstraintInitGroup) -> proc_ma } InitKind::Program { owner } => { // Define the space variable. - let space = match space { - // If no explicit space param was given, serialize the type to bytes - // and take the length (with +8 for the discriminator.) - None => { - let account_ty = f.account_ty(); - match matches!(f.ty, Ty::Loader(_) | Ty::AccountLoader(_)) { - false => { - quote! { - let space = 8 + #account_ty::default().try_to_vec().unwrap().len(); - } - } - true => { - quote! { - let space = 8 + anchor_lang::__private::bytemuck::bytes_of(account_ty::default()).len(); - } - } - } - } - // Explicit account size given. Use it. - Some(s) => quote! { - let space = #s; - }, - }; + let space = quote! {let space = #space;}; // Define the owner of the account being created. If not specified, // default to the currently executing program. diff --git a/lang/syn/src/lib.rs b/lang/syn/src/lib.rs index ca652f81d5..cf00ca23ed 100644 --- a/lang/syn/src/lib.rs +++ b/lang/syn/src/lib.rs @@ -721,7 +721,7 @@ pub enum ConstraintRentExempt { pub struct ConstraintInitGroup { pub if_needed: bool, pub seeds: Option, - pub payer: Option , + pub payer: Expr, pub space: Option , pub kind: InitKind, } diff --git a/lang/syn/src/parser/accounts/constraints.rs b/lang/syn/src/parser/accounts/constraints.rs index 533d5053fc..42454fec4f 100644 --- a/lang/syn/src/parser/accounts/constraints.rs +++ b/lang/syn/src/parser/accounts/constraints.rs @@ -505,17 +505,28 @@ impl<'ty> ConstraintGroupBuilder<'ty> { } } - // SPL Space. - if self.init.is_some() - && self.seeds.is_some() - && self.token_mint.is_some() - && (self.mint_authority.is_some() || self.token_authority.is_some()) - && self.space.is_some() - { - return Err(ParseError::new( - self.space.as_ref().unwrap().span(), - "space is not required for initializing an spl account", - )); + // Space. + if let Some(i) = &self.init { + let initializing_token_program_acc = self.token_mint.is_some() + || self.mint_authority.is_some() + || self.token_authority.is_some() + || self.associated_token_authority.is_some(); + + match (self.space.is_some(), initializing_token_program_acc) { + (true, true) => { + return Err(ParseError::new( + self.space.as_ref().unwrap().span(), + "space is not required for initializing an spl account", + )); + } + (false, false) => { + return Err(ParseError::new( + i.span(), + "space must be provided with init", + )); + } + _ => (), + } } let ConstraintGroupBuilder { @@ -593,7 +604,7 @@ impl<'ty> ConstraintGroupBuilder<'ty> { init: init.as_ref().map(|i| Ok(ConstraintInitGroup { if_needed: i.if_needed, seeds: seeds.clone(), - payer: into_inner!(payer.clone()).map(|a| a.target), + payer: into_inner!(payer.clone()).unwrap().target, space: space.clone().map(|s| s.space.clone()), kind: if let Some(tm) = &token_mint { InitKind::Token { diff --git a/lang/syn/src/parser/accounts/mod.rs b/lang/syn/src/parser/accounts/mod.rs index e375cbc159..b0178af5f5 100644 --- a/lang/syn/src/parser/accounts/mod.rs +++ b/lang/syn/src/parser/accounts/mod.rs @@ -93,8 +93,7 @@ fn constraints_cross_checks(fields: &[AccountField]) -> ParseResult<()> { for field in init_fields { // Get payer for init-ed account - let associated_payer_name = match field.constraints.init.clone().unwrap().payer.unwrap() - { + let associated_payer_name = match field.constraints.init.clone().unwrap().payer { // composite payer, check not supported Expr::Field(_) => continue, field_name => field_name.to_token_stream().to_string(), diff --git a/tests/bpf-upgradeable-state/programs/bpf-upgradeable-state/src/lib.rs b/tests/bpf-upgradeable-state/programs/bpf-upgradeable-state/src/lib.rs index 09087114d5..fca03bb7df 100644 --- a/tests/bpf-upgradeable-state/programs/bpf-upgradeable-state/src/lib.rs +++ b/tests/bpf-upgradeable-state/programs/bpf-upgradeable-state/src/lib.rs @@ -32,11 +32,14 @@ pub mod bpf_upgradeable_state { } #[account] -#[derive(Default, Debug)] pub struct Settings { admin_data: u64, } +impl Settings { + pub const LEN: usize = 8; +} + #[error_code] pub enum CustomError { InvalidProgramDataAddress, @@ -49,7 +52,7 @@ pub struct SetAdminSettings<'info> { // In a real program, this should be a PDA, // so the authority cannot create multiple settings accounts. // Not done here for easier testing - #[account(init, payer = authority)] + #[account(init, payer = authority, space = Settings::LEN + 8)] pub settings: Account<'info, Settings>, #[account(mut)] pub authority: Signer<'info>, @@ -65,7 +68,7 @@ pub struct SetAdminSettingsUseProgramState<'info> { // In a real program, this should be a PDA, // so the authority cannot create multiple settings accounts. // Not done here for easier testing - #[account(init, payer = authority)] + #[account(init, payer = authority, space = Settings::LEN + 8)] pub settings: Account<'info, Settings>, #[account(mut)] pub authority: Signer<'info>, diff --git a/tests/cfo/programs/cfo/src/lib.rs b/tests/cfo/programs/cfo/src/lib.rs index 959cc25f5c..480cb04ece 100644 --- a/tests/cfo/programs/cfo/src/lib.rs +++ b/tests/cfo/programs/cfo/src/lib.rs @@ -324,6 +324,7 @@ pub struct CreateOfficer<'info> { seeds = [dex_program.key.as_ref()], bump, payer = authority, + space = Officer::LEN + 8 )] officer: Box >, #[account( @@ -332,7 +333,7 @@ pub struct CreateOfficer<'info> { bump, payer = authority, token::mint = srm_mint, - token::authority = officer, + token::authority = officer )] srm_vault: Box >, #[account( @@ -341,7 +342,7 @@ pub struct CreateOfficer<'info> { bump, payer = authority, token::mint = usdc_mint, - token::authority = officer, + token::authority = officer )] usdc_vault: Box >, #[account( @@ -350,7 +351,7 @@ pub struct CreateOfficer<'info> { bump, payer = authority, token::mint = srm_mint, - token::authority = officer, + token::authority = officer )] stake: Box >, #[account( @@ -359,7 +360,7 @@ pub struct CreateOfficer<'info> { bump, payer = authority, token::mint = srm_mint, - token::authority = officer, + token::authority = officer )] treasury: Box >, #[account(mut)] @@ -392,6 +393,7 @@ pub struct AuthorizeMarket<'info> { payer = payer, seeds = [b"market-auth", officer.key().as_ref(), market.key.as_ref()], bump, + space = MarketAuth::LEN + 8 )] market_auth: Account<'info, MarketAuth>, #[account(mut)] @@ -421,7 +423,7 @@ pub struct CreateOfficerToken<'info> { bump, token::mint = mint, token::authority = officer, - payer = payer, + payer = payer )] token: Account<'info, TokenAccount>, mint: Account<'info, Mint>, @@ -666,28 +668,31 @@ pub struct DropStakeRewardPool<'info> { /// /// PDA - [dex_program_id]. #[account] -#[derive(Default)] pub struct Officer { // Priviledged account. - pub authority: Pubkey, + pub authority: Pubkey, // 32 // Vault holding the officer's SRM tokens prior to distribution. - pub srm_vault: Pubkey, + pub srm_vault: Pubkey, // 32 // Escrow SRM vault holding tokens which are dropped onto stakers. - pub stake: Pubkey, + pub stake: Pubkey, // 32 // SRM token account to send treasury earned tokens to. - pub treasury: Pubkey, + pub treasury: Pubkey, // 32 // Defines the fee distribution, i.e., what percent each fee category gets. - pub distribution: Distribution, + pub distribution: Distribution, // Distribution::LEN // Swap frontend for the dex. - pub swap_program: Pubkey, + pub swap_program: Pubkey, // 32 // Dex program the officer is associated with. - pub dex_program: Pubkey, + pub dex_program: Pubkey, // 32 // SRM stake pool address - pub registrar: Pubkey, + pub registrar: Pubkey, // 32 // MSRM stake pool address. - pub msrm_registrar: Pubkey, + pub msrm_registrar: Pubkey, // 32 // Bump seeds for pdas. - pub bumps: OfficerBumps, + pub bumps: OfficerBumps, // OfficerBumps::LEN +} + +impl Officer { + pub const LEN: usize = 8 * 32 + Distribution::LEN + OfficerBumps::LEN; } /// MarketAuth represents an authorization token created by the Officer @@ -702,26 +707,37 @@ pub struct Officer { /// /// PDA - [b"market-auth", officer, market_address] #[account] -#[derive(Default)] pub struct MarketAuth { // Bump seed for this account's PDA. - pub bump: u8, + pub bump: u8, // 1 +} + +impl MarketAuth { + pub const LEN: usize = 1; } #[derive(AnchorSerialize, AnchorDeserialize, Clone, Default)] pub struct OfficerBumps { - pub bump: u8, - pub srm: u8, - pub usdc: u8, - pub stake: u8, - pub treasury: u8, + pub bump: u8, // 1 + pub srm: u8, // 1 + pub usdc: u8, // 1 + pub stake: u8, // 1 + pub treasury: u8, // 1 +} + +impl OfficerBumps { + pub const LEN: usize = 5; } #[derive(AnchorSerialize, AnchorDeserialize, Default, Clone)] pub struct Distribution { - burn: u8, - stake: u8, - treasury: u8, + burn: u8, // 1 + stake: u8, // 1 + treasury: u8, // 1 +} + +impl Distribution { + pub const LEN: usize = 3; } // CpiContext transformations. diff --git a/tests/ido-pool/programs/ido-pool/src/lib.rs b/tests/ido-pool/programs/ido-pool/src/lib.rs index 2a2abfb7ed..ca7b0320fb 100644 --- a/tests/ido-pool/programs/ido-pool/src/lib.rs +++ b/tests/ido-pool/programs/ido-pool/src/lib.rs @@ -295,7 +295,9 @@ pub struct InitializePool<'info> { #[account(init, seeds = [ido_name.as_bytes()], bump, - payer = ido_authority)] + payer = ido_authority, + space = IdoAccount::LEN + 8 + )] pub ido_account: Box >, // TODO Confirm USDC mint address on mainnet or leave open as an option for other stables #[account(constraint = usdc_mint.decimals == DECIMALS)] @@ -305,7 +307,8 @@ pub struct InitializePool<'info> { mint::authority = ido_account, seeds = [ido_name.as_bytes(), b"redeemable_mint".as_ref()], bump, - payer = ido_authority)] + payer = ido_authority + )] pub redeemable_mint: Box >, #[account(constraint = watermelon_mint.key() == ido_authority_watermelon.mint)] pub watermelon_mint: Box >, @@ -314,14 +317,16 @@ pub struct InitializePool<'info> { token::authority = ido_account, seeds = [ido_name.as_bytes(), b"pool_watermelon"], bump, - payer = ido_authority)] + payer = ido_authority + )] pub pool_watermelon: Box >, #[account(init, token::mint = usdc_mint, token::authority = ido_account, seeds = [ido_name.as_bytes(), b"pool_usdc"], bump, - payer = ido_authority)] + payer = ido_authority + )] pub pool_usdc: Box >, // Programs and Sysvars pub system_program: Program<'info, System>, @@ -341,7 +346,8 @@ pub struct InitUserRedeemable<'info> { ido_account.ido_name.as_ref().trim_ascii_whitespace(), b"user_redeemable"], bump, - payer = user_authority)] + payer = user_authority + )] pub user_redeemable: Box >, // IDO Accounts #[account(seeds = [ido_account.ido_name.as_ref().trim_ascii_whitespace()], @@ -401,7 +407,8 @@ pub struct InitEscrowUsdc<'info> { ido_account.ido_name.as_ref().trim_ascii_whitespace(), b"escrow_usdc"], bump, - payer = user_authority)] + payer = user_authority + )] pub escrow_usdc: Box >, #[account(seeds = [ido_account.ido_name.as_ref().trim_ascii_whitespace()], bump = ido_account.bumps.ido_account, @@ -541,36 +548,39 @@ pub struct WithdrawFromEscrow<'info> { } #[account] -#[derive(Default)] pub struct IdoAccount { - pub ido_name: [u8; 10], // Setting an arbitrary max of ten characters in the ido name. - pub bumps: PoolBumps, - pub ido_authority: Pubkey, - - pub usdc_mint: Pubkey, - pub redeemable_mint: Pubkey, - pub watermelon_mint: Pubkey, - pub pool_usdc: Pubkey, - pub pool_watermelon: Pubkey, - - pub num_ido_tokens: u64, - pub ido_times: IdoTimes, + pub ido_name: [u8; 10], // Setting an arbitrary max of ten characters in the ido name. // 10 + pub bumps: PoolBumps, // 4 + pub ido_authority: Pubkey, // 32 + + pub usdc_mint: Pubkey, // 32 + pub redeemable_mint: Pubkey, // 32 + pub watermelon_mint: Pubkey, // 32 + pub pool_usdc: Pubkey, // 32 + pub pool_watermelon: Pubkey, // 32 + + pub num_ido_tokens: u64, // 8 + pub ido_times: IdoTimes, // 32 +} + +impl IdoAccount { + pub const LEN: usize = 10 + 4 + 32 + 5 * 32 + 8 + 32; } #[derive(AnchorSerialize, AnchorDeserialize, Default, Clone, Copy)] pub struct IdoTimes { - pub start_ido: i64, - pub end_deposits: i64, - pub end_ido: i64, - pub end_escrow: i64, + pub start_ido: i64, // 8 + pub end_deposits: i64, // 8 + pub end_ido: i64, // 8 + pub end_escrow: i64, // 8 } #[derive(AnchorSerialize, AnchorDeserialize, Default, Clone)] pub struct PoolBumps { - pub ido_account: u8, - pub redeemable_mint: u8, - pub pool_watermelon: u8, - pub pool_usdc: u8, + pub ido_account: u8, // 1 + pub redeemable_mint: u8, // 1 + pub pool_watermelon: u8, // 1 + pub pool_usdc: u8, // 1 } #[error_code] diff --git a/tests/misc/programs/misc/src/account.rs b/tests/misc/programs/misc/src/account.rs index b94e1fdcf4..4a5fc13c5c 100644 --- a/tests/misc/programs/misc/src/account.rs +++ b/tests/misc/programs/misc/src/account.rs @@ -1,50 +1,63 @@ use anchor_lang::prelude::*; +macro_rules! size { + ($name: ident, $size:expr) => { + impl $name { + pub const LEN: usize = $size; + } + }; +} + pub const MAX_SIZE: usize = 10; #[account] pub struct Data { - pub udata: u128, - pub idata: i128, + pub udata: u128, // 16 + pub idata: i128, // 16 } +size!(Data, 32); #[account] -#[derive(Default)] pub struct DataU16 { - pub data: u16, + pub data: u16, // 2 } +size!(DataU16, 32); #[account] -#[derive(Default)] pub struct DataI8 { - pub data: i8, + pub data: i8, // 1 } +size!(DataI8, 1); #[account] pub struct DataI16 { - pub data: i16, + pub data: i16, // 2 } +size!(DataI16, 2); #[account(zero_copy)] -#[derive(Default)] pub struct DataZeroCopy { - pub data: u16, - pub bump: u8, + pub data: u16, // 2 + pub _padding: u8, // 1 + pub bump: u8, // 1 } +size!(DataZeroCopy, 4); #[account] -#[derive(Default)] pub struct DataWithFilter { - pub authority: Pubkey, - pub filterable: Pubkey, + pub authority: Pubkey, // 32 + pub filterable: Pubkey, // 32 } +size!(DataWithFilter, 64); #[account] pub struct DataMultidimensionalArray { - pub data: [[u8; 10]; 10], + pub data: [[u8; 10]; 10], // 100 } +size!(DataMultidimensionalArray, 100); #[account] pub struct DataConstArraySize { - pub data: [u8; MAX_SIZE], + pub data: [u8; MAX_SIZE], // 10 } +size!(DataConstArraySize, MAX_SIZE); diff --git a/tests/misc/programs/misc/src/context.rs b/tests/misc/programs/misc/src/context.rs index cda496cbe8..e34c6c71eb 100644 --- a/tests/misc/programs/misc/src/context.rs +++ b/tests/misc/programs/misc/src/context.rs @@ -16,15 +16,17 @@ pub struct TestTokenSeedsInit<'info> { payer = authority, mint::decimals = 6, mint::authority = authority, + )] pub mint: Account<'info, Mint>, #[account( init, - seeds = [b"my-token-seed".as_ref(),], + seeds = [b"my-token-seed".as_ref()], bump, payer = authority, token::mint = mint, token::authority = authority, + )] pub my_pda: Account<'info, TokenAccount>, #[account(mut)] @@ -42,6 +44,7 @@ pub struct TestInitAssociatedToken<'info> { payer = payer, associated_token::mint = mint, associated_token::authority = payer, + )] pub token: Account<'info, TokenAccount>, pub mint: Account<'info, Mint>, @@ -86,6 +89,7 @@ pub struct TestPdaInit<'info> { seeds = [b"my-seed", domain.as_bytes(), foo.key.as_ref(), &seed], bump, payer = my_payer, + space = DataU16::LEN + 8 )] pub my_pda: Account<'info, DataU16>, #[account(mut)] @@ -102,8 +106,9 @@ pub struct TestPdaInitZeroCopy<'info> { seeds = [b"my-seed".as_ref()], bump, payer = my_payer, + space = DataZeroCopy::LEN + 8 )] - pub my_pda: Loader<'info, DataZeroCopy>, + pub my_pda: AccountLoader<'info, DataZeroCopy>, #[account(mut)] pub my_payer: Signer<'info>, pub system_program: Program<'info, System>, @@ -116,7 +121,7 @@ pub struct TestPdaMutZeroCopy<'info> { seeds = [b"my-seed".as_ref()], bump = my_pda.load()?.bump, )] - pub my_pda: Loader<'info, DataZeroCopy>, + pub my_pda: AccountLoader<'info, DataZeroCopy>, /// CHECK: pub my_payer: AccountInfo<'info>, } @@ -204,7 +209,7 @@ pub struct TestI8<'info> { #[derive(Accounts)] pub struct TestInit<'info> { - #[account(init, payer = payer)] + #[account(init, payer = payer, space = DataI8::LEN + 8)] pub data: Account<'info, DataI8>, #[account(mut)] pub payer: Signer<'info>, @@ -213,7 +218,7 @@ pub struct TestInit<'info> { #[derive(Accounts)] pub struct TestInitZeroCopy<'info> { - #[account(init, payer = payer, space = 8 + size_of:: ())] + #[account(init, payer = payer, space = DataZeroCopy::LEN + 8)] pub data: Loader<'info, DataZeroCopy>, #[account(mut)] pub payer: Signer<'info>, @@ -222,7 +227,7 @@ pub struct TestInitZeroCopy<'info> { #[derive(Accounts)] pub struct TestInitMint<'info> { - #[account(init, mint::decimals = 6, mint::authority = payer, mint::freeze_authority = payer, payer = payer)] + #[account(init, mint::decimals = 6, mint::authority = payer, mint::freeze_authority = payer, payer = payer, )] pub mint: Account<'info, Mint>, #[account(mut)] pub payer: Signer<'info>, @@ -233,7 +238,7 @@ pub struct TestInitMint<'info> { #[derive(Accounts)] pub struct TestInitToken<'info> { - #[account(init, token::mint = mint, token::authority = payer, payer = payer)] + #[account(init, token::mint = mint, token::authority = payer, payer = payer, )] pub token: Account<'info, TokenAccount>, pub mint: Account<'info, Mint>, #[account(mut)] @@ -246,14 +251,14 @@ pub struct TestInitToken<'info> { #[derive(Accounts)] pub struct TestCompositePayer<'info> { pub composite: TestInit<'info>, - #[account(init, payer = composite.payer, space = 8 + size_of::())] + #[account(init, payer = composite.payer, space = Data::LEN + 8)] pub data: Account<'info, Data>, pub system_program: Program<'info, System>, } #[derive(Accounts)] pub struct TestFetchAll<'info> { - #[account(init, payer = authority)] + #[account(init, payer = authority, space = DataWithFilter::LEN + 8)] pub data: Account<'info, DataWithFilter>, #[account(mut)] pub authority: Signer<'info>, @@ -262,7 +267,7 @@ pub struct TestFetchAll<'info> { #[derive(Accounts)] pub struct TestInitWithEmptySeeds<'info> { - #[account(init, seeds = [], bump, payer = authority, space = 8 + size_of::())] + #[account(init, seeds = [], bump, payer = authority, space = Data::LEN + 8)] pub pda: Account<'info, Data>, #[account(mut)] pub authority: Signer<'info>, @@ -278,7 +283,7 @@ pub struct TestEmptySeedsConstraint<'info> { #[derive(Accounts)] pub struct InitWithSpace<'info> { - #[account(init, payer = payer)] + #[account(init, payer = payer, space = DataU16::LEN + 8)] pub data: Account<'info, DataU16>, #[account(mut)] pub payer: Signer<'info>, @@ -287,7 +292,8 @@ pub struct InitWithSpace<'info> { #[derive(Accounts)] pub struct TestInitIfNeeded<'info> { - #[account(init_if_needed, payer = payer, space = 500)] + // intentionally using more space (+500) to check whether space is checked when using init_if_needed + #[account(init_if_needed, payer = payer, space = DataU16::LEN + 8 + 500)] pub data: Account<'info, DataU16>, #[account(mut)] pub payer: Signer<'info>, @@ -335,7 +341,7 @@ pub struct TestInitMintIfNeeded<'info> { #[derive(Accounts)] pub struct TestInitTokenIfNeeded<'info> { - #[account(init_if_needed, token::mint = mint, token::authority = authority, payer = payer)] + #[account(init_if_needed, token::mint = mint, token::authority = authority, payer = payer, )] pub token: Account<'info, TokenAccount>, pub mint: Account<'info, Mint>, #[account(mut)] @@ -353,7 +359,7 @@ pub struct TestInitAssociatedTokenIfNeeded<'info> { init_if_needed, payer = payer, associated_token::mint = mint, - associated_token::authority = authority, + associated_token::authority = authority )] pub token: Account<'info, TokenAccount>, pub mint: Account<'info, Mint>, diff --git a/tests/misc/tests/misc.js b/tests/misc/tests/misc.js index fc1b7983d6..3e6cd982f4 100644 --- a/tests/misc/tests/misc.js +++ b/tests/misc/tests/misc.js @@ -1002,7 +1002,8 @@ describe("misc", () => { it("init_if_needed throws if account exists but is not the expected space", async () => { const newAcc = anchor.web3.Keypair.generate(); - await program.rpc.initWithSpace(3, { + const _irrelevantForTest = 3; + await program.rpc.initWithSpace(_irrelevantForTest, { accounts: { data: newAcc.publicKey, systemProgram: anchor.web3.SystemProgram.programId, @@ -1012,7 +1013,7 @@ describe("misc", () => { }); try { - await program.rpc.testInitIfNeeded(3, { + await program.rpc.testInitIfNeeded(_irrelevantForTest, { accounts: { data: newAcc.publicKey, systemProgram: anchor.web3.SystemProgram.programId, diff --git a/tests/zero-copy/programs/zero-copy/src/lib.rs b/tests/zero-copy/programs/zero-copy/src/lib.rs index 58b1beb68a..c6076ea9ff 100644 --- a/tests/zero-copy/programs/zero-copy/src/lib.rs +++ b/tests/zero-copy/programs/zero-copy/src/lib.rs @@ -97,7 +97,8 @@ pub struct CreateBar<'info> { init, seeds = [authority.key().as_ref(), foo.key().as_ref()], bump, - payer = authority, owner = *program_id + payer = authority, owner = *program_id, + space = Bar::LEN + 8 )] bar: AccountLoader<'info, Bar>, #[account(mut)] @@ -132,8 +133,8 @@ pub struct UpdateLargeAccount<'info> { } #[account(zero_copy)] -#[derive(Default)] #[repr(packed)] +#[derive(Default)] pub struct Foo { pub authority: Pubkey, pub data: u64, @@ -143,10 +144,13 @@ pub struct Foo { } #[account(zero_copy)] -#[derive(Default)] pub struct Bar { - pub authority: Pubkey, - pub data: u64, + pub authority: Pubkey, // 32 + pub data: u64, // 8 +} + +impl Bar { + pub const LEN: usize = 32 + 8; } #[account(zero_copy)]