Skip to main content

Overview

Program Derived Addresses (PDAs) are deterministic addresses derived from seeds and the program ID. NullGraph uses PDAs for all on-chain accounts to ensure predictable, collision-free addressing.

Seed Constants

All PDA seeds are defined in the constants file:
lib/constants.ts

PDA Functions

All PDA derivation functions are located in lib/pda.ts and follow the same pattern:

findProtocolStatePDA

Derive the global protocol state account address.

Seed Structure

Buffer
Buffer.from('protocol_state')

Usage Example

Implementation

lib/pda.ts
There is only one protocol state account per program deployment.

findNullResultPDA

Derive the address for a specific null result (NKA) submission.

Parameters

PublicKey
required
The public key of the researcher submitting the null result
number | BN
required
The specimen number (NKA counter value). Can be a JavaScript number or BN instance.

Seed Structure

Buffer
Buffer.from('null_result')
Buffer
researcher.toBuffer() - 32 bytes
Buffer
specimenNumber as little-endian u64 - 8 bytes

Usage Example

Implementation

lib/pda.ts

findBountyPDA

Derive the address for a specific bounty.

Parameters

PublicKey
required
The public key of the bounty creator
number | BN
required
The bounty number (bounty counter value)

Seed Structure

Buffer
Buffer.from('null_bounty')
Buffer
creator.toBuffer() - 32 bytes
Buffer
bountyNumber as little-endian u64 - 8 bytes

Usage Example

Implementation

lib/pda.ts

findVaultPDA

Derive the token vault address for a specific bounty.

Parameters

PublicKey
required
The public key of the bounty account

Seed Structure

Buffer
Buffer.from('bounty_vault')
Buffer
bountyPDA.toBuffer() - 32 bytes

Usage Example

Implementation

lib/pda.ts
The vault is a token account that holds BIO tokens for the bounty reward. It’s owned by the program and uses the bounty PDA as a seed.

findSubmissionPDA

Derive the address for a bounty submission.

Parameters

PublicKey
required
The public key of the bounty
PublicKey
required
The public key of the null result being submitted

Seed Structure

Buffer
Buffer.from('bounty_submission')
Buffer
bountyPDA.toBuffer() - 32 bytes
Buffer
nullResultPDA.toBuffer() - 32 bytes

Usage Example

Implementation

lib/pda.ts
Each null result can only be submitted to a bounty once. The PDA ensures uniqueness.

PDA Relationships

Here’s how PDAs relate to each other:

Common Patterns

Deriving Next Account

Checking Account Existence

Batch Deriving PDAs

Return Values

All PDA functions return a tuple:
PublicKey
The derived Program Derived Address
number
The bump seed (0-255) used to find the PDA off the ed25519 curve

Best Practices

Always use the PDA derivation functions instead of hardcoding addresses. PDAs are deterministic and will be the same across all clients.
When incrementing counters (specimenNumber, bountyNumber), always fetch the latest protocol state first to avoid PDA collisions.
The bump seed is automatically stored in account data by the program. You typically don’t need to use it in frontend code.

Next Steps

Hooks

Learn how hooks use PDAs internally for transactions

Types

Explore account structures that live at these PDAs