Rust para Programas Solana
Código Solana on-chain é Rust, mas não é Rust de laptop com um main diferente. Você compila para sBPF, roda dentro do SVM e só toca estado da chain através de contas e syscalls.
Busque em todas as páginas da documentação
Código Solana on-chain é Rust, mas não é Rust de laptop com um main diferente. Você compila para sBPF, roda dentro do SVM e só toca estado da chain através de contas e syscalls.
Esse subconjunto - no_std, alocação restrita, entrypoint fixo, layouts Borsh (ou zero-copy), matemática checked, erros tipados e orçamentos de compute/tamanho - é a linguagem de todo programa nativo, Anchor e leve no Agave 4.1.1.
no_std: um entrypoint, dados de instrução e conta em nível de byte (geralmente Borsh), aritmética segura, erros fail-fast e limites rígidos de compute units e tamanho de binário.unwrap, crescimento ilimitado de Vec, deps std, overflow silencioso, logging pesado) ou falham ao compilar para cargo build-sbf ou passam nos testes e quebram sob CU, rent e pressão de auditoria na mainnet-beta.O source de programa Solana é Rust 1.91.1 (pin deste site), mas o target não é um triple de host.
cargo build-sbf (via ferramentas de plataforma Agave / build Anchor) cross-compila para sBPF (Solana Bytecode Format). Validadores carregam o .so e o SVM executa sob locks Sealevel e metering de compute.
Não há main de processo. O loader invoca um único entrypoint que o crate registra (nativo entrypoint!, ou dispatcher gerado pelo Anchor). Essa função recebe program_id, um slice de AccountInfo e bytes de instruction_data. Variantes de instrução, layouts de conta, PDAs e CPIs constroem sobre esse trio.
O ambiente é no_std: sem filesystem, sockets, threads ou biblioteca padrão completa. alloc opcional dá Vec / String / Box, mas uso de heap custa compute. Código de produção prefere contas de tamanho fixo, parsing amigável à stack e evitar format! em caminhos quentes.
Estado durável não vive no binário do programa. Registros do app ficam em contas que o programa possui (ou que outros programas possuem, mutados só via CPI). Structs Rust on-chain são schemas sobre bytes de conta.
Borsh é a codificação de fato para instruções e a maioria dos structs de conta (padrão Anchor 0.32.1). Layouts fixos grandes costumam usar zero-copy bytemuck. Dinheiro e contadores usam u64 (ou inteiros fixos mais largos) com ops checked. Falhas retornam ProgramError (ou códigos custom mapeados); prefira ? a unwrap. Execução é medida em compute units, e tamanho de binário afeta custo de deploy. "Compila" não é "cabe nos orçamentos de CU e tamanho."
Crates nativos dependem de solana-program (ou Pinocchio). Projetos Anchor usam anchor-lang = "0.32.1" para geração de entrypoint e validação de contas.
Fluxo de build: compilar para ELF sBPF com ferramentas de plataforma, fazer deploy com Solana CLI 3.0.10 / Anchor, armazenar bytecode em ProgramData sob o loader upgradeable; em cada instrução o SVM mapeia contas, chama o entrypoint, mede CU e commita ou faz rollback.
Testes unitários de host (#[cfg(test)]) rodam na workstation; testes de integração usam LiteSVM 0.6.x, Surfpool 0.12.0 ou validador local.
Estilo nativo:
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
pubkey::Pubkey,
};
entrypoint!(process_instruction);
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
// decodifica instruction_data, valida contas, muta estado owned
Ok(())
}Dentro do handler você geralmente:
next_account_info ou checagens de índiceOk(()) ou Err(...)Anchor envolve isso em módulos #[program] e discriminators de 8 bytes. O modelo de runtime não muda: um entrypoint, contas declaradas, dados em byte.
On-chain você tem core, crates no_std selecionados, syscalls solana_program (log, CPI, sysvars), alloc opcional e serializadores como Borsh / bytemuck que compilam para sBPF.
Você não tem std completo, runtimes async, clientes HTTP ou acesso a filesystem. Se cargo build-sbf falha numa dependência, audite cargo tree por std transitivo e troque por crates seguros para programa.
Dados de instrução e corpos de conta são bytes. Borsh é determinístico e little-endian: inteiros fixos, bool de 1 byte, Pubkey de 32 bytes, Vec/String com prefixo u32, e discriminants de enum.
Dimensione contas na criação para que serialize não escreva além de account.data.len(). Mudanças de schema precisam de versionamento ou migrações; reordenar variantes de enum muda tags silenciosamente. Zero-copy (Pod + Zeroable + #[repr(C)]) reinterpreta contas fixas grandes sem cópia completa quando CU importa.
Quantidades de token, taxas em basis points, matemática de shares e índices de reward devem usar:
let next = balance
.checked_add(amount)
.ok_or(ProgramError::InvalidArgument)?;Prefira checked_* quando overflow é erro, saturating_* quando um cap é intencional, e checagens explícitas de limites para regras de negócio (max supply, max bps). Não confie em panics de overflow só em debug; trate wraparound como falha de design.
ProgramResult é Result<(), ProgramError>. Mapeie falhas de domínio para códigos custom (impls From nativos, #[error_code] Anchor ou similar) para que clientes TypeScript com @solana/kit 7.0.0 possam ramificar em números de erro em vez de só raspar logs.
Use msg! com moderação para diagnóstico. Logs custam CU e não substituem erros estruturados em caminhos de falha esperados (não autorizado, slippage, expirado).
CU vem de um orçamento no nível da transação (na Solana moderna incluindo Agave 4.1.1, planeje em torno de um default perto de 1.400.000 CU a menos que instruções Compute Budget mudem o limite dentro dos caps do protocolo).
Sumidouros comuns de CU:
msg! verboso em loops apertadosSumidouros de tamanho de binário:
Disciplina significa early returns, iteração limitada, deps enxutas e profiling com simulação antes de tráfego mainnet-beta.
| Abordagem | Experiência Rust | CU / tamanho | Quando encaixa |
|---|---|---|---|
| Anchor 0.32.1 | Macros, contas, IDL | Baseline maior | Velocidade de produto, clientes tipados |
solana-program nativo | Entrypoint e checagens explícitas | Teto menor se cuidadoso | Aprendizado, loaders custom de controle |
| Pinocchio / pilhas finas | Orientado a sistemas | Geralmente mais enxuto | Caminhos quentes, programas de infraestrutura |
| Híbrido | Camada app Anchor + core fino | Split por CPI | Sistemas maduros com hotspots medidos |
Os três ainda obedecem restrições no_std, layouts Borsh-ou-bytes, matemática checked e metering de CU. Escolha de framework muda macros e ergonomia de validação, não as regras do SVM.
| Hábito Rust de host | Substituto on-chain |
|---|---|
main + args CLI | Entrypoint + bytes de instrução + lista de contas |
| Arquivos / linhas de DB | Contas owned pelo programa com layouts fixos ou versionados |
anyhow + stack traces | Códigos compactos ProgramError + logs seletivos |
Crescimento ilimitado de Vec | Capacidade fixa, storage em conta, contagens máximas |
| Threads / async | Instrução single-thread; paralelização é Sealevel entre txs |
println! | msg! (medido) |
| Dinheiro em ponto flutuante | Lamports inteiros / unidades base de token + ops checked |
Use headers de conta versionados, discriminators (tags manuais ou de 8 bytes do Anchor), seeds PDA como parte da API, e helpers CPI que ainda exigem contas declaradas. Mantenha testes só de host atrás de cfg para não inchar o binário sBPF.
Teste unitariamente matemática pura e packing no host. Rode instruções completas sob LiteSVM 0.6.x ou Surfpool 0.12.0. Meça tamanho de binário após build e computeUnitsConsumed da simulação (meta RPC Kit basta para checagens no lado do cliente).
no_std com alloc opcional; a maioria de std e pilhas async não compila para sBPF.unwrap é ok se clientes são honestos." Clientes são adversariais; panics desperdiçam CU e produzem UX de cliente pior que erros tipados.msg! pode empurrar caminhos além do orçamento de CU; prefira erros e indexação off-chain para eventos de alto volume.repr(C)/Pod; campos de comprimento variável costumam favorecer Borsh.Bytecode sBPF (ELF .so) executado pelo SVM em validadores Agave. Você builda com cargo build-sbf ou build do Anchor, não só um target de host normal.
O loader BPF/SBF chama o entrypoint registrado para cada instrução. Frameworks geram ou envolvem esse entrypoint para você.
no_std remove a biblioteca padrão. alloc restaura opcionalmente tipos de heap (Vec, String) via allocator do programa, ainda sem I/O de SO ou threads. Prefira layouts fixos quando possível.
Sim. Anchor 0.32.1 emite Rust que aponta para o mesmo runtime. Macros reduzem boilerplate para contas, erros e IDL; não mudam regras Sealevel.
É determinístico, compacto e compartilhado entre programas nativos, padrões Anchor e muitos coders de cliente. Estabilidade cross-language importa mais que usar qualquer formato serde que você gosta no host.
Quando contas são grandes, de tamanho fixo e quentes o bastante para deserialize/serialize completo dominar CU. Mantenha regras de alinhamento e padding sob revisão.
Sim. Adição, multiplicação para taxas e matemática de shares ainda podem estourar u64. Ops checked transformam isso em falha limpa de instrução.
Mapeie códigos de erro custom no programa e decodifique off-chain (tabelas IDL/erro com Anchor, ou códigos documentados para nativo). Use meta de transação @solana/kit 7.0.0 para logs e campos err.
Remova logs em caminho quente, limite loops, evite clonar buffers grandes, deserialize só campos necessários e simule com tamanhos de conta realistas.
Deve compilar sob cargo build-sbf, de preferência como no_std. Cheque deps transitivas por features só std e prefira crates mantidos para programas Solana.
Prefira fixed-point inteiro para saldos, taxas e shares. Evite floats para qualquer coisa financeira.
Páginas Sealevel cobrem locks, paralelismo e metering. Esta seção cobre o subconjunto Rust que você escreve dentro desse runtime.
Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, LiteSVM 0.6.x.
Este overview, depois Rust for Solana Basics, depois páginas no_std, Borsh, aritmética, erros e CU conforme você constrói.
Ele afina deps e estilo de entrypoint. Você ainda raciocina sobre contas, bytes, erros e CU da mesma forma.
?Versões da stack: Esta página foi escrita para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0 e LiteSVM 0.6.x.
Revisado por Chris St. John·Última atualização: 15 de jul. de 2026