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.