11. Porting reflexes, the grep-able checklist
- Every
Addressparameter → an explicit auth decision; privileged paths auth a stored role address, never the parameter. - Every layer that exercises an address’s authority calls
require_auth, including the outermost one (middleware replay). get+ mutate is banned; read-modify-write goes throughupdate.checked_*on every money path;amount > 0at every amount-taking entry point (i128is signed).- No
unwrap/expect/barepanic!on externally reachable paths,panic_with_error!orErronly; error codes frozen forever. - Nothing load-bearing in
temporary(); TTL is never a permission; deadlines live in values. - Fine-grained storage keys; no per-tx iteration over user-controlled collection sizes; instance storage stays small and global.
- Every user-supplied contract address is allowlisted; every callee return value is validated (length, sign, sum, freshness).
extend_ttlin hot paths and an owned, runbooked keep-alive job; max TTL makes liveness an operational property.mock_all_authsnever appears without anenv.auths()assertion on the same invocation.- Solvency (and every conservation law the type system used to give you) is asserted in code and is the fuzz oracle.
- One upgrade path per contract: either a gated
update_current_contract_wasmor a repointable address in a caller; never both, ideally neither on custody. - Getters are pure; no writes, no TTL bumps: view traffic is simulation, and simulation discards writes.
- Nothing the contract branches on lives only in events; events are write-only in production; if logic reads it, store it.
- Every function computing a share, fee, or payout makes the
transfercall in the same body; a split that is only published settled nothing, and only abalanceassertion catches it.
← Cheat sheet index · ← 10. Toolchain quick map · 12. Verification →