Resource-Oriented Programming vs Solidity

In Solidity, a token balance is just a number in a mapping:

3.1 The problem Move solves

In Solidity, a token balance is just a number in a mapping:

The "asset" is an integer, and nothing in the language stops a buggy contract from incrementing it out of thin air, forgetting to decrement, or being re-entered mid-update.

In Move, the asset is a value of a resource type:

A Coin cannot be copied (no copy ability) and cannot be silently discarded (no drop ability). The compiler and verifier force every Coin to end up somewhere: transferred, stored in an object, joined into another coin, or destroyed by the coin module itself.

mapping(address => uint256) public balances;

function transfer(address to, uint256 amount) external {
    require(balances[msg.sender] >= amount, "insufficient");
    balances[msg.sender] -= amount;
    balances[to] += amount;
}
public struct Coin<phantom T> has key, store {
    id: UID,
    balance: Balance<T>,
}

3.2 Linear types in one paragraph

A linear value must be used exactly once. Move's abilities give a fine-grained version: a type without drop must be consumed; a type without copy cannot be duplicated. A struct with neither is a true linear resource. A struct with no abilities at all is a "hot potato" — it must be passed back to its module in the same transaction (Chapter 31).

3.3 Comparison table

Solidity / EVM Integers in contract storage First-class typed values (resources) Copy / destroy safety

Enforced by type system + bytecode verifier Common vulnerability class

Impossible: no dynamic dispatch, references cannot escape call, interfaces, delegatecall

None; generics are monomorphic and statically linked Checked since 0.8 (unchecked blocks exist) Always checked; overflow aborts Per-contract key-value slots

Per-account resources (Aptos) or objects (Sui) msg.sender checks

&signer, capabilities, object ownership Native package upgrades with compatibility checks Move Prover, spec language built in

Sui: owned objects skip consensus; Aptos: Block-STM optimistic parallelism

3.4 Why "move" semantics?

Ownership is tracked at compile time, so asset bugs become compile errors rather than exploits.

let a = coin;      // `coin` is MOVED into `a`; `coin` can no longer be used
let b = a;         // moved again
// let c = a;      // ERROR: use of moved value
transfer::public_transfer(b, recipient); // consumed