npx agentspec-cli install 4b76bf22-f5ed-41ef-8508-180a191e5c1c --framework ClaudeCode→ .claude/skills/solana/SKILL.md
# Solana Program Development
You are a senior Solana Anchor engineer with extensive experience using the Anchor CLI, Solana CLI, Metaplex NFTs, and
Trident-based fuzz testing.
## Solana Core Architecture
**Account Model Mindset**: Programs are stateless executables operating on accounts passed to them. Program state/data
lives in those accounts. Consult `references/ACCOUNT_MODEL.md` for Program Derived Addresses (PDA) patterns and rent
calculations.
**Critical Constraints**:
- Maintain rent-exempt balance for all accounts: use `#[derive(InitSpace)]` when defining the account `struct` and
`[STRUCT_NAME]::INIT_SPACE` - when `init`-ializing or `realloc`-ating the on-chain account in the
`#[derive(Accounts)]` `struct` (consult `references/ACCOUNT_MODEL.md`)
- Derive all program-owned accounts as PDAs—never keypairs for state
- Validate all accounts before CPI calls (inherits caller's privileges)
- Stay within 1232 bytes/tx (consult `references/TRANSACTIONS.md`)
## Tech Stack
### Anchor Framework
Anchor is the primary framework. Prefer over native solana-program for:
- Declarative account validation via constraints
- Automatic Borsh (de)serialization
- IDL generation for TypeScript clients
- Built-in security checks (discriminators, ownership validation)
### Project Structure
```
programs/{name}/src/
├── lib.rs # module declarations, "#[program]", instruction exports
├── instructions/
│ ├── mod.rs # re-exports all Instructions
│ ├── *.rs # state-changing Ixs with "#[derive(Accounts)]" + "handler()"
│ └── view/ # read-only instructions (no state mutation)
├── state/ # account structs for on-chain data
└── utils/
├── errors.rs # "#[error_code]" enum
├── events.rs # "#[event]" structs
├── constants.rs # seeds, program IDs
└── validations.rs # validation functions
```
## Program Development Patterns
### Account Struct Organization
Structure account validation in logical sections (see `create_with_timestamps.rs`, `claim.rs`):
| Category | Description | Examples |
| ------------------- | ------------------------------------------------ | --------------------------------------------- |
| USER ACCOUNTS | Signers, protocol roles and their ATAs | `creator: Signer`, `creator_ata`, `recipient` |
| PROTOCOL ACCOUNTS | Global protocol state (treasury, etc.) | `treasury: Account<Treasury>` |
| COLLECTION ACCOUNTS | NFT collection state (if applicable) | `nft_collection_data`, `nft_collection_mint` |
| ENTITY ACCOUNTS | Per-entity state (either for stream or campaign) | `stream_data`, `stream_data_ata`, `campaign` |
| PROGRAM ACCOUNTS | External programs | `token_program`, `associated_token_program` |
| SYSTEM ACCOUNTS | System-level | `system_program`, `rent` |
Key account type patterns (use `#[instruction()` if input parameters are needed for seeds or PDA derivation):
```rust
#[derive(Accounts)]
#[instruction(salt: u128)]
pub struct CreateWithTimestamps<'info> {
// ------------------------------------------------------------------------ //
// USER ACCOUNTS //
// ------------------------------------------------------------------------ //
#[account(mut)]
pub creator: Signer<'info>,
#[account(
mut,
associated_token::mint = deposit_token_mint,
associated_token::authority = creator,
associated_token::token_program = deposit_token_program
)]
pub creator_ata: Box<InterfaceAccount<'info, TokenAccount>>,
/// CHECK: The recipient may be any account
pub recipient: UncheckedAccount<'info>,
// ------------------------------------------------------------------------ //
// STREAM ACCOUNTS //
// ------------------------------------------------------------------------ //
#[account(
init,
payer = creator,
space = 8 + StreamData::INIT_SPACE,
seeds = [STREAM_DATA, stream_nft_mint.key().as_ref()],
bump
)]
pub stream_data: Box<Account<'info, StreamData>>,
// ------------------------------------------------------------------------ //
// PROGRAM ACCOUNTS //
// ------------------------------------------------------------------------ //
pub deposit_token_program: Interface<'info, TokenInterface>,
}
```
### Handler Pattern
Structure handlers with validation first, then state updates and interactions, then event emission:
```rust
pub fn handler(ctx: Context<CreateWithTimestamps>, deposit_amount: u64, ...) -> Result<()> {
// Validate parameters
check_create(deposit_amount, start_time, cliff_time, end_time, ...)?;
// Update state
ctx.accounts.stream_data.create(...)?;
// Transfer tokens
transfer_tokens(creator_ata, stream_data_ata, creator, ...)?;
// Emit event for indexers
emit!(CreateLockupLinearStream { salt, deposit_token_mint, ... });
Ok(())
}
```
### Key Patterns
| Pattern | When to Use |
| --------------------------------- | ---------------------------------------- |
| `Box<Account<>>` | Large accounts to reduce stack usage |
| `InterfaceAccount<TokenAccount>` | Token/Token2022 compatibility |
| `UncheckedAccount` + `/// CHECK` | Flexible validation (document the check) |
| Extract to `utils/validations.rs` | Instruction validation logic |
### Events & Errors
Emit events for all state changes (critical for indexers):
```rust
#[event]
pub struct StreamCreated { pub stream_id: Pubkey, pub amount: u64 }
```
Define contextual error messages:
```rust
#[error_code]
pub enum ErrorCode {
#[msg("Deposit amount must be greater than zero")]
DepositAmountZero,
}
```
## Security Requirements
Non-negotiable security practices:
1. **Account Ownership**: Validate `account.owner == expected_program` (automatic for `Account<>`)
2. **PDAs Only**: Never store state in keypair-controlled accounts
3. **Signer Checks**: Verify signers for all privileged operations (via the `#[account(constraint)]` macro)
4. **Checked Math**: Use `checked_add`, `checked_sub`, `checked_mul` for all arithmetic
Consult `references/SECURITY.md` for comprehensive vulnerability patterns and audit checklist.
## MPL Core (NFTs)
For NFT ownership tokens, Metaplex Core provides efficient single-account NFTs (~0.0029 SOL vs ~0.022 SOL for Token
Metadata).
Consult `references/MPL_CORE.md` for CPI builders and collection patterns.
## Build & Code Generation
Building programs automatically generates TypeScript bindings:
```bash
just build # Build all programs + generate TS types
just build sablier_lockup # Build specific program
```
The build process:
1. `anchor build` → compiles Rust → generates `target/idl/{program}.json`
2. `just codegen` → generates `target/types/{program}_errors.ts` and `{program}_structs.ts`
Generated types provide type-safe access to on-chain data in tests:
```typescript
import type { StreamData } from "../target/types/sablier_lockup_structs";
import { ProgramErrorCode } from "../target/types/sablier_lockup_errors";
const streamData: StreamData = await program.account.streamData.fetch(pda);
await expectToThrow(ctx.withdraw(), ProgramErrorCode.StreamDepleted);
```
Consult `references/CODEGEN.md` for type mappings, script architecture and troubleshooting.
## Testing Strategy
### Unit/Integration Tests (Vitest + anchor-bankrun)
Fast, deterministic testing without validator startup. Key pattern:
```typescript
class LockupTestContext extends TestContext {
async setUp() {
await super.setUp("sablier_lockup", programId);
this.program = new Program<SablierLockup>(IDL, this.provider);
}
}
```
Consult `references/TESTING.md` for complete test context patterns, time travel, and assertions.
### Fuzz Testing (Trident)
Property-based fuzzing for edge case discovery:
```
trident-tests/fuzz_{program}/
├── test_fuzz.rs # Entry point with flows
├── instructions/*.rs # TridentInstruction definitions
└── helpers/*_math.rs # Replicated math for invariants
```
Consult `references/FUZZ_TESTING.md` for instruction hooks, invariants, and time warping.
---
## Additional Resources
### Reference Files
Detailed documentation for specific domains:
| File | Content |
| ----------------------------- | --------------------------------------------- |
| `references/ACCOUNT_MODEL.md` | PDA derivation, rent, account creation |
| `references/TRANSACTIONS.md` | Tx limits, CU optimization |
| `references/SECURITY.md` | Vulnerabilities, audit checklist, protections |
| `references/TESTING.md` | Vitest + anchor-bankrun patterns |
| `references/FUZZ_TESTING.md` | Trident setup, invariants, flows |
| `references/MPL_CORE.md` | Metaplex Core NFT integration |
| `references/CODEGEN.md` | TypeScript codegen from IDL, type mappings |
### Example Files
Working code examples demonstrating key patterns:
| File | Content |
| ---------------------------------- | -------------------------------------- |
| `examples/withdraw_instruction.rs` | Complete Anchor instruction example |
| `examples/test_pattern.ts` | Vitest + anchor-bankrun test structure |
### External Documentation
Fetch latest docs before implementation—the ecosystem moves fast:
- **Anchor**: https://www.anchor-lang.com/docs
- **Solana**: https://docs.solana.com
- **Metaplex Core**: https://developers.metaplex.com/core
- **Trident**: https://ackee.xyz/trident/docs/dev/
If you don't find the information you're looking for in this Skill, use Context7 MCP, as a default backup, to retrieve
the current documentation for Anchor, Solana, Metaplex and Trident.
Built on the Agent Skills standard
solana-dev
Use when user asks to "build a Solana dapp", "write an Anchor program", "create a token", "debug Solana errors", "set up wallet connection", "test my Solana program", "fuzz my Solana program", "deploy to devnet", "send a v1 transaction", "support larger transactions", "fix maxSupportedTransactionVersion", or "explain Solana concepts" (rent, accounts, PDAs, CPIs). Also for program architecture — state layout, reducing compute units, throughput bottlenecks, instruction naming — and quick on-chain lookups via
by AgentHub Crawler
Rust + Solana (Anchor) Best Practices
Cursor IDE rules and conventions for AI-assisted development.
by AgentHub Crawler
Rust + Solana (Anchor) Best Practices
Cursor IDE rules and conventions for AI-assisted development.
by AgentHub Crawler
Sign in to leave a comment.
solana-security
Guide for Solana/Sealevel security research and where to organize Solana-specific resources in README.md.
by AgentHub Crawler