Move is the programming language Sui runs for every on-chain program, and Sui Move is the dialect of that language that stores assets as objects with unique IDs rather than as resources inside accounts. The word "Move" in a headline can mean five different things, and mixing them up is how a Solidity habit, an Aptos tutorial, or a Diem-era example gets copied onto the wrong chain.
Those five names are worth sorting before any syntax, and the Sui glossary keeps the dialect labels in one place. Move is the language family, Diem Move is the original account-and-resource version written inside Meta's payments project, and Sui Move is the object-centric adaptation the Sui docs actually document. Aptos Move is a sibling dialect with its own storage model rather than a drop-in copy, and Solidity is a different family entirely, the EVM one, so a contract written for it will not compile here.
Generic smart-contract theory, gas auctions, and EVM calling conventions belong in how Ethereum smart contracts work. The dialect also sits in the wider layer-1 comparison frame. The Sui job is narrower: what the language family promises, what the Sui dialect changes, and which bugs that still does not prevent.
Five names that all get called "Move"
Sui's own concepts page is unusually plain about which dialect it is teaching. "Move is an open source language for writing safe packages to manipulate onchain objects". It then warns that "Where the Sui documentation refers to the Move language, the content is documenting the specific Move implementation on the Sui blockchain", and that the original use case is named Move on Diem when the difference matters. Sui Move drops Diem's global storage and the move_to / move_from operations that went with it, treats address as a 32-byte object ID rather than a 16-byte account key, requires an id: UID field on every object, adds a one-shot init on publish, and gives entry a Sui-specific meaning inside programmable transaction blocks. Inputs are named up front by those IDs so the scheduler can run non-overlapping transactions in parallel, which is a dialect choice, not a Solidity port. (source: Sui's Move concepts docs)
| Name | What it actually is | What it is not |
|---|---|---|
| Move | A language family designed so assets are hard to copy or lose by accident | A single compiler you can point at any chain |
| Diem Move | The original account-and-resource dialect | What Sui mainnet runs |
| Sui Move | Move plus objects, unique IDs, init, and Sui's entry rules | Aptos Move with a different logo |
| Aptos Move | The other live dialect from the same Meta lineage | A Sui package you can republish |
| Solidity | The main EVM contract language | Something Move compiles from |
Aptos and Sui share abilities and a scarcity bias, then diverge on storage, standard libraries, and transaction shape. That comparison is the Sui-versus-Aptos article. Architecture around validators, checkpoints, and how a transaction is scheduled sits in the guide on how Sui works.
The project's beginner page makes a stronger claim than a type system can cash on its own: "the programming language used to build Sui apps has ownership and permission rules baked in, making certain types of exploits structurally harder to write in the first place". That is the project's own wording, not an audit of every package on mainnet. (source: Sui's beginner guide) What "structurally harder" does and does not cover is the Cetus lesson in the risks section, not a property of the brochure sentence.
Why the language is called Move
Ownership is the mechanism, and the Move Book says the name comes from it. "Ownership is the central concept of Move - it is even where the language got its name". The promise the book states is that "a value cannot be duplicated and cannot be accidentally lost", and the compiler is what enforces it: a program that breaks the rules does not compile. Every value has one owner at a time: passing it into a function moves it, and returning it moves it back. When a scope ends, anything still sitting there must be discardable or already handed off. (source: The Move Book on ownership)
Suppose Priya writes a Coin type with no abilities, mints one coin, and tries to pass that same value into spend twice. The first call moves the coin, so the second call is a compile error rather than a runtime surprise. The book walks that exact failure: the compiler points at the line where the value was previously moved, and it will not let her spend the same coin twice. That is move semantics doing the job a Solidity mapping does with require checks you can forget to write.
The same example shows the other half of the promise. If she mints a coin and lets the function end without passing it on, that is also an error, because a type without drop cannot be forgotten in a local variable. Assets do not silently vanish at the closing brace, so data types that should vanish opt into drop on purpose.
This is stricter than the EVM habit in smart contract security, where a token balance is usually a number in a map and copying that number is ordinary. Move's default is the opposite: copying is a privilege the type has to declare, and a forgotten require is not how scarcity is enforced.
Four abilities, deny by default
Abilities are the permission bits on a type. The Move Book's introduction is the clean statement: "Move has a unique type system in which each type declares what its values are allowed to do". "By default, a Move value can only be created, moved around, and taken apart; everything beyond that is a privilege the type must be granted explicitly". The four abilities are copy (duplicate), drop (discard), key (a unit of storage, on Sui an object), and store (allowed inside other stored values). A type without copy cannot be duplicated, and a type without drop cannot be lost, which is how Move models assets without relying on programmer memory. (source: The Move Book on abilities)
| Ability | What it unlocks | Typical home |
|---|---|---|
| copy | The value can be duplicated | Integers, booleans, addresses, plain data |
| drop | The value can be discarded when a scope ends | The same data types, plus receipts you are done with |
| key | The value can sit in on-chain storage as an object | Coins, NFTs, admin caps, pools |
| store | The value can live inside an object | Nested metadata, balances inside a wrapper |
A struct can only receive an ability its fields also support, so granting copy to a wrapper whose inner type cannot be copied is a compile error. A type with no abilities at all is a hot potato: the receipt shape used for flash-style obligations.
On Sui, key is the object bit, and the storage chapter is direct: "Throughout the book, we refer to any struct with the key ability as an object". The Sui verifier then adds a layout rule the original Diem key did not have: the first field must be id: UID. "Objects can never have drop or copy". That follows from UID itself having neither ability, so an object is non-copyable and non-discardable by construction. (source: The Move Book on the key ability)
The object-model article covers ownership kinds, shared versus address-owned, and wrapping. key plus UID is what makes a Sui type an object, and that choice is a dialect change from Diem, where key marked a resource in global storage.
store is the quieter sibling: it lets a type sit inside an object, while a value with copy or drop but no store lives only for the transaction that created it and cannot be persisted. Combining the three non-key abilities is allowed in any mix, and none of them implies another.
Packages, modules, init, and upgrades
A Sui program is not a single Solidity file: it is a package, a published bundle of modules at an address. The Move Book's package page says "A single program is organized into a package". "A package is published on the blockchain" and is identified by an address. Locally that is a directory with Move.toml and a sources folder. After publish, "A published package becomes immutable and can be interacted with by sending transactions". An upgrade does not edit that bytecode in place: it "publishes a new version of the package at a new address, leaving the old version intact". (source: The Move Book on packages)
Sui's upgrade docs repeat the immutability in protocol language: "Sui smart contracts are immutable package objects consisting of a collection of Move modules". They also carry two operational facts that surprise people coming from upgradeable EVM proxies. "Module initializers do not re-run with package upgrades". And "You cannot delete old packages from the network". Callers can keep hitting the old address, and other packages can keep calling methods defined there. (source: Sui's package upgrade docs)
init is the one-shot setup hook. The Move Book's initializer page says the runtime calls it on publish, and that "These rules are not a convention - they are enforced by the bytecode verifier". A module added in an upgrade will not have its init called. The usual pattern is to create an AdminCap in init and transfer it to the publisher, so the first transaction after publish already has an owner for privileged calls. (source: The Move Book on module initializers)
That is a different upgrade story from a Solidity proxy, where the same address keeps serving new logic. On Sui the old package stays, the new package gets a new address, and init will not run again to hand you a second admin object unless you write that on purpose. Capability objects are how privilege survives that split: the admin object outlives the package address that minted it.
entry functions and programmable transaction blocks
entry is the Sui-specific keyword people copy from a tutorial without noticing it is not a visibility level. A public function is already callable from a transaction. The Move Book's advanced chapter is blunt: the modifier "is only meaningful on _non-public_ functions - private or public(package)", and what it creates is a narrowed contract in two directions. Other packages cannot wrap the function, act on its result, or build it into larger logic. Arguments passed to it must also be free of obligations created by other commands in the same programmable transaction block. "This guarantee is checked _statically_, before the transaction begins execution". A transaction that violates it fails verification and is not executed. Those rules arrived in Sui v1.62 and replaced an older, tighter set. The teaching case is a flash loan: if Priya's coin was minted from a borrowed balance whose Loan receipt is still live, a non-public entry spend will not take that coin until the receipt is unpacked. (source: The Move Book on entry functions)
Sui's PTB docs say the same thing from the transaction side. "PTBs can call any public function and any entry function, whether private (entry fun f()), or public(package) (public(package) entry fun f())". Non-entry private functions cannot be called from a PTB, and "there is no reason to add entry to a public function". Older signature limits on entry parameters have been removed, so an entry function can now take and return the same shapes a public function can. (source: Sui's programmable transaction block docs)
Hold on to one thing: entry is a caller-limiting tool for a PTB, not a badge that makes a function "the" entry point of a package, and if the function is already public, the keyword is decoration.
Capabilities and hot potatoes: two patterns the type system is for
A capability is an object you pass to prove you are allowed to do something. The Move Book treats it as a door key: if you hold the object, the function that asks for it will compile; if you do not, it will not. "There's a convention to name capabilities with the Cap suffix". An AdminCap created in init and transferred to the publisher is the usual "there is one admin" setup. Abilities on the cap decide how freely it can move. With key and store, it can be transferred with public transfer functions and stored inside other objects. With only key, only the defining module can move it, so the module can restrict or forbid handing the cap on. (source: The Move Book on capabilities)
A hot potato is the opposite extreme: a struct with no abilities, called that because "none of the modules can keep it". Once constructed, "the transaction will abort due to unused value without drop" unless the defining module unpacks it. Flash-loan receipts and put-it-back wrappers use that shape. The potato cannot leak into storage and cannot be ignored. (source: The Move Book on hot potatoes)
Here is a quick scenario. A lending package issues a Receipt with no abilities when Priya borrows against a shared pool. Her programmable transaction block must repay and unpack that receipt in the same block, or the whole block aborts. She cannot stash the receipt in her wallet and walk away, because that is not a runtime warning: it is the type system refusing to let the transaction end.
Neither pattern exists in the same form in Solidity, where access control is usually an address check you write by hand and a callback you remember to call. Move makes the forgotten callback a compile failure, which is the teaching value, and it is also not a substitute for reading the package you are about to sign, which is the same habit smart-contract wallet risk trains on a different stack.
Limits of Move
Deny-by-default abilities close a class of bugs: accidental copies of an asset, dropped coins, and public functions that should have required a cap. They do not close math bugs in a library, oracle bugs, or an upgrade cap held by someone you do not trust. Bytecode verification is a second filter, not a substitute for reading the package.
The May 2025 drain of Cetus, a major Sui app, is the dated reminder. Independent write-ups traced it to an overflow check in a helper, not to someone copying a key object they did not own. The Move VM aborts on many integer overflows, and that particular shift still wrapped. The dated incident record lives in the guide on whether Sui is safe. The language lesson is smaller: safe packages, in the docs' opening sentence, is a design goal, and an app can still miss a boundary condition.
Sui Move also does not make two dialects interoperable. A module written against Aptos's account-and-resource model will not publish on Sui without a rewrite, even though both are "Move." Treat a random GitHub snippet as chain-specific until the Move.toml and the object types say otherwise.
The compiler emits Move bytecode, and the Sui verifier checks that bytecode before the package object is stored. New objects must get fresh UIDs that are never reused, which is a network rule on top of the language rather than something a Solidity compiler equivalent does. It still assumes the package that creates the object is the package you meant to call.
Where Sui Move fits, and what to read next
Step back and the dialect is one decision repeated at every layer. Values move, they do not copy, unless the type says so. Storage is objects with IDs, not a hidden global map. Privilege is an object you hold, not an address in a list, unless the package went out of its way to store addresses, and setup runs once at publish. Upgrades mint a new package and leave the old one standing. entry limits who can wrap a function inside a PTB, and it does not make the package safe by itself.
You do not need to memorize the four abilities on sight: you need the default, which is that if a type looks like an asset it probably cannot be copied or dropped, and if a function asks for a Cap, the cap is the permission. The guide on how Sui works places this language in the rest of the stack. The object-model article is the next stop if the question is ownership kinds rather than types. If the question is whether language-level safety made the chain safe to use, that is the guide on whether Sui is safe, which is a different question on purpose.
Frequently asked questions
What is Move on Sui?
It is the dialect of Move that Sui actually runs: object-centric storage, 32-byte IDs, a required UID on every key type, a one-shot init, and an entry keyword with Sui-specific PTB rules. Diem's address was 16 bytes and keyed an account in global storage. Sui reused the type as a 32-byte identifier for objects and accounts after dropping that global map.
Is Sui Move the same as Aptos Move?
No, they are not the same dialect. They share a family, abilities, and a scarcity bias, then split on storage and standard libraries. A compiled Aptos bytecode blob will not republish on Sui, and a Sui package will not compile for Aptos without a rewrite. The side-by-side lives in the Sui-versus-Aptos comparison.
Can I write Solidity and deploy it on Sui?
No, Solidity will not deploy on Sui. Solidity targets the EVM. Move targets a different bytecode and a different type system. Some teams publish tooling that translates or wraps, but that is a product claim to verify, not a property of Sui Move. Even a working translator would still have to emit Sui objects with UID fields, because that layout is a verifier rule, not a style choice.
If Move is "safe," why do Sui apps still get exploited?
Because abilities stop copy-and-drop mistakes, not every math bug, oracle bug, or admin-key mistake. Cetus in May 2025 is the public case: an overflow in a helper, not a stolen key object. The helper compiled, which is the point: language safety is a compile-time filter, and published bytecode can still be wrong. Read the package, the cap holders, and the upgrade policy, not only the language brochure.
What is an ability in Move?
A permission the type declares, one of copy, drop, key, and store. The default is none of them. A type without copy cannot be duplicated. A type without drop cannot be discarded. On Sui, key plus a UID field is what makes a struct an object, and combining copy, drop, and store is allowed in any mix because none of those three implies another.
Do Move packages on Sui upgrade in place?
No, they do not upgrade in place. Publish makes an immutable package object at an address. An upgrade publishes a new version at a new address and leaves the old bytecode up. init does not re-run on that upgrade, and nothing deletes the old package, so callers can keep using it. Other packages can keep calling methods on that old address too.
Why is the language called Move?
The Move Book says ownership is the central concept and that the language is named for it. Values are moved from owner to owner. They are not copied unless the type opts in. Returning a value from a function is also a move, which is the opposite default of most languages, including Solidity.
What does the entry keyword do?
It is not a visibility level. On a non-public function it lets a programmable transaction block call the function while forbidding other packages from wrapping it. Adding entry to an already-public function does nothing useful. A PTB that breaks the hot-potato argument rules fails verification before it runs, a check the Move Book dates to Sui v1.62.
Researched and written by the BloFin Academy editorial team with AI-assisted drafting. Updated August 2026. Primary sources include Sui's Move concepts, package-upgrade, and programmable-transaction-block docs, The Move Book's ownership, abilities, key, package, capability, hot-potato, initializer, and entry-function pages, and Sui's beginner guide. Language facts checked against those cited pages as of August 13, 2026.
This article is educational and general in nature, not financial or investment advice. Cryptocurrencies like SUI carry real risks, including price volatility, project execution risk, smart-contract exploits in ecosystem apps, and the chance of losing funds. Nothing here is a recommendation to buy, sell, hold, or participate in any project. Do your own research, and consider speaking with a licensed professional before making financial decisions. BloFin does not provide investment advice.
