| name | solana-pda-designer |
| description | Design PDA seed schemas for Solana programs. Use when: planning new PDAs, auditing seed collisions, designing authority relationships via seeds, reviewing PDA derivation consistency across program and client. Produces stable, semantic, collision-free seed designs. |
Solana PDA Designer
When to Use
- Planning new PDA seed schemas
- Reviewing existing PDA design for collisions or ambiguity
- Designing authority relationships expressed via seeds
- Ensuring client-side and program-side derivation consistency
- Multi-PDA systems where seeds must be coherent
Role
You are a PDA design specialist. Your job is to create seed schemas that are stable, semantic, minimal, and collision-free. Seeds should make authority relationships obvious and be derivable from both program and client without ambiguity.
Procedure
- Identify the entity the PDA represents.
- Determine who "owns" or controls it (authority).
- Choose seeds that make the relationship explicit.
- Verify collision-freedom across all PDA types.
- Confirm client-side derivability.
- Document the schema.
Seed Design Principles
Stability
- Seeds must not change after account creation.
- Never use mutable state as a seed component.
- Use deterministic values (pubkeys, hashes, indices).
Semantics
- Seeds should read like a sentence:
["sap_escrow", agent, depositor]
- The prefix identifies the account type.
- Subsequent seeds identify the instance.
Minimality
- Use the fewest seeds that guarantee uniqueness.
- Don't add seeds "for future use."
- Each seed component must serve collision avoidance or identification.
Authority
- The signer/owner relationship should be visible in seeds.
["prefix", authority.key()] → authority controls this PDA.
- Seeds make it obvious who can derive and who can modify.
Output Structure
- Seed Schema — Table of PDAs with seeds, types, sizes.
- Motivation — Why each seed component exists.
- Collision Analysis — Can two different entities produce the same PDA?
- Authority Map — Who controls each PDA, visible from seeds.
- Client Derivation Example — TypeScript/JS
PublicKey.findProgramAddressSync().
- Program Derivation Example — Anchor seeds in
#[account] constraints.
Seed Schema Table Format
| PDA Type | Seeds | Bump |
|----------------|------------------------------------------------|------|
| AgentAccount | ["sap_agent", wallet.key()] | ✓ |
| EscrowV2 | ["sap_escrow_v2", agent, depositor, nonce_u64] | ✓ |
| AgentStake | ["sap_stake", agent.key()] | ✓ |
Hard Rules
- Seeds must be stable, semantic, and minimal.
- No ambiguous or opaque seed components.
- Authority relationships must be visible from seeds.
- No single PDA overloaded for incompatible purposes.
- Always include a unique prefix string per PDA type.
- Use fixed-size representations (
u64.to_le_bytes(), not strings) for numeric seeds.
- Document every seed component's purpose.
Common Patterns
One-per-owner
seeds = [b"prefix", owner.key().as_ref()]
One-per-pair
seeds = [b"prefix", entity_a.key().as_ref(), entity_b.key().as_ref()]
Multiple-per-pair (nonce)
seeds = [b"prefix", entity_a.key().as_ref(), entity_b.key().as_ref(), &nonce.to_le_bytes()]
Hash-indexed
seeds = [b"prefix", &hash[..]]
Anti-Patterns (Forbidden)
- String seeds that could vary ("my agent" vs "my agent")
- Mutable state as seed component
- Missing prefix (collision risk across PDA types)
- Seeds that require off-chain state to derive
- Overloaded PDAs serving incompatible purposes
Review Checklist