Пост
Поделитесь своими знаниями.
what are the most common mistakes new Move developers make?
Q: For those mentoring new devs, what pitfalls do you see most often when people first deploy contracts on Sui?
- Sui
- Architecture
- SDKs and Developer Tools
Ответы
8Here’s a summarized list of common mistakes new Move developers make on Sui:
Common Pitfalls for New Move Devs on Sui:
- Misunderstanding Sui’s object model
- Treating everything like Ethereum accounts/slots instead of objects with ownership.
- Overusing shared objects
- Making too many objects shared → high contention, poor parallelism, more gas.
- Not handling Balance
properly
- Keeping loose Coin
s → coin equivocation risks, unnecessary merges/splits.
- Ignoring type safety features
- Skipping phantom types or resource semantics → cross-asset bugs, lost assets.
- Redundant storage writes
- Rewriting big objects instead of using events or child objects for history.
- Weak access control
- Forgetting to gate admin functions with capabilities or checks → anyone can mutate.
- Poor concurrency design
- Centralizing state in one shared object instead of distributing into children → bottlenecks.
- Gas inefficiency
- Emitting large events or storing full history on-chain instead of minimal diffs + off-chain indexing.
Embrace the object-centric model, use Balance, design for parallelism, and lean on Move’s type system + caps for safety.
For devs who’ve already wrapped their head around Sui’s object model, what are some advanced design patterns you’ve found helpful for avoiding these pitfalls—especially around shared object contention and balancing on-chain vs off-chain data?
When new developers start writing Move contracts on Sui, there are some recurring mistakes that tend to surface. If you’re mentoring new devs, these are the pitfalls you’ll probably see most often
Overusing Shared Objects
A lot of beginners model everything as a shared object, thinking it’s the “safe” option. In reality, shared objects are more expensive because they require consensus, and they often block parallelism. New developers miss that owned objects are cheaper, faster, and easier to reason about for most use cases.
Forgetting Cleanup Paths
Move enforces resource safety (you can’t drop or duplicate resources), but developers sometimes forget to provide destroy or reclaim functions. This leads to objects that get “stuck” because they can’t be moved or reclaimed, effectively locking user funds or assets.
Weak Access Control
It’s easy to forget that anyone can call a public entry function. New developers sometimes expose functions without checking ownership or capability permissions, which allows unintended or malicious calls. A best practice is to enforce capability checks or explicit ownership validation at every sensitive entry point.
Relying Too Much on Frontend Validation
Beginners often assume checks like “amount > 0” or “valid token type” can be safely left to the frontend. But Move contracts need to enforce these invariants on-chain, since any attacker can bypass UI checks by calling functions directly.
Inefficient Object Usage
Another common trap is repeatedly splitting and merging coins, or creating large, complex structs with vectors on-chain. This leads to high gas usage. Efficient developers learn to keep objects lean, reuse them, and batch writes to reduce storage overhead.
Ignoring Gas Profiling
New developers sometimes deploy without ever simulating or profiling gas costs. This results in contracts that technically work but are too expensive to use in practice. The Sui CLI’s dry-run
and dev-inspect
features are underused by beginners, even though they’re essential for testing efficiency.
Assuming Move’s Type System Prevents All Bugs
While Move’s linear types prevent duplication and resource loss, they don’t automatically protect against logical errors. Beginners often write code that looks safe but fails in edge cases (e.g., incorrect math in balance updates, or not checking vault supply caps).
When you are just starting with Move on Sui, one of the most common mistakes is forgetting that resources in Move cannot be copied or dropped unless you explicitly allow it. New developers often try to treat tokens or objects like regular variables and run into compiler errors. Another pitfall is poor struct design where ownership fields or access controls are not clearly defined, which can cause capability errors later. Many also overlook the importance of testing with the Sui CLI or dev inspect before publishing, which leads to wasted gas on fixes that could have been caught earlier. Mismanaging gas budgets is another frequent issue since underestimating gas can cause transactions to fail, while overestimating can lock up unnecessary amounts. Finally, new devs sometimes import modules or package IDs incorrectly, which causes “module not found” errors that can be avoided with careful rebuilds. If you slow down, understand object ownership, and rely on the compiler’s safety checks, you will save yourself a lot of frustration.
What’s the first mistake most beginners make with Move?
New Move devs often misuse object ownership (confusing shared vs. owned), forget to enforce invariants with types, ignore gas optimization, hardcode upgrade logic instead of using versioning, and underestimate testing on devnet before mainnet deploy.
When you are just starting out with Move on Sui the most common mistakes usually come from misunderstanding how resources and objects work. Many new developers try to copy or drop resources like Coin<SUI>
without realizing that the type system prevents duplication or loss by design. Another mistake is not thinking in terms of owned objects and shared objects which leads to wrong assumptions about transaction flow or access control. Some developers also forget to set proper entry points with public entry
making functions inaccessible from transactions. Gas budgeting is another area where beginners struggle since they may use values that are too low or too high causing failed transactions or wasted funds. Finally many new devs overlook testing with dev-inspect
before publishing so simple logic errors end up on chain. The key is to embrace Move’s resource safety model test in small steps and think in terms of object ownership rather than a global contract.
- Ignoring Object-Centric Design
Treating Sui like Ethereum and trying to build global state contracts instead of leveraging object-based ownership.
Example: Keeping all balances in one shared object rather than giving users individual owned objects.
Impact: Increases contention, kills parallelism, and raises gas costs.
- Overusing &mut References
New devs often borrow &mut unnecessarily for read-only actions.
Why it’s a problem: Mutable references increase transaction dependencies and prevent parallel execution.
Best Practice: Use immutable & references for reads unless you need to modify the object.
- Forgetting Access Control
Not implementing proper ownership checks or capabilities.
Common issue: Anyone can call withdraw because the function doesn’t enforce owner verification.
Solution: Always enforce TxContext::sender() or object ownership where needed.
- Mishandling Object IDs
Using hardcoded IDs in production code or assuming objects never change owners.
Impact: Breaks composability and security when objects move between accounts.
Tip: Always fetch object IDs dynamically or via configuration objects.
- Poor Gas Optimization
Creating large vectors or unnecessary copies of data.
Using vector::push_back in loops without preallocating capacity.
Storing redundant data instead of using references.
Result: Transactions become expensive and may fail during congestion.
- Ignoring Storage Economics
Forgetting that storage costs are charged upfront and refunded on deletion.
Common mistake: Leaving unnecessary objects in storage after use.
Fix: Delete temporary objects when they’re no longer needed.
- No Versioning or Upgrade Plan
Deploying with no upgrade strategy for shared objects.
When schema changes, existing objects break.
Best Practice: Use a governance-controlled upgrade process or version fields in objects.
- Improper Error Handling
Returning default values instead of aborting with clear error codes.
Makes debugging and auditing harder.
Solution: Use abort with descriptive error constants.
- Forgetting to Validate Inputs
Not checking token types, zero amounts, or integer overflow.
Impact: Leads to exploits or unexpected state corruption.
Best Practice: Validate everything that can be abused (amount > 0, correct coin type, etc.).
- Overcomplicating Capabilities
Creating unnecessary custom capabilities instead of using Sui’s native ownership and dynamic fields.
Leads to bloated code and more security risks.
Mentor’s Rule of Thumb
Always think in terms of object lifecycle and ownership.
Minimize shared state.
Validate inputs.
Test in localnet/testnet with realistic scenarios (including concurrency).
- Treating Sui Like an Account-Based Chain
Many developers come from Ethereum/Solana and try to implement balances or state in a single global object.
Problem: This kills Sui’s parallel execution advantage and creates unnecessary contention.
Better: Design using owned objects per user whenever possible.
- Ignoring Ownership Semantics
Not using Move’s strong ownership model effectively.
Examples:
Failing to restrict transfers of capability objects.
Allowing unauthorized object mutations because ownership isn’t checked against TxContext::sender().
- Not Thinking About Object Lifecycle
Forgetting that objects can be created, transferred, deleted, and that storage refunds happen.
Leaving unused objects in storage, causing unnecessary gas costs and state bloat.
Best Practice: Always clean up temporary objects.
- Gas-Heavy Design Choices
Using large vectors, multiple lookups, or nested loops on-chain.
Common case: building complex indexing structures on-chain instead of off-chain.
Better: Keep on-chain logic minimal, push indexing and aggregation off-chain.
- Overcomplicated Role Management
Trying to implement custom RBAC without understanding capability-based security in Move.
Result: Role escalation vulnerabilities or overly complex logic.
Better: Use Move’s type system and capability patterns (e.g., AdminCap, MintCap).
- Forgetting Type Safety in Token Handling
Not enforcing exact coin type checks (Coin
Impact: Users could deposit wrong tokens, breaking invariants.
Always validate token types explicitly.
- Missing Input Validation
Allowing amount = 0 deposits/withdrawals.
Ignoring overflow checks.
Not checking that an object actually exists or is the correct type.
- Deploying Without Upgrade Strategy
Forgetting versioning for objects or governance logic for shared objects.
When schema changes, old contracts break.
Plan: Include version fields or governance-upgradable architecture.
- Poor Error Messages
Using generic abort codes or not handling errors properly.
Makes debugging and auditing harder for both devs and users.
- Skipping Test Scenarios for Concurrency
Not testing under parallel execution conditions.
Issues:
Race conditions on shared objects.
Lock contention that increases latency.
Fix: Simulate multiple transactions in localnet/testnet
- Designing for Accounts Instead of Objects
New developers often assume Sui works like Ethereum or Solana and try to store all user balances in one shared object.
Why it’s wrong: This defeats Sui’s parallel execution and causes contention on a single object.
Correct approach: Use owned objects per user or design with dynamic fields for scalability.
- Misusing TxContext and Sender Validation
Forgetting to enforce TxContext::sender() for actions that require user authorization.
Or allowing operations without confirming ownership of the object being mutated.
- Overlooking Capability-Based Security
Instead of leveraging Move’s capability pattern, devs hardcode roles or rely on address checks.
Problem: This introduces upgrade headaches and security holes.
Best practice: Issue and restrict capability objects for roles like admin, minter, or issuer.
- Inefficient Storage Design
Creating unnecessary intermediate objects.
Not reusing existing structures, leading to higher gas costs and state bloat.
Example: keeping historical data on-chain instead of off-chain.
- Lack of Type-Specific Token Checks
Accepting any Coin
Result: Users can deposit the wrong token, breaking vault logic.
Solution: Explicitly check for Coin
- Ignoring Object Lifecycle and Deletion
Failing to destroy unused objects after operations.
Leaving orphan objects in storage, causing extra costs and clutter.
Always call object::delete or design a reclaim mechanism.
- Poor Gas Awareness
Writing loops over large vectors on-chain.
Performing unnecessary sorting, filtering, or complex math in Move.
Fix: Push computation off-chain where possible, keep on-chain logic minimal.
- Insufficient Access Control for Shared Objects
Shared objects are global. Not checking access before mutating leads to serious security flaws.
Always verify who can act on shared objects and enforce capability-based permissions.
- Forgetting Versioning for Upgrades
Deploying without an upgrade path or governance logic.
When contract schema changes, users lose funds or functions break.
Include version fields and consider upgradeable governance design.
Знаете ответ?
Пожалуйста, войдите в систему и поделитесь им.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Заработай свою долю из 1000 Sui
Зарабатывай очки репутации и получай награды за помощь в развитии сообщества Sui.

- ... SUIDpodium.js+181
- ... SUITucker+165
- ... SUIGifted.eth+149
- ... SUIacher+113
- ... SUIcasey+88
- ... SUIMiniBob+65
- ... SUItheking+55
- Почему BCS требует точного порядка полей для десериализации, когда структуры Move содержат именованные поля?55
- «Ошибки проверки нескольких источников» в публикациях модуля Sui Move — автоматическое устранение ошибок45
- Сбой транзакции Sui: объекты, зарезервированные для другой транзакции49
- Ошибка Sui Move — невозможно обработать транзакцию Не найдено действительных газовых монет для транзакции315
- Как максимизировать прибыль, держа SUI: стейкинг и ликвидный стейкинг110