This guide explains how to analyze Solana programs, understand their structure, and extract useful information.
Solana programs are compiled to eBPF (extended Berkeley Packet Filter) bytecode, stored in ELF format. They run on the Solana Virtual Machine (SVM).
| Concept | Description |
|---|---|
| Program | Executable code deployed on-chain |
| Account | Data storage on Solana (programs are stateless) |
| Instruction | Entry point into program logic |
| CPI | Cross-Program Invocation - calling other programs |
| PDA | Program Derived Address - deterministic account addresses |
solana program dump <PROGRAM_ID> program.so --url mainnet-betaThis downloads the raw BPF bytecode from the chain.
# File type and architecture
file program.so
# Output: ELF 64-bit LSB shared object, eBPF, version 1 (SYSV), dynamically linked, stripped
# File size
ls -lh program.so
# Extract readable strings
strings program.so > strings.txt
# Look for instruction names
strings program.so | grep "Instruction:"Anchor programs store their IDL (Interface Definition Language) on-chain:
anchor idl fetch <PROGRAM_ID> --provider.cluster mainnetThe IDL contains:
- Instruction definitions
- Account structures
- Error codes
- Type definitions
Use LLVM tools to disassemble eBPF:
llvm-objdump -d program.so > disassembly.asmFrom strings, you can often find:
- Source file paths (reveals module structure)
- Error messages
- Account/instruction names
- Integrated protocols
Look for:
anchor:idlin strings- IDL fetch succeeds
AnchorErrorin error messages- Standard discriminator pattern (8-byte instruction prefix)
Look for:
- No IDL available
- Custom serialization patterns
- Direct
entrypoint!macro usage
| Register | Purpose |
|---|---|
r0 |
Return value |
r1-r5 |
Function arguments |
r6-r9 |
Callee-saved |
r10 |
Frame pointer (read-only) |
Function Call:
call <offset>Memory Access:
r2 = *(u64 *)(r1 + 0x8) # Load 64-bit value
*(u64 *)(r1 + 0x0) = r2 # Store 64-bit valueConditional Branch:
if r1 == 0x0 goto +0x10 # Jump if equal
if r1 s> 0x5 goto +0x1d # Jump if signed greater# Error messages
strings program.so | grep -iE "error|failed|invalid"
# Source paths (reveals structure)
strings program.so | grep "src/"
# Integrated protocols
strings program.so | grep -iE "raydium|jupiter|orca|meteora"# List instructions
jq '.instructions[].name' idl.json
# List accounts
jq '.accounts[].name' idl.json
# List errors
jq '.errors[] | "\(.code): \(.name)"' idl.json
# Get instruction details
jq '.instructions[] | select(.name == "swap")' idl.json- Access Control: Check for signer verification
- Account Validation: PDA derivation, owner checks
- Arithmetic: Overflow protection (checked_add, etc.)
- Reentrancy: CPI patterns
- Error Handling: Proper error propagation
# Unchecked operations
strings program.so | grep -i "unchecked"
# Unsafe patterns
strings program.so | grep -i "unsafe"
# Panic locations
strings program.so | grep "panic"When analyzing DEX aggregators or DeFi programs, look for integrations:
| Protocol | Identifier |
|---|---|
| Raydium AMM | 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 |
| Raydium CLMM | CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK |
| Orca Whirlpools | whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc |
| Meteora DLMM | LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo |
| Phoenix | PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY |
| Tool | Installation | Purpose |
|---|---|---|
solana |
brew install solana |
CLI for Solana operations |
anchor |
cargo install anchor-cli |
Anchor framework tools |
llvm-objdump |
brew install llvm |
Disassembler |
jq |
brew install jq |
JSON processing |
strings |
Built-in | Extract printable strings |