Anchor em Detalhes
Anchor é o framework dominante para escrever programas Solana em Rust. Ele se baseia no mesmo runtime Agave que os programas nativos (bytecode SBF, metadados de conta explícitos, unidades de computação, CPI), mas gera a cola que você escreveria manualmente: discriminadores de instrução, dispatch de ponto de entrada, verificações declarativas de conta, erros tipados, eventos e um IDL que os clientes consomem.
Esta página é o guarda-chuva para anchor-basics: o que é Anchor, como o módulo #[program] e as structs #[derive(Accounts)] formam a superfície de instrução, como um workspace é organizado, como a compilação/implantação e os testes locais se encaixam, e como Anchor se compara aos programas nativos.
Resumo
- Anchor 0.32.1 transforma o desenvolvimento de programas Solana em um fluxo de trabalho restrito e com suporte a IDL: declare o ID do programa e os manipuladores em
#[program], declare as contas e restrições em structsAccounts, e entãoanchor build/anchor test/anchor deployenviam o binário mais o esquema do cliente. - Por que Importa: A maioria dos bugs de produção no Solana são bugs de validação de conta e de esquema do cliente, não bugs de lógica de negócios inteligentes. Anchor falha fechado em signatários ausentes, proprietários incorretos e seeds de PDA ruins, e mantém os clientes TypeScript (e outros) honestos através do IDL.
- Conceitos Chave:
declare_id!,#[program],Context<T>,#[derive(Accounts)], restrições, estado#[account], IDL,Anchor.toml, SBF /.so, nativo vs Anchor. - Quando Usar: Construindo programas de aplicativos, superfícies de administração, lógica de escrow e marketplace, aplicativos adjacentes a SPL e qualquer coisa que se beneficie de clientes tipados em @solana/kit 7.0.0 ou na pilha TS do Anchor.
- Limitações / Trade-offs: A expansão de macro adiciona tamanho binário e alguma sobrecarga de CU; caminhos de acesso extremos podem querer Pinocchio ou nativo; você ainda deve projetar layouts, ameaças e migrações por conta própria.
- Tópicos Relacionados: Exemplos básicos de Anchor, estrutura do projeto, módulo do programa, struct de contas, fluxo de trabalho, compilação e implantação, Anchor vs nativo.
Fundamentos
O que é Anchor
No nível do runtime, um programa Solana ainda implementa aproximadamente process_instruction(program_id, accounts, instruction_data). Anchor não muda esse contrato. Ele gera o ponto de entrada e descompacta os dados da instrução em manipuladores nomeados com argumentos tipados.
O que você escreve é um workspace: crates Rust em programs/, testes TypeScript (ou outros) em tests/, e Anchor.toml para cluster, IDs de programa e scripts. O framework crate é anchor-lang 0.32.1 (mais anchor-spl quando você toca em Token/Associated Token).
A promessa do produto Anchor é tripla:
- Padrões de segurança - a validação da conta é executada antes do corpo do seu manipulador; restrições ausentes geram erro em vez de confiar silenciosamente nas contas do cliente.
- Ergonomia - menos boilerplate para discriminadores, helpers de CPI e tipos de conta comuns (
Signer,Account<T>,Program<T>). - Contrato do cliente -
anchor buildemite IDL JSON para que o código off-chain e os módulos CPI permaneçam alinhados com as instruções on-chain.
O módulo do programa
use anchor_lang::prelude::*;
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
#[program]
pub mod counter {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
ctx.accounts.counter.count = 0;
ctx.accounts.counter.authority = ctx.accounts.authority.key();
Ok(())
}
pub fn increment(ctx: Context<Increment>) -> Result<()> {
ctx.accounts.counter.count = ctx.accounts.counter.count.checked_add(1).unwrap();
Ok(())
}
}declare_id!codifica permanentemente a chave pública do programa que o binário espera; deve corresponder à implantação (useanchor keys syncapós a alteração da chave do par de implantação).#[program]marca o módulo cujas funções públicas se tornam instruções.- Cada manipulador recebe
Context<SomeAccounts>(e argumentos de instrução opcionais), retornaResult<()>, e muta apenas através de campos de conta validados.
Os dados da instrução não são bytes de forma livre que você analisa ad hoc: Anchor deriva discriminadores de 8 bytes e serializa Borsh os argumentos. Clientes que pulam o IDL (ou o regeneram tarde) quebram de maneiras confusas.
A struct de Contas
Cada instrução nomeia uma struct de contas com #[derive(Accounts)]. Os tipos de campo e os atributos são o programa de validação.
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(
init,
payer = authority,
space = 8 + 8 + 32,
seeds = [b"counter", authority.key().as_ref()],
bump
)]
pub counter: Account<'info, Counter>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[account]
pub struct Counter {
pub count: u64,
pub authority: Pubkey,
}Antes que initialize seja executado, Anchor verifica signatários, mutabilidade, seeds de PDA, ID do programa do sistema e que init aloca e atribui a propriedade corretamente. Account<'info, Counter> desserializa com o discriminador de conta de 8 bytes. Falhas retornam erros do Anchor em vez de escritas parciais.
Estrutura do projeto (mapa mínimo)
workspace/
Anchor.toml # toolchain, programs.<cluster>, scripts
Cargo.toml # workspace members = ["programs/*"]
programs/my_program/
Cargo.toml # anchor-lang = "0.32.1"
src/lib.rs
tests/*.ts
target/deploy/*.so # após compilar
target/idl/*.json # após compilarAnchor.toml fixa qual ID de programa mapeia para qual nome de cluster. O Cargo.toml raiz é um workspace Rust; cada programa é seu próprio crate. Testes normalmente chamam o programa através de um provedor (validador local / Surfpool) usando o IDL gerado.
Compilação, implantação e fluxo de trabalho em uma frase
anchor build compila SBF e regenera o IDL; anchor test implanta localmente e executa testes; anchor deploy envia o .so para um cluster; clientes e consumidores de CPI devem acompanhar o novo IDL e ID do programa.
Anchor vs nativo (orientação)
Programas nativos usam entrypoint!, caminhada manual de contas e codecs de cliente mantidos manualmente. Anchor gera essa superfície. Você paga algum tamanho/CU e ganha restrições mais IDL. Núcleos de liquidação quente às vezes deixam Anchor; a maioria dos programas de produto não deve começar nativa "por pureza".
Mecânicas e Interações
Como as peças interagem de ponta a ponta:
Editar lib.rs (#[program] + Accounts + estado #[account])
|
v
anchor build --> target/deploy/*.so + target/idl/*.json
|
v
anchor test --> validador local/Surfpool + testes TS
|
v
anchor deploy --> programa atualizável no cluster
|
v
keys sync / IDL publish --> clientes e consumidores de declare_program!
Caminho de dispatch on-chain
- Transação lista ID do programa, contas e dados da instrução.
- Runtime carrega o programa
.soe invoca o ponto de entrada gerado. - Anchor corresponde ao discriminador de instrução de 8 bytes a um manipulador.
- Anchor desserializa argumentos e constrói
Context<T>validando a structAccounts. - Seu manipulador executa a lógica de negócios e retorna
Ok(())ou um erro. - Em caso de sucesso, as escritas de dados da conta e as alterações de lamport são confirmadas com a transação; em caso de erro, toda a transação falha.
Contexto é a entrega
Context<T> contém accounts: T, program_id, bumps (para bumps de PDA descobertos durante a validação) e contas restantes quando você as usa. Manipuladores não devem reanalisar listas AccountInfo do zero; eles devem confiar (e apenas estender com require!) o que as restrições já impuseram.
Restrições são a fronteira de segurança
Atributos comuns:
| Restrição / tipo | Papel |
|---|---|
Signer | Assinatura de transação presente |
mut | Metadado de conta gravável exigido |
init / init_if_needed | Criar (cuidado com o último) |
seeds + bump | Derivação de PDA e verificação de endereço |
has_one | Igualdade de campo (ex: autoridade armazenada) |
Program<T> | ID do programa conhecido (System, Token, …) |
constraint = expr | Invariante booleano personalizado |
A ordem importa para segurança de init e CPI; trate a ordem de validação como parte do design, não um acidente de listagem de atributos. Regras de negócios personalizadas pertencem a restrições ou require! antecipados, não "verificaremos mais tarde se nos lembrarmos".
Interações de configuração do workspace
- Derivação do ID do programa: binário
declare_id!,Anchor.toml[programs.*]e chave do par de implantação on-chain devem concordar. Após a implantação,anchor keys syncreescreve fontes/configuração quando a chave do par é a fonte da verdade. - Derivação do IDL: alterações na API pública (nova ix, campos renomeados, layout da conta) exigem reconstrução e regeneração do cliente. Enviar apenas um novo
.sosem IDL é como dapps chamam discriminadores incorretos. - Isolamento do cluster: localnet, devnet e mainnet-beta são universos de contas separados; nunca reutilize uma suposição de ID de programa devnet em clientes mainnet.
Lado do cliente
Testes e aplicativos constroem instruções a partir do IDL. @solana/kit 7.0.0 não requer Anchor especificamente, mas precisa de formatos de fio corretos. A força do Anchor é produzir esse contrato a partir das mesmas macros que geram o programa. Prefira regenerar clientes tipados em CI quando o IDL mudar.
Considerações Avançadas e Aplicações
Projetando instruções como uma superfície de API
Pense em cada função #[program] como um método público versionado. Discriminadores estáveis e ordens de conta estáveis importam mais do que módulos Rust inteligentes. Prefira instruções aditivas e layouts de conta versionados em vez de reordenação silenciosa de campos.
Quando você altera o space da conta, planeje instruções de realloc ou migração; clientes que mantêm layouts antigos falharão na verificação de discriminador ou desserialização por boas razões.
Padrões de falha fechada vs risco residual
Anchor remove classes inteiras de erros (autoridade não assinada, proprietário do programa incorreto em Account<T>, endereço incorreto do programa do sistema). Ele não inventa seu modelo de ameaça:
- Quem pode chamar esta instrução?
- Quais contas ainda são
UncheckedAccounte por quê? - As contas de token são do mint/autoridade esperados?
- O
init_if_neededcria uma superfície de ataque de re-inicialização? - Os alvos de CPI e os limites das contas restantes se mantêm sob metadados adversários?
A revisão de segurança ainda se concentra em restrições, seeds e gráficos de CPI - não apenas na matemática do manipulador.
Workspaces multi-programa e CPI
Um workspace pode conter vários crates em programs/. Chamadas entre programas precisam de metadados de conta corretos e, no Anchor 0.32, frequentemente declare_program! ou tipos compartilhados para o chamado. Limites de framework ainda compõem via CPI: um programa Anchor pode chamar nativo/Pinocchio se bytes e seeds corresponderem.
Disciplina de lançamento que corresponde ao framework
- Fixe Anchor CLI / anchor-lang 0.32.1, Rust 1.91.1, Solana CLI 3.0.10 na documentação e CI.
anchor builde comite ou publique artefatos IDL intencionalmente (a política varia; não os deixe acidentais).anchor testverde na pilha local antes do devnet.- Implantação em Devnet + testes de integração contra RPC real.
- Mainnet apenas com compilações verificáveis, higiene da autoridade de atualização e uma história de rollback.
Quando ficar no Anchor vs sair
| Situação | Preferir |
|---|---|
| MVP, admin, marketplace, lógica de aplicativo DeFi padrão | Anchor 0.32.1 |
| Forte necessidade de clientes orientados por IDL e iteração rápida | Anchor |
| Teto de CU medido em um caminho de acesso quente | Otimize Anchor primeiro; extraia o núcleo Pinocchio/nativo se ainda estiver apertado |
| Tamanho binário extremo / auditoria quer verificações totalmente explícitas | Nativo ou Pinocchio (ver Anchor vs nativo) |
| Sistema misto | Periferia Anchor + CPI para núcleo magro |
Perfilar com transações fixas e unitsConsumed; não reescreva frameworks por intuição.
Concepções Errôneas Comuns
- "Anchor é um runtime diferente ou uma cadeia separada." Ele compila para programas SBF comuns no Agave; validadores não tratam Anchor de forma especial.
- "Restrições significam que posso pular o design de segurança." Restrições aplicam o que você declara. Suposições de confiança não declaradas permanecem exploráveis.
- "
declare_id!é decorativo." A incompatibilidade com o programa implantado causa falhas no runtime (DeclaredProgramIdMismatch). Sincronize após alterações de chave. - "Manipuladores são executados antes das verificações de conta." A validação da struct
Accountsé executada primeiro; o manipulador assume umContextválido. - "IDL é documentação opcional." Para programas Anchor, o IDL é o contrato do cliente. Trate-o como um artefato de lançamento.
- "Nativo é sempre mais rápido, então sempre comece nativo." Frequentemente falso para velocidade da equipe e segurança. Meça; use Anchor como padrão para programas de aplicativos.
- "
anchor deploysozinho atualiza todos os clientes." A implantação atualiza o bytecode on-chain; aplicativos, indexadores e módulos CPI precisam do IDL e ID do programa correspondentes. - "Qualquer
AccountInfoem contas restantes é seguro se a struct principal for estrita." Contas restantes são uma superfície de bypass comum; vincule e valide-as explicitamente.
FAQs
O que é Anchor em uma frase?
Um framework Rust para programas Solana que gera dispatch de instrução, validação declarativa de contas, erros/eventos e um IDL a partir de macros em cima do runtime Agave padrão.
Quais versões este site fixa?
Anchor 0.32.1, Rust 1.91.1, Solana CLI 3.0.10, Agave 4.1.1, e @solana/kit 7.0.0 como a pilha de cliente de referência.
O que #[program] gera?
O ponto de entrada do programa, correspondência do discriminador de instrução, desserialização de argumentos e a conexão de cada função pública ao seu caminho de validação Context<T>.
O que é Context<T>?
O argumento do manipulador que contém contas validadas (T), o ID do programa, bumps de PDA descobertos durante a validação e contas restantes opcionais.
O que #[derive(Accounts)] faz?
Ele constrói uma lista de contas tipadas e executa restrições de nível de tipo e de atributo (signer, mut, owner, seeds, init, expressões personalizadas) antes que o corpo do manipulador seja executado.
Por que as structs de Contas usam um lifetime <'info>?
As referências de conta estão vinculadas ao escopo de empréstimo AccountInfo da instrução para essa invocação; o lifetime rastreia esse empréstimo de curta duração corretamente em Rust.
Qual é a diferença entre Account<T> e UncheckedAccount?
Account<T> impõe a propriedade do programa e desserializa T com o discriminador de conta do Anchor. UncheckedAccount pula essas verificações; você deve validar manualmente ou estará aberto a ataques.
Como a estrutura do projeto se relaciona com a implantação?
programs/*/src é o crate on-chain; target/deploy contém o .so; Anchor.toml mapeia nomes de programas para chaves públicas por cluster; testes e clientes consomem target/idl.
O que o anchor build produz?
Um objeto compartilhado SBF em target/deploy/ e IDL JSON em target/idl/, além de artefatos de chave do par relacionados para programas implantáveis.
Como devo iterar no dia a dia?
Altere o código do programa e as contas, execute anchor build, execute anchor test localmente, corrija falhas e, em seguida, promova para implantação em devnet e atualizações de cliente antes do mainnet.
Quando devo escolher nativo em vez de Anchor?
Quando os requisitos medidos de CU ou tamanho binário, ou preferências de auditoria/processo para validação totalmente manual, superam a produtividade do IDL e das macros - muitas vezes como uma extração de caminho quente, não uma reescrita de aplicativo inteiro.
Programas Anchor podem chamar programas nativos?
Sim, via CPI, quando os metadados da conta, propriedade, layouts de dados e seeds de signatário PDA correspondem ao que o chamado espera.
Ainda preciso do Solana CLI se usar o Anchor CLI?
Sim. Solana CLI 3.0.10 lida com chaves do par, saldos, airdrops, configuração de cluster e inspeção de solana program ao lado dos comandos anchor.
Para onde devo ir em seguida nesta seção?
Comece com Fundamentos do Anchor para exemplos concretos, depois Estrutura do Projeto, A Struct de Contas, O Fluxo de Trabalho do Anchor, Compilando e Implantando, e Anchor vs Nativo.
Relacionados
- Fundamentos do Anchor - scaffold, manipuladores, IDL e primeiros testes
- Estrutura do Projeto - layout do workspace, Anchor.toml e crates
- A Struct de Contas - derive(Accounts), tipos e restrições
- O Fluxo de Trabalho do Anchor - compilação local, teste, promoção para devnet/mainnet
- Compilando e Implantando - anchor build, deploy, keys sync, IDL
- Anchor vs Nativo - o que as macros geram e quando o nativo vence
Versões da pilha: Esta página foi escrita para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, e @solana/kit 7.0.0.