Footguns
Common footguns in Anchor that can lead to issues.
Zeroed Discriminators
Anchor supports overriding discriminators with custom values (for accounts, events and instructions).
All-zero discriminators are only supported in events and instructions. In the case of accounts, e.g:
they are explicitly not supported, as all-zero discriminators are indistinguishable from newly allocated accounts and can expose your code to security and usability issues.
Generic Account Types
Different instantiations of the same generic #[account] type share a default discriminator:
generic arguments are not part of its derivation.
An account serialized as State<u128> can deserialize as State<u64>: the discriminator
matches, and deserialization reads the first eight bytes of the value, leaving the remaining
bytes unchecked. The reverse requires enough account data for a u128; a minimally sized
State<u64> account is too short.
Generic arguments do not distinguish accounts
If the serialized data for one instantiation can be deserialized as another, an account can pass the discriminator check and be interpreted as the wrong type. Do not rely on generic arguments to prevent this type confusion. Use distinct account structs with distinct discriminators, or explicitly validate a stored type tag before using the account data.
Borrowed Data in Account Types
Account types used with Context should own their values rather than hold references borrowed
from other accounts or handler-local data. Do not replace an AccountInfo's lamports or data
backing reference with a reference to a field in ctx.accounts. Mutate the account contents
instead of their backing references.
Avoid borrowed account data
For example, avoid account types such as
struct Borrowed<'info> { value: Cell<Option<&'info u64>> }. Anchor 1.0 uses simplified
Context lifetimes, which can make a reference retained through Cell, RefCell, or similar
interior mutability outlive the value it points to.