Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Ge0frey/nullgraph/llms.txt
Use this file to discover all available pages before exploring further.
Architecture
NullGraph is a fully on-chain protocol built on Solana with zero backend infrastructure. All state lives in Program Derived Addresses (PDAs), all logic executes in an Anchor program, and all reads happen via JSON-RPC.System overview
Data flow
- Writes go through the Solana Wallet Adapter. The user signs transactions in Phantom, which are submitted to the Anchor program.
- Reads use
getProgramAccountsRPC calls through the Anchor client. There is no backend server, database, or indexer. - BIO transfers use CPI
transfer_checkedto the SPL Token Interface, which validates the mint and decimal precision.
No off-chain infrastructure means no single point of failure, no database migrations, and no hosting costs.
On-chain program
The Anchor program lives in a single file (programs/nullgraph/src/lib.rs, ~593 lines). It uses Anchor 0.31.1 with anchor-spl for SPL Token Interface CPI and associated token accounts.
Program ID
2u3DXQq9A6UgMryeVSWCNdYLy3Fjh391R5hcfWYkCgZK.
Account architecture
NullGraph uses four main account types, all implemented as Program Derived Addresses:1. ProtocolState (Singleton)
Global configuration storing auto-incrementing counters, fee rate, and treasury address.| Field | Type | Description |
|---|---|---|
authority | Pubkey | Protocol admin wallet |
nka_counter | u64 | Auto-incrementing NKA counter |
bounty_counter | u64 | Auto-incrementing bounty counter |
fee_basis_points | u16 | Fee on settlement (250 = 2.5%) |
treasury | Pubkey | Treasury wallet for collected fees |
bump | u8 | PDA bump seed |
["protocol_state"]
The singleton pattern ensures a single source of truth for protocol configuration and prevents counter collision.
2. NullResult (One per NKA)
Stores all metadata for a Null Knowledge Asset.| Field | Type | Description |
|---|---|---|
researcher | Pubkey | Submitting wallet |
specimen_number | u64 | Sequential ID (NKA-0001, NKA-0002, …) |
hypothesis | [u8; 128] | Hypothesis tested (UTF-8, zero-padded) |
methodology | [u8; 128] | Methodology summary |
expected_outcome | [u8; 128] | What was expected |
actual_outcome | [u8; 128] | What actually happened |
p_value | u32 | Fixed-point (8700 = 0.8700) |
sample_size | u32 | Sample size n |
data_hash | [u8; 32] | SHA-256 of attached data file |
status | u8 | 0 = Pending, 1 = Verified, 2 = Disputed |
created_at | i64 | Unix timestamp |
bump | u8 | PDA bump seed |
["null_result", researcher_pubkey, specimen_number_le_bytes]
3. NullBounty (One per bounty)
Represents a bounty posted by a BioDAO or researcher.| Field | Type | Description |
|---|---|---|
creator | Pubkey | Bounty poster wallet |
bounty_number | u64 | Sequential ID (NB-0001, NB-0002, …) |
description | [u8; 256] | Description of null result needed |
reward_amount | u64 | BIO reward in base units (6 decimals) |
BIO_mint | Pubkey | Token mint address (BIO) |
vault | Pubkey | Vault token account PDA |
deadline | i64 | Deadline as Unix timestamp |
status | u8 | 0 = Open, 1 = Matched, 2 = Fulfilled, 3 = Closed |
matched_submission | Pubkey | BountySubmission PDA (zeroed if unmatched) |
created_at | i64 | Unix timestamp |
vault_bump | u8 | Vault PDA bump |
bump | u8 | PDA bump seed |
["null_bounty", creator_pubkey, bounty_number_le_bytes]Vault Seeds:
["bounty_vault", bounty_pda_key]
4. BountySubmission (Links an NKA to a bounty)
Created when a researcher submits their NKA to a bounty.| Field | Type | Description |
|---|---|---|
researcher | Pubkey | Claimant wallet |
null_result | Pubkey | NullResult PDA key |
bounty | Pubkey | NullBounty PDA key |
status | u8 | 0 = Pending, 1 = Approved, 2 = Rejected |
created_at | i64 | Unix timestamp |
bump | u8 | PDA bump seed |
["bounty_submission", bounty_pda_key, null_result_pda_key]
Instructions
The program exposes six instructions:initialize_protocol(fee_basis_points)
One-time setup. Creates the ProtocolState singleton with counters at zero and the given fee rate.
ProtocolInitialized { authority, fee_basis_points }
submit_null_result(...)
Mints a new NKA. Increments nka_counter, creates the NullResult PDA, and records all fields.
NullResultSubmitted { specimen_number, researcher }
create_bounty(description, reward_amount, deadline)
Creates a NullBounty PDA + vault, transfers BIO from the creator’s token account to the vault.
reward_amount > 0Emits:
BountyCreated { bounty_number, creator, reward_amount, deadline }
submit_to_bounty()
Links a researcher’s NKA to an open bounty. Creates a BountySubmission PDA and transitions the bounty to Matched.
has_one constraint)Emits:
BountySubmissionCreated { bounty_number, specimen_number, researcher }
approve_bounty_submission()
Bounty creator approves the submission. Transfers reward - fee BIO to the researcher and fee BIO to the treasury via vault CPI.
BountyFulfilled { bounty_number, specimen_number, researcher, payout, fee }
close_bounty()
Bounty creator reclaims escrowed BIO from any Open or Matched bounty. Vault balance returns to creator, bounty set to Closed.
BountyClosed { bounty_number, creator, refunded_amount }
Error codes
Frontend architecture
A React 19 SPA built with Vite 7.3 and Tailwind CSS v4. Connects directly to Solana devnet with no backend server.Provider stack
ProgramProvider exposes a single Anchor Program instance constructed from the compiled IDL:
Routes
| Route | Page | Description |
|---|---|---|
/ | Landing | Hero, problem/solution, how-it-works timeline |
/dashboard | Dashboard | Protocol stats and full NKA registry grid |
/submit | Submit | Four-step guided form |
/market | Market | Bounty card grid with create-bounty modal |
/market/:bountyId | BountyDetail | Single bounty view with submissions |
/nka/:specimenNumber | NullResultDetail | Full NKA metadata with Explorer links |
Data hooks
All data fetching uses custom React hooks that wrapprogram.account.<type>.all():
useProtocolState()- Fetches the singleton ProtocolStateuseNullResults()- Fetches all NullResult accountsuseBounties()- Fetches all NullBounty accountsuseBountySubmissions(filters)- Fetches BountySubmission accounts (filterable by bounty or researcher)
{ data, loading, error, refetch }.
No indexer required — the frontend fetches all accounts on page load. For production scale, consider using a Solana indexer like Helius or GenesysGo.
Transaction hooks
Transaction hooks derive PDAs, build instructions, send transactions, and show toast notifications:useSubmitNullResult()- Mints a new NKAuseCreateBounty()- Creates a bounty with escrowed BIOuseSubmitToBounty()- Links an NKA to a bountyuseApproveBountySubmission()- Approves a submission and pays outuseCloseBounty()- Closes a bounty and refunds escrow
useSubmitNullResult:
Design system
Dark-mode cyberpunk aesthetic defined as Tailwind v4@theme tokens:
- Background:
#060810with a 40px CSS grid overlay - Surfaces:
#0d1017(surface),#161c2a(raised),#232840borders - Accents: Neon cyan (
#5ec4de), magenta (#c8836a), lime (#62b862) - Typography: Cabinet Grotesk (display), Satoshi (body), Space Grotesk (mono/data)
- Effects: CRT scanline animation, SVG noise overlay, glass card hover lifts with colored glow shadows
Security model
On-chain security
- Signer checks on every write instruction via Anchor struct-level enforcement
- PDA ownership — all data accounts are program-owned PDAs
has_oneconstraints ensure only the correct wallets can perform actions- Status guards validate current status before every state mutation
- Replay protection — PDA
initconstraints prevent duplicate accounts - Vault authority — vault token accounts use the vault PDA itself as authority
- Safe arithmetic — all fee/payout math uses
checked_mul,checked_div,checked_sub - Transfer validation — all BIO transfers use
transfer_checked, validating mint and decimal precision
Frontend security
- No private keys handled. All signing delegated to Phantom.
- Client-side file hashing via Web Crypto API (
crypto.subtle.digest). - Input bounds match on-chain field sizes (128/256 chars via
maxLength).
Tech stack summary
On-chain
| Technology | Version | Purpose |
|---|---|---|
| Solana | Devnet | Settlement layer |
| Anchor | 0.31.1 | Program framework |
| anchor-spl | 0.31.1 | SPL Token Interface CPI |
| Rust | 2021 edition | Program language |
Frontend
| Technology | Version | Purpose |
|---|---|---|
| React | 19.2 | UI framework |
| TypeScript | 5.9 | Type safety |
| Vite | 7.3 | Build tool + dev server |
| Tailwind CSS | 4.2 | Utility-first styling |
| React Router | 7.13 | Client-side routing |
| Lucide React | 0.575 | Icons |
Solana client libraries
| Library | Purpose |
|---|---|
@coral-xyz/anchor (0.32.1) | Anchor client for IDL-based program interaction |
@solana/web3.js | JSON-RPC client and transaction building |
@solana/wallet-adapter-react | React hooks for wallet connection |
@solana/wallet-adapter-react-ui | Wallet connection modal and button |
@solana/wallet-adapter-wallets | Phantom wallet adapter |
@solana/spl-token | SPL Token client utilities |
What’s next?
Now that you understand the architecture, explore:- Program reference - Complete on-chain program documentation
- Frontend integration - Build a frontend for NullGraph
- Security best practices - Anchor security patterns used in NullGraph