Criando e Fechando Contas
A criação de conta aloca espaço, atribui um proprietário e financia a isenção de aluguel. O fechamento recupera lamports. realloc aumenta ou diminui os dados no local.
Receita
// Criar
#[account(init, payer = payer, space = 8 + MyData::INIT_SPACE)]
pub data: Account<'info, MyData>,
// Aumentar
#[account(mut, realloc = new_size, realloc::payer = payer, realloc::zero = false)]
pub data: Account<'info, MyData>,
// Fechar
#[account(mut, close = receiver)]
pub data: Account<'info, MyData>,Quando usar isso:
- Fluxos de integração de usuários que criam PDAs ou contas de configuração
- Instruções de migração que expandem o tamanho da conta
- Incentivos de limpeza que retornam aluguel aos usuários
- Encerramento de protocolo recuperando contas de cofre
Exemplo de Trabalho
use anchor_lang::prelude::*;
#[program]
pub mod lifecycle {
use super::*;
pub fn create(ctx: Context<Create>, label: String) -> Result<()> {
ctx.accounts.data.authority = ctx.accounts.payer.key();
ctx.accounts.data.label = label;
Ok(())
}
pub fn expand(ctx: Context<Expand>, extra: u32) -> Result<()> {
ctx.accounts.data.extra = extra;
Ok(())
}
pub fn close_account(ctx: Context<CloseData>) -> Result<()> {
Ok(())
}
}
#[account]
#[derive(InitSpace)]
pub struct MyData {
pub authority: Pubkey,
#[max_len(20)]
pub label: String,
pub extra: u32,
}
#[derive(Accounts)]
pub struct Create<'info> {
#[account(init, payer = payer, space = 8 + MyData::INIT_SPACE)]
pub data: Account<'info, MyData>,
#[account(mut)]
pub payer: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct Expand<'info> {
#[account(
mut,
realloc = 8 + MyData::INIT_SPACE,
realloc::payer = payer,
realloc::zero = false,
)]
pub data: Account<'info, MyData>,
#[account(mut)]
pub payer: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct CloseData<'info> {
#[account(mut, close = receiver, has_one = authority)]
pub data: Account<'info, MyData>,
pub authority: Signer<'info>,
#[account(mut)]
pub receiver: SystemAccount<'info>,
}O que isso demonstra:
- CPIs
initpara o System Program para alocação + transferência de aluguel reallocpode exigir lamports adicionais derealloc::payerclosezera os dados e envia todos os lamports parareceiver
Mergulho Profundo
Etapas de Criação (Tempo de Execução)
- O pagador assina e fornece lamports
- O System Program aloca
spacebytes - O proprietário é definido para o programa de chamada
- O programa grava os dados iniciais
Segurança de Fechamento
- O
closedo Anchor define os lamports para 0 e atribui a propriedade ao System Program - Sempre verifique a autoridade antes de fechar para evitar griefing
- Não é possível fechar contas que ainda detêm fundos inesperados (adicione restrições)
Armadilhas
initsemsystem_program- falha de compilação/tempo de execução. Correção: sempre incluaProgram<'info, System>.- Redução de
reallocperdendo dados - trunca bytes. Correção: migre os dados antes de reduzir ou apenas aumente. - Fechamento de contas referenciadas em outros lugares - quebra indexadores downstream. Correção: emita um evento e documente o ciclo de vida.
- Esqueceu
mutno pagador pararealloc- financiamento insuficiente. Correção: marque o pagador comomutquandoreallocpuder custar lamports. - Fechamento de contas de token com saldo - SPL requer saldo vazio primeiro. Correção: transfira tokens e depois feche via CPI SPL.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
init_if_needed | Integração de usuário idempotente | Segurança estrita de criação única |
| CPI Manual do Sistema | Programas nativos sem Anchor | Projetos Anchor (use macros) |
| Migração de conta nova | Mudanças de layout que quebram compatibilidade | Adições de campo menores |
realloc | Crescimento modesto de tamanho | Grandes alterações de conjunto de dados (novo PDA) |
FAQs
O que o init faz nos bastidores?
CPI para o System Program create_account com espaço, proprietário e lamports do pagador.
Quem pode fechar uma conta?
Seu programa via restrição close - tipicamente exigindo um signatário de autoridade.
Para onde vão os lamports recuperados?
A conta especificada em close = receiver.
Quando o realloc é necessário?
Quando os dados da conta crescem além do space originalmente alocado.
O realloc custa aluguel extra?
Sim, se um tamanho maior exigir um mínimo mais alto de isenção de aluguel. O pagador financia a diferença.
Posso fechar um PDA?
Sim. O programa assina, se necessário; os lamports vão para o receptor.
O que é init_if_needed?
Cria a conta apenas se ela não existir - útil para padrões semelhantes a ATAs com cuidado.
Contas fechadas podem ser reativadas?
O mesmo endereço pode ser reinicializado se recriado com init - trate como uma nova conta.
Como fechar várias contas de uma vez?
Múltiplas restrições close em uma instrução - observe os limites de CU.
O fechamento emite um evento?
Não automaticamente. Adicione emit! para indexadores.
Usuários podem fechar contas sem o programa?
Contas vazias de propriedade do sistema podem ser drenadas; contas de propriedade do programa exigem instrução do programa.
O que é realloc::zero?
Se os novos bytes são zerados. false preserva os dados existentes durante o crescimento.
Relacionado
- Aluguel e Isenção de Aluguel - valores de financiamento
- Contas de Dados e Layout - planejamento de espaço
- Estado de Propriedade do Programa - criação de PDA
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.