Skip to main content
Sigvex

PDA Bump Seed Reuse Remediation

How to fix reuse of bump seeds across multiple PDA derivations.

PDA Bump Seed Reuse Remediation

Overview

Related Detector: PDA Bump Seed Reuse

PDA bump seed reuse occurs when the same bump value is shared across PDA derivations with different seed patterns. The fix is to derive and store a separate canonical bump for each PDA type.

Before (Vulnerable)

let bump = account_data.bump;
let vault = create_program_address(&[b"vault", user, &[bump]], pid)?;
let meta = create_program_address(&[b"meta", user, &[bump]], pid)?; // Same bump!

After (Fixed)

let (vault, vault_bump) = find_program_address(&[b"vault", user], pid);
let (meta, meta_bump) = find_program_address(&[b"meta", user], pid);
account_data.vault_bump = vault_bump;
account_data.meta_bump = meta_bump;

Alternative Mitigations

1. Anchor seeds with per-account bumps

#[account(seeds = [b"vault", user.key().as_ref()], bump = vault.bump)]
pub vault: Account<'info, Vault>,

#[account(seeds = [b"meta", user.key().as_ref()], bump = meta.bump)]
pub meta: Account<'info, Metadata>,

2. Store bumps in a config struct

#[account]
pub struct PdaConfig {
    pub vault_bump: u8,
    pub escrow_bump: u8,
    pub metadata_bump: u8,
}

Common Mistakes

Mistake 1: Using a single bump field for all PDAs

#[account]
pub struct State {
    pub bump: u8, // WRONG: one bump for all PDAs
}

Each PDA type needs its own bump field.

Mistake 2: Hardcoding bump values

let bump: u8 = 255; // WRONG: hardcoded, not canonical

Always use find_program_address to derive canonical bumps.

References