ratchetv0.4.0

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, is_writable, or optionality toggled on an existing slot. Tightening (incl. optional → required) breaks existing callers; relaxation is safe.
MIXED
allow-signer-mut-flip
R011
enum-variant-removed-or-inserted
A Borsh-serialized enum variant was removed, inserted before existing variants (shifting later ordinals), or changed its payload shape.
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 discriminator changed; every off-chain listener filtering for the old value goes silent. Only fires on programs that declare events — ratchet never requires adding them.
BREAKING
allow-event-rename
R017
event-removed
An event was removed; every off-chain listener subscribed to it goes permanently silent with no error anywhere. Only fires on programs that declare events.
BREAKING
allow-event-removal
R018
error-code-change
A declared error was removed, renumbered, or repurposed. Clients matching on the old code misroute their error handling.
UNSAFE
allow-error-change
R019
type-shape-change
A nested user-defined type (struct or alias referenced by name) changed shape. Every account or instruction embedding it reads shifted bytes.
BREAKING
allow-type-shape-change
R020
serialization-change
An account switched between Borsh and zero-copy (bytemuck) layout, or its repr changed. Identical fields, incompatible bytes.
BREAKING
allow-serialization-change

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 = ...)].