ratchetv0.3.2

Rule catalog

16 upgrade-safety rules grouped by what they protect. Each has a stable ID that never changes once published; severities and allow flags are tuned conservatively — when in doubt ratchet flags.

ID
Name
Severity
Allow flag
R001
account-field-reorder
Shared account fields were reordered; every existing account now deserializes to garbage because Borsh lays fields out by declaration order.
BREAKING
R002
account-field-retype
A shared field's type changed. Any size change shifts every later byte offset; same-size retypes (u64 → i64) are wire-compatible but semantic breaks.
BREAKING
allow-type-change
R003
account-field-removed
A field was removed from an account. Its bytes remain on-chain and get misread as the next field by the new program.
BREAKING
allow-field-removed / --migrated-account
R004
account-field-insert-middle
A new field was inserted before existing fields. Borsh offsets shift, corrupting every existing account.
BREAKING
allow-field-insert / --migrated-account
R005
account-field-append
A new field was appended. Existing accounts lack those bytes; they need reallocation via Anchor's realloc constraint or a migration.
UNSAFE
allow-field-append / --realloc-account / --migrated-account
R006
account-discriminator-change
An account's 8-byte discriminator changed (typically a struct rename). Every existing on-chain account fails AccountDiscriminatorMismatch.
BREAKING
allow-rename
R007
instruction-removed
An instruction was removed. Every existing client calling it gets InstructionFallbackNotFound.
BREAKING
allow-ix-removal
R008
instruction-arg-change
An instruction's argument signature changed (reordered, retyped, added, removed). Existing clients send bytes the program misreads.
BREAKING
allow-ix-arg-change
R009
instruction-account-list-change
An instruction's account list shape changed. Solana dispatches accounts by index; the wrong account now lands at each slot's position.
BREAKING
allow-ix-account-change
R010
instruction-signer-writable-flip
is_signer or is_writable toggled on an existing slot. Tightening (false → true) breaks existing callers; relaxation (true → false) is safe.
MIXED
allow-signer-mut-flip
R011
enum-variant-removed-or-inserted
A Borsh-serialized enum variant was removed or inserted before existing variants, shifting the ordinal of every later variant.
BREAKING
R012
enum-variant-append
A new variant was appended at the tail. Ordinals of existing variants are preserved — safe; reported for visibility only.
ADDITIVE
R013
pda-seed-change
A PDA's seed expression changed. Every existing account at the old address is orphaned; no client can re-derive it with the new formula.
BREAKING
allow-pda-shape-change (presence flip only)
R014
instruction-discriminator-change
An instruction's discriminator changed (handler rename, explicit override). Existing callers dispatch into the wrong handler.
BREAKING
allow-ix-rename
R015
account-removed
An account struct disappeared entirely. Every existing on-chain account of that type is unreachable through the new program.
BREAKING
allow-account-removal
R016
event-discriminator-change
An event's 8-byte log selector changed. Every off-chain indexer filtering for the old value goes silent on the next emit.
BREAKING
allow-event-rename

Pass an allow flag with --unsafe <flag> (e.g. --unsafe allow-rename).

--migrated-account <Name> demotes R003, R004, and R005 for that account — use when a Migration<From, To> or custom migration instruction exists.

--realloc-account <Name> demotes R005. Auto-populated from source when --new-source is provided and the field carries #[account(realloc = ...)].