PDA Accounts

Summary

Create PDA accounts via invoke_signed with the PDA's seeds. Only the owning program can sign for a PDA. Anchor's init constraint automates PDA account creation.

PDA Signing via invoke_signed

When a program needs to sign on behalf of a PDA during a CPI, it uses invoke_signed with the PDA's seeds. The runtime verifies the seeds derive the expected PDA using the calling program's ID, ensuring only the owning program can sign. For the full verification flow, see PDA Signing.

Create a PDA Account

Deriving a PDA and creating an account at a PDA are separate operations. You must explicitly create the account after deriving the address.

To create an account at a PDA, the deriving program invokes the System Program's create_account instruction via invoke_signed, passing the PDA's seeds so the runtime can verify the program's authority over that address.

The example below uses the Anchor framework to create a new account with a program-derived address. The program includes a single initialize instruction to create the new account, which will store the user address and bump seed used to derive the PDA.

Program
use anchor_lang::prelude::*;
declare_id!("75GJVCJNhaukaa2vCCqhreY31gaphv7XTScBChmr1ueR");
#[program]
pub mod pda_account {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
let account_data = &mut ctx.accounts.pda_account;
// store the address of the `user`
account_data.user = *ctx.accounts.user.key;
// store the canonical bump
account_data.bump = ctx.bumps.pda_account;
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(mut)]
pub user: Signer<'info>,
#[account(
init,
// define the seeds to derive the PDA
seeds = [b"data", user.key().as_ref()],
// use the canonical bump
bump,
payer = user,
space = 8 + DataAccount::INIT_SPACE // 8 bytes for Anchor account discriminator
)]
pub pda_account: Account<'info, DataAccount>,
pub system_program: Program<'info, System>,
}
#[account]
#[derive(InitSpace)]
pub struct DataAccount {
pub user: Pubkey,
pub bump: u8,
}

The init constraint tells Anchor to invoke the System Program to create a new account using the PDA as the address. The seeds used to create the PDA are:

  • The fixed string: "data"
  • The address of the user account provided in the instruction
  • The canonical bump seed

In this example, the bump constraint is not assigned a value, so Anchor will use find_program_address to derive the PDA and find the bump.

pda_account
#[account(
init,
seeds = [b"data", user.key().as_ref()],
bump,
payer = user,
space = 8 + DataAccount::INIT_SPACE // 8 bytes for Anchor account discriminator
)]
pub pda_account: Account<'info, DataAccount>,

The test file below contains a transaction that invokes the initialize instruction to create a new account with a program-derived address. The file contains code to derive the PDA.

The example also shows how to fetch the new account that will be created.

Test
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { PdaAccount } from "../target/types/pda_account";
import { PublicKey } from "@solana/web3.js";
describe("pda-account", () => {
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
const program = anchor.workspace.PdaAccount as Program<PdaAccount>;
const user = provider.wallet as anchor.Wallet;
// Derive the PDA address using the seeds specified on the program
const [PDA] = PublicKey.findProgramAddressSync(
[Buffer.from("data"), user.publicKey.toBuffer()],
program.programId
);
it("Is initialized!", async () => {
const transactionSignature = await program.methods
.initialize()
.accounts({
user: user.publicKey
})
.rpc();
console.log("Transaction Signature:", transactionSignature);
});
it("Fetch Account", async () => {
const pdaAccount = await program.account.dataAccount.fetch(PDA);
console.log(JSON.stringify(pdaAccount, null, 2));
});
});

If you invoke the initialize instruction again with the same user address seed, the transaction will fail. This happens because an account already exists at the derived address.

Is this page helpful?

सामग्री तालिका

पृष्ठ संपादित करें

द्वारा प्रबंधित

© 2026 सोलाना फाउंडेशन। सर्वाधिकार सुरक्षित।
जुड़े रहें