Security & Common Vulnerabilities

Move eliminates whole classes of bugs (re-entrancy, double spending of resources, dangling references), but logic and access-control bugs remain.

39.1 Common pitfalls

Capability leak Admin/mint capability given store and accidentally returned or transferred publicly; or a function returns &mut internals

Minimize abilities; never return caps from public functions; audit public functions returning objects Missing access control

Public function mutates privileged state without checking caller

Require &AdminCap, check signer address, or bind caps to object IDs Cap not bound to object AdminCap for pool A works on pool B

Store pool_id in the cap and assert equality Arithmetic aborts as DoS

Overflow in fee math blocks all withdrawals; division by zero on empty pool

Use u128/u256 intermediates, check zero denominators, saturate where appropriate Precision loss / rounding

Rounding always favoring the user lets attackers drain dust repeatedly

Round in favor of the protocol; mul before div; minimum amounts Shared object contention

Single hot shared object limits throughput and enables griefing

Shard state, use owned objects, minimize shared writes Public functions composed in PTBs

Sui: any public function can be combined arbitrarily, e.g., flash loan + oracle manipulation

Treat every public function as an entry point; use hot potatoes for enforced flows Randomness misuse

Public randomness consumers, uneven gas paths Private entry functions, equal gas paths Oracle manipulation Using AMM spot price as an oracle

TWAPs or external oracles (Pyth, Switchboard, Supra) Unchecked generic types

Function accepts any Coin<T> and treats it as the expected currency

Constrain types (Coin<SUI>), store TypeName and compare, use phantom types Object ID confusion

Passing a different object of the same type than intended Store and check expected IDs Unbounded growth

Vectors in shared objects grow until operations exceed gas/size limits Tables, pagination, per-user objects Upgrade risks

Old package versions remain callable (Sui) Versioned shared objects; gate old entry points

Visible pending transactions on shared objects Commit-reveal, slippage limits, deadlines Signer misuse (Aptos)

Storing or passing signer-derived capabilities too broadly

Keep SignerCapability/ExtendRef private; never expose functions returning signer publicly

39.2 Defensive checklist

Every public/entry function: who can call it, with which objects, and what can they gain?

Every struct: are its abilities minimal? (Does a cap really need store? Does a receipt need drop?)

Every arithmetic expression: overflow, underflow, divide-by-zero, rounding direction.

Every shared object: contention, griefing, unbounded growth.

Every external input: object IDs, coin types, amounts, deadlines, slippage bounds.

Tests for failure paths (#[expected_failure]), fuzz/random tests, and formal specs for invariants.

Third-party audit (OtterSec, Zellic, MoveBit, Certora, Asymptotic, Trail of Bits...) before mainnet value.