Token-2022 轉帳鉤子模板 是做什麼的?
轉帳鉤子是 Token-2022 中最難正確實作的擴展:程式必須暴露 Anchor 不會自動產生的介面判別器,以位元組精確的順序佈局
ExtraAccountMetaList,並抵禦帶外調用。小小的錯誤就會導致不透明的執行時期錯誤。此技能是一條預設安全的捷徑,由可編譯的程式和 LiteSVM 攻擊測試作為後盾。與 token-extensions 技能的比較:
solana-token-extensions/token-2022-extensions將鉤子視為一個功能(一個靜態範例,加上一個清單審查)。此為專用的鉤子工具——唯一一個能按需生成全新安全鉤子(scaffold.sh)並透過通過的攻擊測試來支援其審查功能的工具。互補性:當您實際構建或強化鉤子時,可與它們一同安裝。
何時使用此技能
- 建立轉帳鉤子:白名單/KYC 閘門、版稅強制執行、費用路由、每筆轉帳記帳/限制、類靈魂綁定規則。
- 除錯鉤子:
AccountNotFound、NotEnoughAccountKeys、IncorrectAccountAddress,或「沒有鉤子時轉帳正常,加上鉤子就失敗」。 - 審查/稽核現有鉤子程式的常見陷阱。
- 建立指向鉤子的 Token-2022 代幣鑄幣廠,並編寫用戶端轉帳。
整合者注意:如果您是消費端(接受一個含有鉤子的第三方鑄幣廠),那是另一個問題——大多數整合者應拒絕未知的鉤子鑄幣廠。請參閱配套技能 token2022-integration-guard。
心智模型(請先閱讀此部分)
- 鉤子程式實作
Execute(SPL 轉帳鉤子介面),Token-2022 會在每次轉帳時透過 CPI 調用它。Anchor 透過sha256("global:<ix>")進行分派,這不符合介面判別器——因此您需添加一個fallback來解碼介面指令並在行程內分派(絕不進行自我 CPI)。→ program.md - 鉤子可以要求額外帳戶。您可以在單一
ExtraAccountMetaListPDA(["extra-account-metas", mint])中宣告它們;Token-2022 讀取它並在轉帳時將這些帳戶傳遞給Execute,並解析基於種子的 PDA。順序至關重要。→ extra-account-metas.md - 用戶端必須使用
createTransferCheckedWithTransferHookInstruction建立轉帳(單純的transferChecked會遺漏額外帳戶並還原)。→ client-wiring.md - 鉤子可被攻擊者觸及:請保護它。→ security.md
- 透過透過鉤子進行轉帳的測試來證明它。→ testing.md
路由表
| 使用者正在… | 閱讀 |
|---|---|
| 編寫鉤子程式(Execute、fallback、初始化元資料列表) | program.md |
| 處理 ExtraAccountMetaList / 不透明帳戶錯誤 | extra-account-metas.md |
| 編寫鑄幣廠 + 用戶端轉帳 | client-wiring.md |
| 強化 / 審查鉤子的安全性 | security.md |
| 為鉤子編寫測試 | testing.md |
| 建立一個全新的鉤子工作區 | 執行 /transfer-hook:scaffold |
| 審查現有鉤子程式 | 執行 /transfer-hook:audit |
| 來源 / 進一步閱讀 | resources.md |
此技能提供的內容
| 工件 | 路徑 | 說明 |
|---|---|---|
| 參考鉤子程式 | examples/hook/ | 一個可編譯的 Anchor 1.0 鉤子:白名單閘門 + 每個鑄幣廠計數器、fallback 路由器,以及 is_transferring 守衛。 |
| 攻擊測試 | examples/hook/tests/ | LiteSVM 測試,透過鉤子進行轉帳:白名單通過(計數器增加)、非白名單被拒絕、直接 Execute 被拒絕。 |
| 腳手架腳本 | scripts/scaffold.sh | 從參考範例中生成一個全新的鉤子工作區。 |
固定技術棧 (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(套件原生,已預載 Token-2022)。參考程式可編譯且其測試在此技術棧上通過。
不可妥協的規則
- 添加
fallback來解碼TransferHookInstruction::Execute並在行程內分派(__private::__global::transfer_hook)——絕不使用invoke調用自己的程式。 - 在第一次轉帳之前初始化
ExtraAccountMetaList,並保持Vec<ExtraAccountMeta>的順序與您的Execute帳戶結構體完全相同。 - 使用
is_transferring守衛Execute——拒絕來自真實轉帳之外的調用。 - 將每個注入的帳戶綁定到 PDA 種子(
Account<T>+seeds),絕不使用裸露的UncheckedAccount,否則攻擊者可以偽造您的白名單。 - 保持鉤子最小且完整——它會在每次轉帳時執行;當機/過高的計算單元會使代幣無法使用。
- 測試轉帳路徑,而不僅僅是單元邏輯——一個能編譯的鉤子在解析階段仍可能失敗。