Squelette de Hook de Transfert Token-2022
Les hooks de transfert sont l'extension Token-2022 la plus difficile à maîtriser : le programme doit exposer un discriminateur d'interface qu'Anchor ne génère pas, organiser un
ExtraAccountMetaListavec un ordre octet-exact, et résister aux appels hors contexte. Les petites erreurs se manifestent par des erreurs d'exécution opaques. Cette compétence est la voie sécurisée par défaut, soutenue par un programme compilable et des tests d'attaque LiteSVM.vs les compétences d'extensions de token :
solana-token-extensions/token-2022-extensionstraitent les hooks comme une fonctionnalité (un seul exemple statique, plus une checklist d'audit dans un cas). C'est l'outil dédié au hook — le seul qui génère un nouveau hook sécurisé à la demande (scaffold.sh) et qui soutient son auditeur avec des tests d'attaque fonctionnels. Complémentaire : installez-le à côté d'eux lorsque vous construisez ou durcissez réellement un hook.
Quand utiliser cette compétence
- Construire un hook de transfert : filtrage whitelist/KYC, application de royalties, routage de frais, comptabilité/limites par transfert, règles de type âme-liée.
- Déboguer un hook :
AccountNotFound,NotEnoughAccountKeys,IncorrectAccountAddress, ou « le transfert fonctionne sans le hook mais échoue avec ». - Réviser/auditer un programme de hook existant pour les pièges standards.
- Créer un mint Token-2022 qui pointe vers un hook, et câbler le transfert côté client.
Note pour l'intégrateur : si vous êtes du côté consommateur (acceptant un mint tiers qui a un hook), c'est un problème différent — la plupart des intégrateurs devraient rejeter les mints à hook inconnus. Voir la compétence complémentaire token2022-integration-guard.
Le modèle mental (lisez ceci d'abord)
- Un programme de hook implémente
Execute(l'interface SPL transfer-hook), que Token-2022 CPI à chaque transfert. Anchor distribue parsha256("global:<ix>"), ce qui NE correspond PAS au discriminateur de l'interface — vous ajoutez donc unfallbackqui décode l'instruction d'interface et distribue en cours (jamais un self-CPI). → program.md - Le hook peut exiger des comptes supplémentaires. Vous les déclarez une fois dans un
PDA
ExtraAccountMetaList(["extra-account-metas", mint]) ; Token-2022 le lit et passe ces comptes àExecute, résolvant les PDA basés sur des seeds au moment du transfert. L'ordre est important. → extra-account-metas.md - Le client doit construire le transfert avec
createTransferCheckedWithTransferHookInstruction(un simpletransferCheckedomet les comptes supplémentaires et échoue). → client-wiring.md - Un hook est accessible à un attaquant : protégez-le. → security.md
- Prouvez-le avec des tests qui transfèrent via le hook. → testing.md
Table de routage
| L'utilisateur est… | Lire |
|---|---|
| En train d'écrire le programme de hook (Execute, fallback, init de la liste de métas) | program.md |
| En train de lutter contre ExtraAccountMetaList / les erreurs de compte opaques | extra-account-metas.md |
| En train de câbler le mint + le transfert client | client-wiring.md |
| En train de durcir / auditer un hook pour la sécurité | security.md |
| En train d'écrire des tests pour un hook | testing.md |
| En train de générer un nouvel espace de travail de hook | exécutez /transfer-hook:scaffold |
| En train d'auditer un programme de hook existant | exécutez /transfer-hook:audit |
| Sources / lectures complémentaires | resources.md |
Ce qui est livré dans cette compétence
| Artefact | Chemin | Ce que c'est |
|---|---|---|
| Programme de hook de référence | examples/hook/ | Un hook Anchor 1.0 compilable : filtrage whitelist + compteur par mint, routeur fallback, et garde is_transferring. |
| Tests d'attaque | examples/hook/tests/ | Tests LiteSVM qui transfèrent via le hook : whitelisté passe (compteur incrémenté), non-whitelisté échoue, Execute direct rejeté. |
| Script de génération de squelette | scripts/scaffold.sh | Produit un nouvel espace de travail de hook à partir de la référence. |
Pile figée (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 (natif du kit,
Token-2022 préchargé). Le programme de référence compile et ses tests passent sur cette pile.
Règles non négociables
- Ajoutez un
fallbackqui décodeTransferHookInstruction::Executeet distribue en cours (__private::__global::transfer_hook) — jamaisinvokevotre propre programme. - Initialisez le
ExtraAccountMetaListavant le premier transfert, et gardez l'ordre duVec<ExtraAccountMeta>identique à votre structure de comptesExecute. - Protégez
Executeavecis_transferring— rejetez les appels en dehors d'un vrai transfert. - Lie chaque compte injecté à des seeds PDA (
Account<T>+seeds), jamais unUncheckedAccountnu, sinon un attaquant falsifie votre whitelist. - Gardez le hook minimal et total — il s'exécute sur chaque transfert ; une panique / CU élevée bloque le token.
- Testez le chemin de transfert, pas seulement la logique unitaire — un hook qui compile peut encore échouer au moment de la résolution.