Appearance
HookAPIVersion
Purpose: declares which Hook API ABI a newly created hook's WASM was written against. On this branch (dev) the only accepted value is 0 (Guard-type hooks); there is no gas-metered ABI (HookApiVersion 1) or sfHookGas/sfHookCallbackGas/sfHookWeakGas fields in this codebase.
Field declaration: UINT16, code 20.
It is soeOPTIONAL on sfHook and soeREQUIRED on ltHOOK_DEFINITION.
Storage is definition-only — the mirror image of HookName. Unlike most sfHook fields, sfHookApiVersion is never legal on the per-account sfHook entry at all (forbidden on install and update — see below), so it only ever exists on ltHOOK_DEFINITION. The hsoCREATE case writes it exclusively onto the new definition and never onto the newHook object representing the account's chain entry. This is the exact opposite storage rule from HookName, which lives only on the entry and never on the definition — don't assume every sfHook field is dual-homed.
Required and pinned to 0 on hsoCREATE.
Both branches are temMALFORMED (API_MISSING/API_INVALID): missing and HookApiVersion: 1 values are rejected. This confirms the branch has no live gas-hook ABI — 1 is not a placeholder for a future feature flag, it is simply invalid input today.
Forbidden on hsoINSTALL (API_ILLEGAL) — installing a hash never lets you re-declare its ABI version, since that's a property of the WASM the definition already fixed at create time.
(The comment says "not allowed in update" but this branch of the code is in the hsoINSTALL case — the message text is copy-pasted from the update case below it; the check itself is correctly scoped to install by virtue of which switch arm it's in.) It produces temMALFORMED.
Forbidden on hsoUPDATE, identically (API_ILLEGAL) — same rejection, same log code.
Forbidden on hsoDELETE and hsoNSDELETE as part of each operation's "only these fields may be present" whitelist — see Operation Matrix.
Net effect: sfHookApiVersion is legal in exactly one place across the entire SetHook surface — a hsoCREATE entry, where it is mandatory and must equal 0. Every other operation forbids it outright, and it is never readable back from a per-account sfHook entry, only from the ltHOOK_DEFINITION the entry's sfHookHash points at.
Common mistakes:
- Sending
HookApiVersion: 0on an install or update "just to be explicit" — this is rejected exactly like any other non-empty value would be; the field must be entirely absent outside of create. - Assuming a value other than
0is reserved for gas-metered hooks on this branch. There is no gas-hook support here; any non-zero value is simply malformed input, not a forward-compatible flag. - Looking for
sfHookApiVersionon the per-accountltHOOKentry when inspecting a live hook. It is only ever onltHOOK_DEFINITION; the per-account entry only carriessfHookHashpointing at it.
Related documents
- HookName — the field with the opposite storage rule (entry-only, never on the definition).
- CreateCode — the other fields
hsoCREATErequires alongsidesfHookApiVersion. - Operation Matrix — full per-operation field matrix, including the amendment gates for the other create-time fields.