Skip to main content
add missing answer part
Source Link
Henry E
  • 2.9k
  • 7
  • 32

Without constraints

Check initialized

Account::try_from will check

  • the account is owned by the correct program
  • the account is initialized
  • the account has the correct discriminator and can be deserialized into the struct
let example_pda1_account_info = ctx.accounts.example_pda1.to_account_info()
let mut example_pda1: Account<ExamplePda> = 
   Account::try_from(example_pda1_account_info)?;

Check uninitialized

I haven't checked that this actually compiles but this is adapted from the zero discriminator check that the zero constraint source code uses.

let mut __data: &[u8] = ctx.accounts.example_pda1.to_account_info().try_borrow_data()?;
let mut __disc_bytes = [0u8; 8];
__disc_bytes.copy_from_slice(&__data[..8]);
let __discriminator = u64::from_le_bytes(__disc_bytes);
if __discriminator != 0 {
    return Err();
}

With constraints

Check initialized

To check that a program account has been initialized you can just get anchor to try and load the program account in the accounts context, similar to how you verify the account is empty above.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump = example_pda1.bump,
)]
pub example_pda1: Account<'info, ExamplePdaAccount>

Anchor will try to load the account data and check that the 8 bytes at the start of the account match the expected discriminator.

Check uninitialized

For checking that an account is not initialized I would instead check that the system program still owns the account. A system program account can't have data on it, though it might have some lamports in it.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump,
)]
pub example_pda1: SystemAccount<'info>

Finally zero doesn't do what you expect it to do here. It does a lot more. Check out the constraints doc https://docs.rs/anchor-lang/latest/anchor_lang/derive.Accounts.html#constraints. Essentially it checks that the 8 byte discriminator is not initialized and that the account has enough solana rent to be rent exempt (although this is now a run time requirement) but it will also check that your account is owned by the program calling the function, ensures the account is mutable, and initializes the account + the discriminator. zero is essentially a lighter weight version of init that needs to be called in different scenarios that are explained in the docs.

Use this constraint (zero) if you want to create an account in a previous instruction and then initialize it in your instruction instead of using init. This is necessary for accounts that are larger than 10 Kibibyte because those accounts cannot be created via a CPI (which is what init would do).

To check that a program account has been initialized you can just get anchor to try and load the program account in the accounts context, similar to how you verify the account is empty above.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump = example_pda1.bump,
)]
pub example_pda1: Account<'info, ExamplePdaAccount>

Anchor will try to load the account data and check that the 8 bytes at the start of the account match the expected discriminator.

For checking that an account is not initialized I would instead check that the system program still owns the account. A system program account can't have data on it, though it might have some lamports in it.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump,
)]
pub example_pda1: SystemAccount<'info>

Finally zero doesn't do what you expect it to do here. It does a lot more. Check out the constraints doc https://docs.rs/anchor-lang/latest/anchor_lang/derive.Accounts.html#constraints. Essentially it checks that the 8 byte discriminator is not initialized and that the account has enough solana rent to be rent exempt (although this is now a run time requirement) but it will also check that your account is owned by the program calling the function, ensures the account is mutable, and initializes the account + the discriminator. zero is essentially a lighter weight version of init that needs to be called in different scenarios that are explained in the docs.

Use this constraint (zero) if you want to create an account in a previous instruction and then initialize it in your instruction instead of using init. This is necessary for accounts that are larger than 10 Kibibyte because those accounts cannot be created via a CPI (which is what init would do).

Without constraints

Check initialized

Account::try_from will check

  • the account is owned by the correct program
  • the account is initialized
  • the account has the correct discriminator and can be deserialized into the struct
let example_pda1_account_info = ctx.accounts.example_pda1.to_account_info()
let mut example_pda1: Account<ExamplePda> = 
   Account::try_from(example_pda1_account_info)?;

Check uninitialized

I haven't checked that this actually compiles but this is adapted from the zero discriminator check that the zero constraint source code uses.

let mut __data: &[u8] = ctx.accounts.example_pda1.to_account_info().try_borrow_data()?;
let mut __disc_bytes = [0u8; 8];
__disc_bytes.copy_from_slice(&__data[..8]);
let __discriminator = u64::from_le_bytes(__disc_bytes);
if __discriminator != 0 {
    return Err();
}

With constraints

Check initialized

To check that a program account has been initialized you can just get anchor to try and load the program account in the accounts context, similar to how you verify the account is empty above.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump = example_pda1.bump,
)]
pub example_pda1: Account<'info, ExamplePdaAccount>

Anchor will try to load the account data and check that the 8 bytes at the start of the account match the expected discriminator.

Check uninitialized

For checking that an account is not initialized I would instead check that the system program still owns the account. A system program account can't have data on it, though it might have some lamports in it.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump,
)]
pub example_pda1: SystemAccount<'info>

Finally zero doesn't do what you expect it to do here. It does a lot more. Check out the constraints doc https://docs.rs/anchor-lang/latest/anchor_lang/derive.Accounts.html#constraints. Essentially it checks that the 8 byte discriminator is not initialized and that the account has enough solana rent to be rent exempt (although this is now a run time requirement) but it will also check that your account is owned by the program calling the function, ensures the account is mutable, and initializes the account + the discriminator. zero is essentially a lighter weight version of init that needs to be called in different scenarios that are explained in the docs.

Use this constraint (zero) if you want to create an account in a previous instruction and then initialize it in your instruction instead of using init. This is necessary for accounts that are larger than 10 Kibibyte because those accounts cannot be created via a CPI (which is what init would do).

added 972 characters in body
Source Link
Henry E
  • 2.9k
  • 7
  • 32

To check that a program account has been initialized you can just get anchor to try and load the program account in the accounts context, similar to how you verify the account is empty above.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump = example_pda1.bump,
)]
pub example_pda1: Account<'info, ExamplePdaAccount>

Anchor will try to load the account data and check that the 8 bytes at the start of the account match the expected discriminator.

For checking that an account is not initialized I would instead check that the system program still owns the account. A system program account can't have data on it, though it might have some lamports in it.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump,
)]
pub example_pda1: SystemAccount<'info>

Finally zero doesn't do what you expect it to do here. It does a lot more. Check out the constraints doc https://docs.rs/anchor-lang/latest/anchor_lang/derive.Accounts.html#constraints. Essentially it checks that the 8 byte discriminator is not initialized and that the account has enough solana rent to be rent exempt (although this is now a run time requirement) but it will also check that your account is owned by the program calling the function, ensures the account is mutable, and initializes the account + the discriminator. zero is essentially a lighter weight version of init that needs to be called in different scenarios that are explained in the docs.

Use this constraint (zero) if you want to create an account in a previous instruction and then initialize it in your instruction instead of using init. This is necessary for accounts that are larger than 10 Kibibyte because those accounts cannot be created via a CPI (which is what init would do).

To check that a program account has been initialized you can just get anchor to try and load the program account in the accounts context, similar to how you verify the account is empty above.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump = example_pda1.bump,
)]
pub example_pda1: Account<'info, ExamplePdaAccount>

Anchor will try to load the account data and check that the 8 bytes at the start of the account match the expected discriminator.

For checking that an account is not initialized I would instead check that the system program still owns the account. A system program account can't have data on it, though it might have some lamports in it.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump,
)]
pub example_pda1: SystemAccount<'info>

To check that a program account has been initialized you can just get anchor to try and load the program account in the accounts context, similar to how you verify the account is empty above.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump = example_pda1.bump,
)]
pub example_pda1: Account<'info, ExamplePdaAccount>

Anchor will try to load the account data and check that the 8 bytes at the start of the account match the expected discriminator.

For checking that an account is not initialized I would instead check that the system program still owns the account. A system program account can't have data on it, though it might have some lamports in it.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump,
)]
pub example_pda1: SystemAccount<'info>

Finally zero doesn't do what you expect it to do here. It does a lot more. Check out the constraints doc https://docs.rs/anchor-lang/latest/anchor_lang/derive.Accounts.html#constraints. Essentially it checks that the 8 byte discriminator is not initialized and that the account has enough solana rent to be rent exempt (although this is now a run time requirement) but it will also check that your account is owned by the program calling the function, ensures the account is mutable, and initializes the account + the discriminator. zero is essentially a lighter weight version of init that needs to be called in different scenarios that are explained in the docs.

Use this constraint (zero) if you want to create an account in a previous instruction and then initialize it in your instruction instead of using init. This is necessary for accounts that are larger than 10 Kibibyte because those accounts cannot be created via a CPI (which is what init would do).

Source Link
Henry E
  • 2.9k
  • 7
  • 32

To check that a program account has been initialized you can just get anchor to try and load the program account in the accounts context, similar to how you verify the account is empty above.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump = example_pda1.bump,
)]
pub example_pda1: Account<'info, ExamplePdaAccount>

Anchor will try to load the account data and check that the 8 bytes at the start of the account match the expected discriminator.

For checking that an account is not initialized I would instead check that the system program still owns the account. A system program account can't have data on it, though it might have some lamports in it.

#[account(
  seeds = [
    b"some-seed",
    partner1_pub.key().as_ref(),
  ],
  bump,
)]
pub example_pda1: SystemAccount<'info>