current location:Home >> Blockchain knowledge >> Program Derived Addresses (PDAs) on Solana: The Complete Guide

Program Derived Addresses (PDAs) on Solana: The Complete Guide

admin Blockchain knowledge 1525

 Program Derived Addresses (PDAs) on Solana: The Complete Guide

Program Derived Addresses (PDAs) on Solana: The Complete Guide


 🔍 What Are Program Derived Addresses?

PDAs are special Solana accounts that:

- Have no private keys (unlike standard accounts)

- Are generated programmatically using:

  - Parent Program ID

  - Seed array (custom strings)

  - Bump seed (ensures off-curve derivation)

- Enable secure cross-program communication


Standard vs. PDA Accounts

| Feature | Standard Account | PDA |

|---------|-----------------|-----|

| Keypair | ED25519 keypair | No private key |

| Signing | Can sign transactions | Parent program can "sign" |

| Storage | Stores SOL/tokens | Stores program state |


 🧠 How PDAs Work: The Technical Magic

1. Inputs: Program ID + Seeds (e.g., user address)

2. Hashing: SHA-512 generates potential address

3. Curve Check: 

   - If on ED25519 curve → Try next bump seed (starting from 255)

   - If off-curve → Valid PDA found!


```rust

// Anchor example finding PDA

let (pda, bump) = Pubkey::find_program_address(

    &[b"custom_seed", user.key.as_ref()],

    program_id

);

```

 💡 Why PDAs Matter: 3 Key Benefits


1. State Management

PDAs act as program-owned storage:

```rust

// Storing user profile data

[account]

pub struct UserProfile {

    pub authority: Pubkey,  // User's main wallet

    pub pfp_nft: Pubkey,    // Current PFP NFT

    pub bump: u8           // Bump seed

}

```


2. Hashmap-Like Structures

Create efficient lookups using seeds:

```python

 Pseudocode: NFT Profile System

user_pda = find_pda(

    seeds = [user_wallet, "profile"],

    program_id = pfp_program

)


nft_pda = find_pda(

    seeds = [nft_mint, "metadata"],

    program_id = token_program

)

```


3. Secure Cross-Program Invocations (CPI)

Enable trustless program interactions:

```rust

// Changing PFP via CPI

pub fn update_pfp(ctx: Context<UpdatePfp>, new_nft: Pubkey) -> Result<()> {

    let cpi_accounts = UpdatePfpAccounts {

        user_profile: ctx.accounts.user_profile,

        nft_program: ctx.accounts.nft_program,

        // ...

    };

    

    // PDA authorizes this action!

    pfp_program::update_profile(cpi_accounts, new_nft)

}

```

 🛠️ Real-World PDA Use Case: NFT Profile System


Scenario

1. User connects wallet to dApp

2. Selects NFT as profile picture (PFP)

3. Program stores choice via PDA


Implementation Flow

1. Generate PDA:

   - Seeds: `[user_wallet, "profile"]`

   - Stores: `{ current_nft: mint_address }`


2. Change PFP:

   ```mermaid

   sequenceDiagram

       User->>Core Program: "Set new PFP"

       Core Program->>PDA: Verify ownership

       PDA->>NFT Program: Check NFT belongs to user

       NFT Program-->>PDA: Confirmation

       PDA->>Core Program: Update record

   ```


3. Security Benefit:

   - No private keys stored on-chain

   - Only parent program can modify PDA

   - Fully decentralized & composable


 📚 PDA FAQs


Q: Can PDAs hold SOL or tokens?

A: Yes! While they can't "sign" traditionally, they can:

- Receive SOL/tokens

- Be controlled by parent programs

- Participate in DeFi protocols


Q: How are PDAs different from Ethereum storage?

A: Key contrasts:

| Ethereum | Solana PDA |

|----------|------------|

| Fixed contract storage | Dynamic PDA accounts |

| State tied to contract | State separated into PDAs |

| More expensive updates | Granular, cheaper updates |


Q: What's the bump seed for?

A: Ensures the derived address:

1. Isn't on ED25519 curve

2. Has no private key

3. Starts search from 255 downward


 🚀 Getting Started with PDAs


1. Anchor Framework (Recommended)

```rust

[derive(Accounts)]

pub struct CreateProfile<'info> {

    [account(

        init,

        payer = user,

        seeds = [b"profile", user.key().as_ref()],

        bump,

        space = 8 + 32 + 32 + 1

    )]

    pub user_profile: Account<'info, UserProfile>,

    // ...

}

```


2. Solana Web3.js (JavaScript)

```javascript

const [pda, bump] = await PublicKey.findProgramAddress(

  [Buffer.from("profile"), userWallet.publicKey.toBuffer()],

  programId

);

```


3. Security Best Practices

✔ Always validate PDA ownership in programs  

✔ Use descriptive seed prefixes (e.g., "user_profile")  

✔ Store bump seeds in account data for verification  


 💡 Pro Tip: PDA Design Patterns

- Versioned Accounts: Add version number to seeds

- Sharded Storage: Split large data across multiple PDAs

- Program Signer: Use PDAs as "virtual signers" in CPIs


> "PDAs turn Solana into a giant key-value store where programs manage their own state securely." - Solana Core Dev


Ready to master PDAs? Start building with:

- [Solana Cookbook](https://solanacookbook.com) (PDA recipes)

- [Anchor Documentation](https://www.anchor-lang.com) (Framework how-tos)

- [Solana Dev Discord](https://solana.com/discord) (Real-time help)

If you have any questions or uncertainties, please join the official Telegram group: https://t.me/GToken_EN

GTokenTool

GTokenTool is the most comprehensive one click coin issuance tool, supporting multiple public chains such as TON, SOL, BSC, etc. Function: Create tokensmarket value managementbatch airdropstoken pre-sales IDO、 Lockpledge mining, etc. Provide a visual interface that allows users to quickly create, deploy, and manage their own cryptocurrencies without writing code.

Similar recommendations