Compute unit and rent cost optimization analysis for Solana programs
curl -s https://parity.cx/api/skills/gas-optimization | shcopyYou are analyzing a Solana smart contract for compute unit efficiency and rent cost optimization. Solana charges per compute unit consumed and per byte of on-chain storage. This skill identifies wasteful patterns that increase transaction costs, reduce throughput, or cause unnecessary rent burden.
Solana programs have a default compute budget of 200,000 compute units per instruction. Programs can request up to 1,400,000 CUs via ComputeBudgetInstruction::set_compute_unit_limit, but higher CU consumption means higher priority fees and reduced inclusion probability during congestion. Anchor adds overhead for account deserialization and constraint validation. Minimizing CU usage per instruction directly reduces user costs and improves scalability.
Rent is charged at ~6.96 SOL per MB per year (rent-exempt threshold). Every byte of on-chain account data has a permanent cost. Over-allocating account space wastes rent deposits.
Before starting analysis, fetch the following from the Parity repository:
| Source | Path | Contains |
|--------|------|----------|
| Framework Patterns | programs/parity/src/context_engine.rs > ANCHOR_PATTERNS | Correct Anchor patterns including data layout, CPI invocation, and account initialization examples |
| Skill Definition | programs/parity/src/skills.rs > BUILTIN_SKILLS (gas-optimization entry) | Canonical step list and output spec |
GitHub base URL: https://github.com/paritydotcx/Skills/blob/main/
Use ANCHOR_PATTERNS to compare the target program's account structures and CPI calls against known efficient implementations.
Analyze all #[account] struct definitions for data packing efficiency.
What to look for:
String where fixed [u8; N] would suffice (String stores length prefix + heap data, more expensive to serialize/deserialize)Vec<T> fields where a fixed array [T; N] could work (Vec requires length prefix and dynamic allocation)Option<Pubkey> (33 bytes: 1 discriminator + 32 key) where a zero-key sentinel could save spaceWasteful pattern:
#[account]
pub struct UserProfile {
pub name: String, // 4 + N bytes, variable
pub bio: String, // 4 + N bytes, variable
pub avatar_url: String, // 4 + N bytes, variable
pub authority: Pubkey, // 32
pub created_at: i64, // 8
}Optimized pattern:
#[account]
pub struct UserProfile {
pub authority: Pubkey, // 32
pub created_at: i64, // 8
pub name: [u8; 32], // 32, fixed
pub bio: [u8; 128], // 128, fixed
pub avatar_hash: [u8; 32], // 32, store hash, not full URL
}Finding if applicable:
Check for unnecessary realloc operations or patterns that create accounts and immediately resize them.
What to look for:
realloc constraints on accounts that could have been initialized with the correct sizeFinding if applicable:
Identify accounts that are deserialized unnecessarily.
What to look for:
Account<'info, T> (full deserialization) where AccountLoader<'info, T> (zero-copy) would be appropriate for accounts over 1KBOptimized pattern:
// For large accounts (>1KB), use zero-copy to avoid full deserialization
#[account(zero_copy)]
#[repr(C)]
pub struct LargeState {
pub data: [u64; 128], // 1KB, accessed field-by-field without full deser
}
// In accounts struct:
pub large_state: AccountLoader<'info, LargeState>,Finding if applicable:
Estimate the compute unit consumption of each instruction handler.
Base costs to reference:
find_program_address): ~1,500 CU per derivationmsg! logging: ~100 CU per callFor each instruction, sum the estimated costs and compare against the compute_budget input parameter (default 200,000). Flag instructions that exceed 70% of budget.
Finding if applicable:
Evaluate cross-program invocations for batching opportunities.
What to look for:
Finding if applicable:
Calculate total rent cost for all account types and identify savings opportunities.
Calculation:
For each #[account] type, compute:
Finding if applicable:
Return results as structured JSON:
{
"estimated_compute_units": {
"initialize": 45000,
"deposit": 72000,
"withdraw": 95000,
"close": 38000
},
"findings": [
{
"severity": "medium",
"title": "Variable-length String field in UserProfile",
"location": {
"file": "lib.rs",
"line": 12,
"instruction": null
},
"description": "UserProfile.name uses String type. Maximum name length is 32 characters. Using [u8; 32] saves ~4 bytes per account and eliminates length-prefix deserialization.",
"recommendation": "Replace `pub name: String` with `pub name: [u8; 32]` and update serialization logic."
}
],
"summary": "Total estimated rent across all account types: 0.0089 SOL. 2 optimization opportunities identified saving ~12,000 CU on the deposit instruction."
}