Model ownership before functions

Sui applications should begin with an object and authority model. Identify owned, shared, immutable, wrapped, and dynamic-field objects; define who can create, transfer, mutate, delete, or freeze each one; and record how those permissions change over time. The object graph is part of the security architecture, not an implementation detail.

Entry functions should require the narrowest authority needed. Review whether a caller can substitute an object from another market, campaign, pool, or configuration and whether IDs are bound to the intended parent state.

Use capabilities deliberately

Capabilities encode authority as resources. Document every administrative, minting, treasury, upgrade, pause, and operator capability, including how it is created, stored, transferred, revoked, or destroyed. Avoid broad capabilities when separate roles can reduce blast radius.

Witness patterns and one-time initialization should be tested against duplicate creation and package-upgrade paths. Public functions that expose generic composition need review for unintended combinations of types and capabilities.

Control shared-state and value movement

Shared objects require careful reasoning about concurrency, transaction ordering, versioning, and contention. Validate state transitions and conservation properties under competing transactions, not only sequential examples. Dynamic fields should use stable keys and enforce parent-child relationships so state cannot be hidden, duplicated, or orphaned.

For Coin and Balance operations, define rounding, minimums, overflow behavior, treasury authority, and invariant checks. Any conversion between internal accounting and transferable assets needs tests at zero, maximum, and precision boundaries.

Review upgrades and package dependencies

Record package IDs, dependency versions, upgrade policy, upgrade capability custody, and migration assumptions. Consumers need a reliable way to discover the active package and object versions. An upgrade should preserve type and state expectations or provide an explicit migration path with acceptance tests.

Production evidence should link the source commit, Move tests, package build output, published package transaction, package ID, upgrade policy, capability owner, initialized objects, indexer status, and operator runbook.

Test adversarial transactions

Tests should cover unauthorized capabilities, substituted objects, invalid parents, repeated initialization, stale shared objects, concurrent writes, malformed dynamic fields, zero and boundary values, dependency failures, and upgrade transitions. State-machine and property tests help confirm conservation and permission invariants across transaction sequences.