Start with the object model

Sui replaces the account-based accounting ledger found on EVM chains with a direct object model. In standard blockchains, your token balance is just a number stored inside a user’s address. On Sui, that token is an independent, programmable object with its own ID, owner, and version. This shift moves DeFi logic from the background to the foreground, letting smart contracts interact directly with assets rather than managing abstract balances.

Objects can be owned by accounts, other objects, or the protocol itself. This structure allows for composability that mirrors real-world finance. When you swap tokens on a Sui DEX, you aren't updating two separate ledger entries; you are moving specific objects from one wallet to another and updating their metadata simultaneously. This atomicity prevents the state inconsistencies that often plague cross-chain bridges and complex DeFi strategies.

Sui Move primitives

This model is particularly powerful for lending protocols. Instead of locking funds into a shared pool, a user deposits a specific NFT or token object into a lending contract. The contract holds that object, and the user receives a corresponding receipt object. If the user wants to withdraw, they return the receipt, and the original object is transferred back. This explicit ownership tracking makes liquidation logic clearer and safer, as the protocol knows exactly which objects to seize.

Understanding this object-centric architecture is the first step to building efficient DeFi applications. It allows for parallel transaction processing, meaning swaps, deposits, and withdrawals can happen simultaneously without clogging the network. By treating assets as first-class citizens, Sui provides a foundation where DeFi primitives are not just simulated, but executed with native efficiency.

Bundle actions in PTBs

Programmable Transaction Blocks (PTBs) are the engine that powers complex DeFi logic on Sui. Instead of submitting individual transactions that settle one after another, PTBs allow you to group multiple operations into a single atomic unit. This means every action either succeeds completely or fails entirely, eliminating the risk of partial execution where funds might get stuck in an intermediate state.

This atomicity is critical for operations like decentralized swaps. When you trade Token A for Token B, you need to ensure the transfer happens exactly when the price is agreed upon. With PTBs, you can bundle the swap logic with the asset transfers. If the slippage tolerance is exceeded or the liquidity pool doesn't have enough reserves, the entire block reverts, and your original assets remain untouched.

To build these bundles, you rely on Move primitives to manipulate Sui objects. Think of a PTB as a single transaction containing several sub-tasks. You can create new objects, transfer existing ones, and update state all within the same block. The system executes these steps in parallel where possible, but the final outcome is guaranteed to be consistent.

Sui Move primitives
1
Create or reference objects

Start by defining the objects involved in your transaction. This could be a new coin object you are minting or an existing liquidity pool object you are referencing. You use Move to specify the type and initial state of these objects, ensuring they are ready to participate in the atomic sequence.

Sui Move primitives
2
Transfer assets between objects

Use the transfer primitive to move assets between the objects you defined. Unlike older systems that restricted transfers, Sui Move allows you to transfer any object programmatically. This step moves the tokens from the user's wallet into the liquidity pool, or vice versa, as part of the swap logic.

Sui Move primitives
3
Update state and emit events

Once the assets have moved, update the internal state of the objects to reflect the new balances. This might involve adjusting the exchange rate in a pool or updating a counter. Finally, emit an event to log the transaction on-chain, providing a transparent record of the atomic operation for off-chain services to track.

Handle assets with abilities

Move treats assets like physical objects rather than simple ledger entries. This distinction is enforced through four abilities: store, key, drop, and copy. These modifiers dictate how objects can be moved, stored, and destroyed, effectively embedding security logic directly into the type system.

When you build a DeFi protocol, these abilities prevent entire classes of bugs. For example, drop prevents memory leaks by ensuring resources are explicitly discarded, while copy restricts duplication, stopping double-spending at the compiler level. Without these constraints, a simple swap or deposit could accidentally leave dangling references or create phantom tokens.

Consider a liquidity pool deposit. The pool must mark its internal token structures with store so they can persist on-chain, but the user’s incoming tokens must be key-able to ensure unique ownership. If you misconfigure these, the compiler blocks the transaction before it ever hits the network.

By strictly defining how assets behave, you remove the need for complex reentrancy guards. The language itself ensures that once an asset is moved out of a context, it cannot be accessed again, making your DeFi primitives inherently safer and easier to audit.

Avoid common transfer errors

When building DeFi protocols on Sui, the most frequent source of bugs isn't complex logic—it's mishandling object ownership. Unlike Ethereum, where tokens are just balances in a contract, Sui treats assets as distinct objects with unique IDs. If your code treats these objects like simple variables, users will lose funds or transactions will fail silently.

The primary pitfall is ignoring the transfer primitive. In Move, you cannot simply assign an object ID to a variable and expect it to remain on-chain. If you create an object but don't transfer it to a user's address or store it in a persistent struct, it becomes inaccessible. This is especially dangerous in DeFi swaps where intermediate tokens must be passed between contracts.

Consider a simple swap function. If your code creates a new token object but fails to call transfer to the recipient's wallet, that token remains in the transaction's temporary state and is discarded when the block finalizes. The user sees no balance increase, and your protocol appears broken. Always ensure every new object is explicitly transferred to its final owner.

Never assume an object persists just because you created it. Explicitly transfer ownership to the user or a storage struct.

Another common error is assuming object IDs are stable across transactions. While IDs are unique, they are not predictable. If your protocol relies on hard-coded IDs or expects an ID to remain constant after a reset, it will fail. Always retrieve the current object ID from the chain state or pass it as a parameter to your functions.

Finally, be careful with freeze and destroy operations. Freezing an object makes it immutable, which is useful for NFTs but disastrous for liquidity pools that need to update balances. Destroying an object removes it entirely from the chain. In DeFi, accidental destruction of pool shares or liquidity tokens can lead to permanent loss of value. Always double-check that your destruction logic is gated by strict conditions, such as a successful exit from a pool.

Verify your contract logic

Before pushing to mainnet, you must treat your Sui Move code as a live asset. A DeFi module handles real value, so verification is not just about syntax; it is about ensuring object ownership, ability constraints, and transaction atomicity hold under pressure.

Start by auditing object ownership. In Sui, objects are the primary unit of state. Ensure that sensitive objects like liquidity pools or vaults are owned by the module itself (Transfer::public_share or Transfer::private) rather than by individual users. If a user owns the pool object, they can arbitrarily destroy or move it, bypassing your logic entirely.

Next, verify ability constraints. Move’s type system prevents certain operations based on the copy, drop, store, and key abilities attached to your structs. For example, if your Token struct lacks the key ability, it cannot be stored in global storage. If it lacks drop, you cannot accidentally burn tokens by dropping a variable. Run sui move check to catch these static errors early.

Finally, test atomicity using Programmable Transaction Blocks (PTBs). Your DeFi actions—such as a swap or deposit—should be wrapped in a PTB to ensure they execute as a single unit. If a swap fails halfway through, the entire transaction reverts, leaving the user’s state untouched. This prevents partial updates that could leave funds in an inconsistent state.

Sui Move primitives

Questions about Sui Move

Developers often ask how the Move language differs from other smart contract platforms and how it handles speed. The answers lie in Sui’s unique object model and parallel execution engine.

What is Move on Sui?

Move is an open-source programming language designed specifically for Sui. It allows developers to define, create, and manage programmable objects representing assets. Unlike traditional smart contracts that rely on global state variables, Move treats assets as distinct objects with their own addresses and ownership rules. This makes it easier to write safe packages that manipulate onchain data without the risk of accidental state corruption.

Is Sui faster than Solana?

Sui achieves high throughput by executing transactions in parallel rather than sequentially. Because Move objects are independent, the network can process multiple swaps or deposits simultaneously if they don’t touch the same assets. Solana also uses parallel execution, but Sui’s object-centric model often results in lower latency for complex DeFi interactions. The result is a network that feels more responsive during peak activity, handling thousands of transactions per second with consistent finality.