Scaffold de Hook de Transferência Token-2022
Hooks de transferência são a extensão Token-2022 mais difícil de acertar: o programa deve expor um discriminador de interface que o Anchor não gera, dispor um
ExtraAccountMetaListcom ordem exata de bytes e resistir a invocações fora da banda. Pequenos erros aparecem como erros opacos de runtime. Esta skill é o caminho seguro por padrão, apoiado por um programa compilável e testes de ataque LiteSVM.vs. as skills de extensões de token:
solana-token-extensions/token-2022-extensionstratam hooks como um recurso (um exemplo estático único, mais uma auditoria em checklist em um caso). Esta é a ferramenta de hook dedicada — a única que gera um hook seguro novo sob demanda (scaffold.sh) e apoia seu auditor com testes de ataque que passam. Complementar: instale-a junto com elas quando estiver realmente construindo ou endurecendo um hook.
Quando usar esta skill
- Construindo um hook de transferência: bloqueio whitelist/KYC, imposição de royalties, roteamento de taxas, contabilização/limites por transferência, regras do tipo soulbound.
- Depurando um hook:
AccountNotFound,NotEnoughAccountKeys,IncorrectAccountAddress, ou "transferência funciona sem o hook, mas falha com ele." - Revisando/auditando um programa de hook existente para as armadilhas padrão.
- Criando um mint Token-2022 que aponta para um hook e conectando a transferência do cliente.
Nota para integradores: se você está do lado consumidor (aceitando um mint de terceiros que tem um hook), esse é um problema diferente — a maioria dos integradores deve rejeitar mints de hook desconhecidos. Veja a skill complementar token2022-integration-guard.
O modelo mental (leia primeiro)
- Um programa de hook implementa
Execute(a interface SPL transfer-hook), que Token-2022 chama via CPI em toda transferência. O Anchor despacha porsha256("global:<ix>"), que NÃO corresponde ao discriminador da interface — então você adiciona umfallbackque decodifica a instrução da interface e despacha em processo (nunca uma self-CPI). → program.md - O hook pode exigir contas extras. Você as declara uma vez em um
ExtraAccountMetaListPDA (["extra-account-metas", mint]); Token-2022 o lê e passa essas contas paraExecute, resolvendo PDAs baseados em sementes no momento da transferência. A ordem é crucial. → extra-account-metas.md - O cliente deve construir a transferência com
createTransferCheckedWithTransferHookInstruction(umtransferCheckedsimples omite as contas extras e reverte). → client-wiring.md - Um hook é atingível por atacantes: proteja-o. → security.md
- Prove isso com testes que transferem através do hook. → testing.md
Tabela de roteamento
| O usuário está… | Leia |
|---|---|
| Escrevendo o programa hook (Execute, fallback, init meta list) | program.md |
| Lutando contra ExtraAccountMetaList / erros opacos de conta | extra-account-metas.md |
| Conectando o mint + a transferência do cliente | client-wiring.md |
| Endurecendo / auditando um hook para segurança | security.md |
| Escrevendo testes para um hook | testing.md |
| Scaffolding de um workspace de hook novo | execute /transfer-hook:scaffold |
| Auditando um programa hook existente | execute /transfer-hook:audit |
| Fontes / leitura adicional | resources.md |
O que acompanha esta skill
| Artefato | Caminho | O que é |
|---|---|---|
| Programa hook de referência | examples/hook/ | Um hook Anchor 1.0 compilável: bloqueio whitelist + contador por mint, roteador fallback e guarda is_transferring. |
| Testes de ataque | examples/hook/tests/ | Testes LiteSVM que transferem através do hook: whitelisted passa (contador incrementa), não-whitelisted falha fechado, Execute direto rejeitado. |
| Script de scaffold | scripts/scaffold.sh | Gera um workspace de hook novo a partir da referência. |
Stack fixada (2026)
Anchor 1.0, anchor-spl 1.0.2, spl-transfer-hook-interface =2.1.0,
spl-tlv-account-resolution 0.11, @solana/spl-token 0.4.14, litesvm 1.2 (nativo do kit,
Token-2022 pré-carregado). O programa de referência compila e seus testes passam nesta stack.
Regras não negociáveis
- Adicione um
fallbackque decodificaTransferHookInstruction::Executee despacha em processo (__private::__global::transfer_hook) — nuncainvokeseu próprio programa. - Inicialize o
ExtraAccountMetaListantes da primeira transferência e mantenha a ordem doVec<ExtraAccountMeta>idêntica à struct de contas do seuExecute. - Proteja o
Executecomis_transferring— rejeite chamadas fora de uma transferência real. - Vincule cada conta injetada a sementes PDA (
Account<T>+seeds), nunca umUncheckedAccountsimples, ou um atacante falsifica sua whitelist. - Mantenha o hook mínimo e total — ele é executado em toda transferência; um pânico/CU pesado quebra o token.
- Teste o caminho de transferência, não apenas a lógica unitária — um hook que compila ainda pode falhar no momento da resolução.