Close-up of hardware security key on desk, laptop with security setup guide, home office background, cryptocurrency security ritual.
Protocols

Program Derived Address (PDA) Design Patterns

Canonical patterns for using PDAs as deterministic, program-controlled accounts including bump seed management, multi-signer derivation, and security anti-patterns. Covers common privilege escalation bugs and how auditors detect PDA misuse.
introduction
DETERMINISTIC PROGRAM ACCOUNT CONTROL

Introduction

Program Derived Addresses are the foundational primitive for programmatic custody on Solana, enabling deterministic account derivation and off-curve signing authority.

Program Derived Addresses (PDAs) are a core Solana account model primitive that allows programs to deterministically derive addresses and sign for them without holding a private key. A PDA is a 32-byte address computed from a set of seeds and a program ID, deliberately placed off the ed25519 curve to ensure no external entity can generate a valid signature for it. This off-curve property is the security foundation: only the program that owns the PDA can "sign" via invoke_signed, making PDAs the canonical mechanism for programmatic custody of token accounts, state accounts, and authority records across the Solana ecosystem.

The canonical PDA derivation process uses Pubkey::find_program_address, which iterates through bump seeds (starting at 255 and decrementing) until it finds an address off the ed25519 curve. The resulting bump seed becomes part of the derivation path and must be stored or re-derived for every invoke_signed call. Misunderstanding this bump seed lifecycle is the root cause of many security vulnerabilities: programs that accept user-supplied bump seeds without validation, programs that fail to verify PDA ownership before modifying account data, and programs that conflate PDA derivation with authority checks all create privilege escalation vectors that auditors systematically target during security reviews.

PDA design patterns extend beyond simple derivation into multi-signer CPI contexts, where a single instruction can authorize actions across multiple PDAs simultaneously. This enables complex atomic operations—like moving funds between two program-controlled vaults or updating interdependent state accounts—without requiring intermediate transactions. However, these patterns introduce subtle security considerations around seed collision, bump seed canonicalization, and the distinction between PDA signer privileges and account ownership. Teams building upgradeable programs face additional complexity: if a program's upgrade authority changes the program ID, all existing PDAs become orphaned unless migration logic is embedded in the original derivation design.

For protocol architects and security reviewers, PDA design patterns represent a critical intersection of account model constraints, runtime behavior, and authorization logic. Chainscore Labs provides PDA-focused security reviews that examine bump seed handling, seed collision resistance, CPI authorization chains, and upgrade-related PDA migration risks. Teams deploying programs that rely on complex PDA hierarchies or multi-signer CPI flows should engage a review before mainnet deployment to identify privilege escalation paths that static analysis tools frequently miss.

PDA DESIGN PATTERNS

Quick Facts

Operational and security facts about Program Derived Addresses that affect program design, audit surface, and account authority management

FieldValueWhy it matters

Deterministic derivation

PDAs are derived from a program ID and a set of seeds, optionally including a bump seed to push the address off the ed25519 curve

Programs can deterministically locate and control accounts without managing a private key, enabling state management and cross-program interaction patterns

Bump seed canonical range

Bump seeds are a single byte (u8) in the range 0–255, with 255 being the starting point for find_program_address iteration

Using a non-canonical bump (one that is not the highest valid bump) can break composability and cause security issues if other programs derive the PDA with the canonical bump

Signer authority

PDAs can act as signers in CPIs via invoke_signed, but they cannot sign transactions directly because they lack a private key

This allows programs to control token accounts, escrow vaults, and governance authorities without exposing a private key, but requires careful seed management to prevent unauthorized signing

Seed collision risk

If a program uses user-supplied seeds without domain separation or type prefixes, different logical accounts can map to the same PDA

Seed collision is a common privilege escalation vector where an attacker can reuse a PDA intended for one purpose to authorize an unrelated action

Close-and-reinitialize attack

If a program closes a PDA account and later re-derives it with the same seeds, an attacker can reinitialize the account with malicious state before the program uses it again

Auditors flag this as a critical vulnerability; mitigation requires either never reusing a closed PDA's seeds or checking the account's owner and data length after re-derivation

Multi-signer PDA derivation

A single instruction can use invoke_signed with multiple PDAs, each derived from different seeds, to satisfy multi-signer requirements in a CPI

This enables complex custody patterns like multi-party escrow or DAO-controlled treasuries, but requires the program to correctly derive and pass all required signer seeds

PDA as token account authority

Token-2022 and SPL Token accounts can have a PDA as their authority, enabling programmatic control over token transfers, freezes, and closes

This is the foundation for escrow programs, AMM pools, and staking derivatives, but incorrect authority validation can lead to total loss of funds

technical-context
DETERMINISTIC DERIVATION AND SECURITY MODEL

Technical Mechanism

How PDAs create program-controlled addresses without private keys, and why the bump seed is the critical security primitive.

Program Derived Addresses (PDAs) are Solana's mechanism for creating accounts that are owned and controlled by on-chain programs rather than by external keypairs. A PDA is derived deterministically by hashing a set of seeds—typically including a user's wallet address, a static string, and other contextual data—along with the program's own ID. The resulting 32-byte output is checked to ensure it falls off the ed25519 curve, guaranteeing that no corresponding private key exists. This cryptographic property is the foundation of PDA security: because no external signer can produce a valid signature for the address, only the owning program can authorize state changes to the account via invoke_signed.

The invoke_signed function is the sole mechanism by which a program can 'sign' for a PDA during a Cross-Program Invocation (CPI). The program provides the same seeds used to derive the PDA, along with a bump seed—a single byte that pushed the address off the ed25519 curve during derivation. The runtime re-derives the address from the provided seeds and program ID, and if it matches the PDA in the instruction's account list, the runtime treats the program as a valid signer. The canonical bump is the first bump value (starting from 255 and decrementing) that produces an off-curve address. Using a non-canonical bump is functionally valid but wastes compute units and is a strong indicator of a flawed or malicious program, as it can be used to create multiple valid derivation paths for the same logical account.

The most critical security anti-pattern in PDA design is the failure to validate all seeds, particularly user-provided ones. If a program derives a PDA using a user's wallet address as a seed but does not verify that the user has signed the transaction, an attacker can substitute their own address, derive a different PDA, and hijack the account's authority. This class of 'type substitution' or 'seed injection' vulnerability is a leading cause of privilege escalation bugs. Auditors systematically check that every PDA derivation in a program is accompanied by a corresponding signer check or an equivalent constraint that anchors the PDA to a specific, transaction-signed authority. The Anchor framework's seeds constraint in its #[account(...)] macro automates this check, but native programs must enforce it manually in their instruction handlers.

WHO MUST REVIEW PDA SECURITY

Affected Actors

Program Developers

PDA design flaws are the most common source of critical vulnerabilities in Solana programs. Developers must ensure that every PDA derivation includes a unique seed domain separator to prevent cross-function collision attacks.

Immediate actions:

  • Audit all Pubkey::find_program_address calls for missing or weak seeds.
  • Verify that bump seeds are stored on-chain and validated on every instruction invocation.
  • Ensure that programs check both the account owner and the PDA derivation before trusting account data.

Chainscore Labs can review your program's PDA architecture, identify missing authorization checks, and harden your derivation logic against privilege escalation attacks.

implementation-impact
PDA SECURITY & IMPLEMENTATION

Core Design Patterns

Canonical patterns for deterministic, program-controlled accounts and the critical security rules that prevent privilege escalation.

01

Deterministic Address Derivation

PDAs are derived using a program ID and a set of seeds via find_program_address. This creates an address off the ed25519 curve, ensuring no private key exists. The canonical bump seed (the first valid bump found, starting from 255) must be stored and validated on every instruction to prevent bump seed canonicalization attacks where an attacker provides a different bump to create a distinct PDA.

02

Signer Authorization via `invoke_signed`

Programs authorize PDA actions using invoke_signed, which generates a synthetic signature from the program's ID and the exact seeds and bump used to derive the PDA. A mismatch in seeds or bump will cause the CPI to fail. This pattern is essential for token vaults, escrow accounts, and cross-program interactions where the PDA must act as a signer without a private key.

03

Multi-Signer PDA Derivation

For shared control, PDAs can be derived using multiple public keys as seeds. A common pattern for a 2-of-2 escrow between users A and B is find_program_address(&[b"escrow", user_a.key.as_ref(), user_b.key.as_ref()], program_id). This ensures the escrow account is deterministically tied to both parties and can only be controlled by the program when both users authorize the interaction.

04

Anti-Pattern: Missing Bump Validation

A critical vulnerability flagged by auditors is failing to validate the bump seed provided by the caller. If a program uses create_program_address with a user-supplied bump instead of re-deriving and checking it, an attacker can forge a valid PDA for a different set of seeds. Always re-derive the PDA using find_program_address and assert the bump matches the one stored in the account or provided by the caller.

05

Anti-Pattern: Authority Mix-Up in CPI

A privilege escalation bug occurs when a program uses its own PDA as the signer for a CPI but fails to verify the authority of the accounts it is modifying. For example, a program might use its PDA to close a token account without checking that the token account's owner is the PDA. An attacker could pass a victim's token account and drain it. Always verify that the target account's owner field matches the expected PDA before signing.

06

Pattern: PDA as a Token Vault

A foundational DeFi pattern is a PDA-owned token account. The program derives a PDA using seeds like b"vault" and the user's public key, then creates an associated token account (ATA) with that PDA as the owner. Funds can only be moved by the program via invoke_signed with the correct seeds. This pattern underpins escrow, staking, and liquidity pool contracts by guaranteeing that only the program logic can release user deposits.

COMMON PDA VULNERABILITY CLASSES

Security Anti-Patterns and Risks

Recurring security flaws in PDA-based authorization that lead to privilege escalation, unauthorized fund transfers, or account takeover. Each row identifies a failure mode, how it manifests in Solana programs, which actors are exposed, and the recommended verification or remediation step.

Anti-PatternFailure modeWho is affectedMitigation

Missing bump seed validation

Program accepts a user-supplied bump without verifying it produces the expected PDA, allowing an attacker to forge a PDA from a different canonical bump

DeFi protocols, token vaults, staking programs

Always derive the PDA on-chain using Pubkey::find_program_address and validate the provided bump matches

Unchecked account owner in PDA authorization

Program assumes a PDA is owned by itself without verifying the owner field, allowing an attacker to pass an account owned by a malicious program that mimics the PDA address

Lending protocols, escrow programs, AMM pools

Explicitly check that ctx.accounts.pda.owner == program_id before trusting the account data

Type confusion via PDA reuse

Same PDA seed derivation is used for multiple account types, allowing an attacker to pass a valid PDA of one type where another type is expected

Protocols with multiple PDA-governed vaults or state accounts

Include a unique discriminator in seeds (e.g., b"vault" vs b"state") and validate account discriminator bytes on deserialization

Missing signer seed invocation

Program derives a PDA but fails to invoke it with the seeds during CPI, causing the CPI to lack the PDA's signing authority

Programs managing token accounts or executing cross-program transfers

Use invoke_signed with the correct seeds and bump when the PDA must act as a signer in CPIs

Arbitrary CPI destination with PDA authority

Program invokes an arbitrary program provided by the user using the PDA's signer privileges, enabling privilege escalation through a malicious CPI target

Programs that delegate PDA signing to user-specified programs

Whitelist allowed CPI destinations or restrict the program ID to known, verified programs

PDA initialization without rent-exemption check

Program initializes a PDA account without verifying it is rent-exempt, allowing an attacker to drain lamports or cause account closure

Programs that dynamically create PDA accounts

Verify account.lamports() >= Rent::get()?.minimum_balance(space) before marking the account as initialized

Reinitialization attack on PDA

Program fails to check that a PDA has not already been initialized, allowing an attacker to reinitialize it with attacker-controlled data or overwrite critical state

Programs with one-time PDA initialization flows

Check for a discriminator or initialized flag at the start of the instruction and reject if already set

Seed collision across users or scopes

PDA seeds lack user-specific or scope-specific components, allowing one user's PDA to collide with another's or enabling cross-account manipulation

Multi-user protocols, DAOs, token vesting contracts

Include the user's public key, a unique identifier, or a domain separator in the seed derivation to ensure isolation

PDA SECURITY AND CORRECTNESS

Developer Implementation Checklist

A practical checklist for developers implementing Program Derived Addresses. Each item targets a common vulnerability or integration failure that auditors and runtime experts flag during security reviews.

What to check: Every instruction that receives a PDA account must re-derive the address on-chain using Pubkey::find_program_address and compare it against the provided account key.

Why it matters: The runtime does not automatically verify that a provided account is the correct PDA for the given seeds. Without explicit validation, an attacker can supply a different account controlled by them, leading to unauthorized access to privileged program state.

Readiness signal: Your instruction handler contains an explicit assert_eq!(derived_key, ctx.accounts.my_pda.key()) check before any mutable access to the account data.

Chains We Build On

Looking to build on a specific blockchain?

We build smart contracts, DeFi applications, wallets, tokenization platforms, and blockchain infrastructure across the major ecosystems teams choose today. That includes Ethereum, Arbitrum, Optimism, Polygon, Avalanche, Solana, Sui, Aptos, Hedera, Stellar, and NEAR, with support for additional EVM and non-EVM networks based on your product requirements.

EVM ecosystems

  • Ethereum logo
    Ethereum
  • Arbitrum logo
    Arbitrum
  • Optimism logo
    Optimism
  • Polygon logo
    Polygon
  • Avalanche logo
    Avalanche
  • Cronos logo
    Cronos

Non-EVM ecosystems

  • Solana logo
    Solana
  • Sui logo
    Sui
  • Aptos logo
    Aptos
  • Hedera logo
    Hedera
  • Stellar logo
    Stellar
  • NEAR logo
    NEAR

Additional ecosystems

  • Polkadot logo
    Polkadot
  • Cosmos logo
    Cosmos
  • TON logo
    TON
  • Cardano logo
    Cardano
  • Algorand logo
    Algorand
  • Tempo logo
    Tempo

Also available for Base, appchains, custom EVM networks, and cross-chain product architecture.

PDA SECURITY AND DESIGN

Frequently Asked Questions

Common questions from developers and auditors about Program Derived Address design patterns, bump seed management, and privilege escalation risks.

Missing or improper signer seed validation. The most frequent critical finding is a program that derives a PDA but fails to verify that the correct signer seeds were used, allowing an attacker to provide a different set of seeds that derives the same PDA but grants unauthorized access.

What to check:

  • Every PDA used as a signer must have its seeds validated against expected values, not just its address
  • Seeds provided by users (e.g., user pubkeys, token mint addresses) must be verified to match the expected authorization context
  • The bump seed must be canonical—using a user-supplied bump without validation is a common vector

Why it matters: An attacker can craft alternative seed combinations that derive the same PDA but represent a different authorization context, effectively bypassing access controls.

Trusted by Industry Leaders

Delivering blockchain solutions for 5+ years.

We have partnered with 50+ leading DeFi protocols, NFT ecosystems, and fintech innovators to build secure, scalable, and capital-efficient blockchain products.

Selected Partners & Clients

ChainVote logo
Reax logo
Sokail logo
Swapsicle logo
SyntheX logo
Tekika logo
Telos logo
Zexe logo
ChainVote logo
Reax logo
Sokail logo
Swapsicle logo
SyntheX logo
Tekika logo
Telos logo
Zexe logo
ChainVote logo
Reax logo
Sokail logo
Swapsicle logo
SyntheX logo
Tekika logo
Telos logo
Zexe logo
ChainVote logo
Reax logo
Sokail logo
Swapsicle logo
SyntheX logo
Tekika logo
Telos logo
Zexe logo
“I've been working with Chainscore Labs for last 3+ years, they've consistently delivered with strong ownership across multiple projects. The team is reliable and detail-oriented.”
L
Lee Erswell
CEO, Telos Foundation
how to get started

How to get started?

If you're looking for blockchain integration, ChainScore Labs has 5+ years of experience helping teams build and integrate exchanges, wallets, smart contracts, tokenization solutions, and protocol-connected products, we can help you choose the right path, integrate securely, and get to production faster. Our team consists of experienced blockchain developers and architects who can help you with your blockchain integration needs.

01

Exploration & Strategy

Define your product goals and choose the right blockchain architecture for your use case.

02

Architecture & Design

Design the smart contracts, tokenomics, and security parameters of your system.

03

Development & Integration

Build and integrate with wallets, oracles, and front-end dApps for a seamless experience.

04

Security & Launch

Comprehensive audits followed by a risk-managed mainnet deployment to protect your users.

Start a build

Need a blockchain engineering team?

Send the project context and we will respond with next steps, scope questions, and a practical path to delivery.