| Crates.io | uncpi |
| lib.rs | uncpi |
| version | 0.4.0 |
| created_at | 2025-12-21 00:39:42.817719+00 |
| updated_at | 2025-12-23 12:39:03.234177+00 |
| description | Transpile Anchor programs to Pinocchio for 85%+ size reduction |
| homepage | https://github.com/openSVM/uncpi |
| repository | https://github.com/openSVM/uncpi |
| max_upload_size | |
| id | 1997158 |
| size | 376,804 |
"ok unc, optimize my anchor uwu" (c) clanker
Production-ready Anchor → Pinocchio transpiler for 85%+ binary size reduction.
✅ Validated against official Solana programs (4,557+ stars) ✅ Tested with patterns from Raydium, Jupiter, Marinade ✅ 80% success rate on real-world programs
| Metric | Anchor | Pinocchio | Savings |
|---|---|---|---|
| Binary Size | ~600-900 KB | ~50-100 KB | 85-90% |
| Deploy Cost | ~10 SOL | ~1 SOL | $1,100+ |
| Compute Units | ~300-600 CU | ~100-150 CU | 60-75% |
cargo install uncpi
git clone https://github.com/openSVM/uncpi.git
cd uncpi
cargo install --path .
Download pre-built binaries for Linux, macOS, and Windows from the releases page.
# Convert a program
uncpi programs/my_program/src/lib.rs -o programs/my_program_pino/
# With options
uncpi programs/my_program/src/lib.rs \
--no-alloc \ # Use no_allocator! for max savings
--inline-cpi \ # Inline CPI calls
--lazy-entrypoint \ # Use lazy_program_entrypoint!
-o output/
┌─────────────────────────────────────────────────────────────────┐
│ uncpi Pipeline │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Parse │───▶│ Analyze │───▶│Transform │───▶│ Emit │ │
│ │ Anchor │ │ AST │ │ IR │ │Pinocchio │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ lib.rs Account Graph Pinocchio IR lib.rs │
│ (Anchor) + Constraints + Validation (Pinocchio) │
│ │
└─────────────────────────────────────────────────────────────────┘
Anchor:
#[program]
pub mod my_program {
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
// ...
}
}
Pinocchio:
use pinocchio::{lazy_program_entrypoint, program_error::ProgramError};
lazy_program_entrypoint!(process_instruction);
fn process_instruction(
program_id: &[u8; 32],
accounts: &[[u8; 32]],
instruction_data: &[u8],
) -> Result<(), ProgramError> {
let discriminator = instruction_data[0];
match discriminator {
0 => initialize(accounts, &instruction_data[1..]),
_ => Err(ProgramError::InvalidInstructionData),
}
}
Anchor:
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(
init,
payer = authority,
space = 8 + State::INIT_SPACE,
seeds = [b"state"],
bump
)]
pub state: Account<'info, State>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}
Pinocchio:
fn initialize(accounts: &[AccountInfo], _data: &[u8]) -> Result<(), ProgramError> {
let state_info = &accounts[0];
let authority_info = &accounts[1];
let system_program = &accounts[2];
// Signer check
if !authority_info.is_signer() {
return Err(ProgramError::MissingRequiredSignature);
}
// PDA validation
let (expected_pda, bump) = Pubkey::find_program_address(&[b"state"], program_id);
if state_info.key() != &expected_pda {
return Err(ProgramError::InvalidSeeds);
}
// Create account via CPI
create_account(
authority_info,
state_info,
8 + State::SIZE,
program_id,
system_program,
&[b"state", &[bump]],
)?;
Ok(())
}
Anchor:
#[account]
#[derive(InitSpace)]
pub struct State {
pub authority: Pubkey,
pub total: u64,
pub bump: u8,
}
Pinocchio:
#[repr(C)]
pub struct State {
pub authority: [u8; 32],
pub total: u64,
pub bump: u8,
}
impl State {
pub const SIZE: usize = 32 + 8 + 1;
pub fn from_account_info(info: &AccountInfo) -> Result<&Self, ProgramError> {
let data = info.try_borrow_data()?;
if data.len() < 8 + Self::SIZE {
return Err(ProgramError::InvalidAccountData);
}
Ok(unsafe { &*(data[8..].as_ptr() as *const Self) })
}
}
| Anchor Constraint | Pinocchio Equivalent |
|---|---|
#[account(mut)] |
info.is_writable() check |
#[account(signer)] |
info.is_signer() check |
#[account(seeds = [...], bump)] |
Pubkey::find_program_address() |
#[account(constraint = expr @ Error)] |
Manual if !expr { return Err(...) } |
#[account(init, payer, space)] |
create_account() CPI |
#[account(token::mint, token::authority)] |
Token program CPI + validation |
#[account(close = target)] |
Transfer lamports + zero data |
Anchor:
let cpi_accounts = Transfer {
from: ctx.accounts.from.to_account_info(),
to: ctx.accounts.to.to_account_info(),
authority: ctx.accounts.authority.to_account_info(),
};
token::transfer(CpiContext::new(token_program, cpi_accounts), amount)?;
Pinocchio:
use pinocchio_token::instructions::Transfer;
Transfer {
from: from_info,
to: to_info,
authority: authority_info,
amount,
}.invoke()?;
remaining_accounts patterns need manual handlingMIT
✅ Official Solana Foundation (4,557+ stars)
✅ Top DeFi Protocols
✅ NFT & Gaming
| Pattern | Success Rate |
|---|---|
| DeFi (AMM, Staking, Vaults) | 100% ✅ |
| NFT (Marketplaces) | 100% ✅ |
| Governance (Voting) | 100% ✅ |
| Gaming (Lottery) | 100% ✅ |
| Overall | 80% (8/10 programs) |
See: PRODUCTION-VALIDATION.md for detailed validation report
✅ Escrow (token swaps, PDAs, signed invocations)
✅ AMM (liquidity pools, mathematical operations)
✅ Staking (reward calculations, time-based logic)
✅ NFT Marketplace (buy/sell/cancel)
✅ Voting (governance, String fields)
✅ Lottery (self-referential PDAs, Option types)
✅ Token Vaults (deposit/withdraw)
Real-world programs built with uncpi:
Pinray AMM - Constant product AMM (x * y = k)
Pinray CLMM - Simplified Concentrated Liquidity