Estado de Propriedade do Programa
Programas Solana são executáveis sem estado. Todo estado durável vive em contas de propriedade do programa - endereços separados cujo campo owner é o ID do seu programa.
Receita
#[account]
pub struct Escrow {
pub maker: Pubkey,
pub amount: u64,
}
#[account(
init,
payer = maker,
space = 8 + Escrow::INIT_SPACE,
seeds = [b"escrow", maker.key().as_ref()],
bump,
)]
pub escrow: Account<'info, Escrow>,Quando usar isso:
- Projetando qualquer protocolo que armazena dados de configuração de usuário ou globais
- Substituindo padrões EVM
mapping(address => Data) - Separando estado "quente" por usuário de contas de configuração globais
- Habilitando transações paralelas em contas de usuário não sobrepostas
Exemplo de Trabalho
use anchor_lang::prelude::*;
declare_id!("Escrow1111111111111111111111111111111111111");
#[program]
pub mod escrow_program {
use super::*;
pub fn initialize(ctx: Context<Initialize>, amount: u64) -> Result<()> {
let escrow = &mut ctx.accounts.escrow;
escrow.maker = ctx.accounts.maker.key();
escrow.amount = amount;
Ok(())
}
pub fn release(ctx: Context<Release>) -> Result<()> {
let escrow = &ctx.accounts.escrow;
require!(escrow.amount > 0, EscrowError::Empty);
// transfere lamports via CPI...
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(
init,
payer = maker,
space = 8 + Escrow::INIT_SPACE,
seeds = [b"escrow", maker.key().as_ref()],
bump,
)]
pub escrow: Account<'info, Escrow>,
#[account(mut)]
pub maker: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[account]
#[derive(InitSpace)]
pub struct Escrow {
pub maker: Pubkey,
pub amount: u64,
}O que isso demonstra:
- O estado do escrow é uma conta pertencente a
escrow_program - As seeds do PDA vinculam a conta a um maker específico
- O bytecode do programa nunca armazena
amount- apenas a conta de escrow o faz
Mergulho Profundo
Padrões de Estado
| Padrão | Seeds | Uso |
|---|---|---|
| PDA por usuário | [b"user", pubkey] | Perfis, posições |
| Configuração global | [b"config"] | Configurações do administrador |
| Cofre por mint | [b"vault", mint] | Custódia de tokens |
Por que Programas Sem Estado
- O mesmo código de programa atende a usuários ilimitados por meio de contas separadas
- Execução paralela quando transações tocam contas diferentes
- Atualizações substituem o código sem migrar o armazenamento embutido
Armadilhas
- Singleton global para todos os usuários - contenção e limites de tamanho. Correção: fragmentar o estado entre PDAs.
- Armazenar estado apenas nos dados da instrução - não é durável. Correção: persistir em contas.
- Armazenamento de bump de PDA ausente - custo de recomputação e problemas de canonicalidade de seeds. Correção: armazenar o bump na conta ou usar
seeds::programcombump. - Divergência de proprietário na inicialização - outro programa poderia se passar por ele. Correção:
initdo Anchor define o proprietário automaticamente. - Não fechar contas obsoletas - aluguel travado para sempre. Correção: restrição
closequando o ciclo de vida termina.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| PDA por entidade | Estado mutável específico do usuário | Pequenas flags globais |
| Conta de configuração única | Configurações de todo o protocolo | Dados de usuário com muitas escritas |
| Conta zero-copy | Dados de conta grandes | Estruturas pequenas |
| Compressão de estado | Mints / reivindicações em massa | Registros atualizados com frequência |
FAQs
Onde meu programa armazena o saldo de um usuário?
Em uma conta de propriedade do programa (geralmente um PDA) - não dentro do binário do programa.
Programas podem ler contas de estado de outros programas?
Sim, se passadas na transação e a desserialização for conhecida. A escrita ainda requer lógica do programa proprietário.
Quantas contas um programa pode possuir?
Endereços distintos ilimitados. Cada um é uma conta separada on-chain.
Qual é o anti-padrão de conta global?
Uma conta contendo todos os registros de usuários. Causa limites de tamanho, explosões de CU e falha na paralelização.
PDAs contam como estado de propriedade do programa?
Sim. PDAs são contas pertencentes ao programa derivado.
Como o upgrade afeta o estado?
As contas de estado persistem entre os upgrades do programa. Apenas o bytecode muda.
Posso migrar o estado para um novo layout?
Sim, via realloc, novas contas ou versionamento de desserialização em manipuladores de instrução.
Quem paga para criar contas de estado?
O payer em init - usuário ou protocolo subsidiador.
Programa-proprietário é o mesmo que usuário-proprietário?
O programa possui a conta; o usuário controla por meio de verificações de signatário nas instruções que a modificam.
Como os indexadores encontram todas as contas de um programa?
RPC getProgramAccounts com filtros memcmp nos discriminadores.
Contas de estado podem conter SOL?
Sim - campo lamports. Comum em padrões de escrow e cofre.
O que é InitSpace no Anchor 0.32.1?
Macro de derivação que calcula o tamanho serializado Borsh para o atributo space.
Relacionado
- Contas do Sistema vs. Contas de Programa - tipos de conta
- Contas de Dados e Layout - serialização
- Criando e Fechando Contas - ciclo de vida
Versões da Pilha: 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.