Sui Move Development
What does it feel like to onboard as a developer — and how does that compare to EVM and Solana?
The parent comparison scores the platforms on safety, onboarding, speed, composability, and ecosystem. This page walks the actual onboarding path — environment, first contract, testing, frontend, deployment — so you can feel the difference rather than read about it.
Onboarding Comparison
The same developer journey across three platforms. Where does each one create friction, and where does it disappear?
| Step | EVM (Solidity) | SVM (Rust/Anchor) | Move (Sui) |
|---|---|---|---|
| 1. Install | Node + Foundry (2 min) | Rust + Solana CLI + Anchor (10 min) | Rust + Sui CLI (5 min) |
| 2. IDE | Hardhat LSP, Foundry extension | rust-analyzer (excellent) | Move Analyzer VSCode extension |
| 3. Browser IDE | Remix (zero install) | Solana Playground | None (CLI required) |
| 4. First contract | forge init → edit .sol → forge test | anchor init → edit lib.rs → anchor test | sui move new → edit .move → sui move test |
| 5. Mental model | Global state + msg.sender | Accounts + PDAs + CPIs | Objects + ownership + capabilities |
| 6. Deploy | forge script --broadcast | anchor deploy | sui client publish |
| 7. Frontend | ethers.js / viem + wagmi | @solana/web3.js + wallet-adapter | @mysten/sui + dApp Kit |
| 8. Wallet connect | MetaMask / WalletConnect | Phantom / wallet-adapter-react | Sui Wallet + zkLogin (seedless) |
| 9. Test in contract language | Yes (Foundry) | No (TypeScript separate) | Yes (Move #[test]) |
| 10. Time to "it works" | Hours | Days | Hours (once mental model clicks) |
The bottleneck is step 5. EVM's mental model is familiar (global state, like a database). Solana's account model is genuinely hard (PDAs, account validation, CPI depth limits). Sui's object model is novel but intuitive once you see that objects ARE the things they represent — a coin is an object you own, not a balance in someone else's ledger.
Environment Setup
# Install Sui CLI (requires Rust)
cargo install --locked --git https://github.com/MystenLabs/sui.git --branch devnet sui
# Verify
sui --version
# Create new project
sui move new my_project
cd my_project
# Run tests
sui move test
# Connect to network
sui client new-env --alias devnet --rpc https://fullnode.devnet.sui.io:443
sui client switch --env devnet
sui client faucet # get test tokens
| Tool | Purpose |
|---|---|
| Sui CLI | Build, test, publish, interact |
| Move Analyzer | VSCode LSP for Move syntax |
| sui move test | Built-in test runner (tests written in Move) |
| Move Prover | Formal verification of contracts |
| SuiScan | Block explorer (suiscan.xyz) |
Compared To
| Concern | EVM | SVM | Sui |
|---|---|---|---|
| Package manager | Foundry remappings / npm | Cargo + Anchor.toml | Move.toml (built-in) |
| Local network | Anvil (fork mainnet) | solana-test-validator | sui start (local network) |
| Formal verification | Certora, Halmos | Trident (early) | Move Prover (mature) |
Core Concepts
Objects vs Accounts
The fundamental difference. EVM and Solana use account-based models. Sui uses objects.
| Concept | EVM | SVM | Sui |
|---|---|---|---|
| State unit | Storage slot in contract | Account (data + owner) | Object (ID + type + owner + data) |
| Ownership | Implicit (mapping balances) | Program-derived (PDA) | Explicit (object field) |
| Transfer | Update balance mapping | Change account owner | Move object to new address |
| Parallelism | Sequential (global state) | Implicit (Sealevel) | Explicit (disjoint object sets) |
| Identity | msg.sender | Signer account | tx_context::sender() + zkLogin |
Object Types
Owned Object → Single owner, fast path (no consensus needed)
Shared Object → Multiple writers, full consensus
Immutable Object → Published packages, constants
Programmable Transaction Blocks
One transaction, up to 1024 operations, with data flowing between them. No equivalent in EVM or Solana at this scale.
PTB:
1. Split coin → coin_a, coin_b
2. Transfer coin_a → recipient
3. Deposit coin_b → DeFi pool
4. Mint receipt NFT from pool
→ All atomic. All in ~390ms.
First Contract
Hello World (Counter)
module hello::counter {
/// A counter object owned by a single address
public struct Counter has key, store {
id: UID,
value: u64,
}
/// Create a new counter, transfer to sender
public fun create(ctx: &mut TxContext) {
let counter = Counter {
id: object::new(ctx),
value: 0,
};
transfer::transfer(counter, tx_context::sender(ctx));
}
/// Increment the counter
public fun increment(counter: &mut Counter) {
counter.value = counter.value + 1;
}
/// Read the value
public fun value(counter: &Counter): u64 {
counter.value
}
#[test]
fun test_counter() {
use sui::test_scenario;
let owner = @0xA;
let mut scenario = test_scenario::begin(owner);
// Create counter
test_scenario::next_tx(&mut scenario, owner);
{
create(test_scenario::ctx(&mut scenario));
};
// Increment and verify
test_scenario::next_tx(&mut scenario, owner);
{
let mut counter = test_scenario::take_from_sender<Counter>(&scenario);
increment(&mut counter);
assert!(value(&counter) == 1, 0);
test_scenario::return_to_sender(&scenario, counter);
};
test_scenario::end(scenario);
}
}
Compared To
EVM equivalent: uint256 public counter; function increment() public { counter++; } — simpler syntax, but the counter lives in contract storage, not as an owned object. Anyone can call increment. Access control is opt-in.
Solana equivalent: Define account struct, derive PDA, validate accounts in instruction handler, serialize/deserialize. ~3x more boilerplate for the same result because the account model requires explicit validation at every step.
Sui difference: The counter IS an object. Ownership is structural. Only the owner can pass &mut Counter. The compiler enforces what EVM and Solana enforce at runtime (or don't).
Token Standards
| Standard | EVM | SVM | Sui |
|---|---|---|---|
| Fungible | ERC-20 (interface) | SPL Token / Token-2022 | sui::coin (module) |
| Non-fungible | ERC-721 (interface) | Metaplex NFT standard | Any object with key ability |
| Semi-fungible | ERC-1155 | SPL Token-2022 | Composable objects |
| Approach | Standard interface, any implementation | Program accounts | Objects with abilities |
In Sui, there's no separate "NFT standard" because every object with key is already uniquely identified, owned, and transferable. The object model IS the standard.
/// A Sui coin is just a typed wrapper around a balance
public struct Coin<phantom T> has key, store {
id: UID,
balance: Balance<T>,
}
Testing
Tests live in the same language as contracts. No context switching.
#[test]
fun test_transfer() {
use sui::test_scenario;
let sender = @0xA;
let recipient = @0xB;
let mut scenario = test_scenario::begin(sender);
// Create and transfer
test_scenario::next_tx(&mut scenario, sender);
{
let coin = coin::mint_for_testing<SUI>(1000, test_scenario::ctx(&mut scenario));
transfer::public_transfer(coin, recipient);
};
// Verify recipient received it
test_scenario::next_tx(&mut scenario, recipient);
{
let coin = test_scenario::take_from_sender<Coin<SUI>>(&scenario);
assert!(coin::value(&coin) == 1000, 0);
test_scenario::return_to_sender(&scenario, coin);
};
test_scenario::end(scenario);
}
| Testing concern | EVM | SVM | Sui |
|---|---|---|---|
| Unit tests | Foundry (Solidity) | Rust #[test] + BanksClient | Move #[test] + test_scenario |
| Integration | Fork tests (Anvil) | TypeScript + anchor test | PTB simulation (dry-run) |
| Fuzzing | Foundry built-in, Echidna | Trident (early) | Move Prover, Belobog |
| Formal verification | Certora (expensive) | None (production) | Move Prover (built-in, free) |
Move Prover is the differentiator. Formal verification is built into the toolchain, not a $50K+ audit add-on.
Frontend Integration
dApp Kit
import { ConnectButton, useCurrentAccount, useSuiClient } from '@mysten/dapp-kit';
import { Transaction } from '@mysten/sui/transactions';
function App() {
const account = useCurrentAccount();
const client = useSuiClient();
const incrementCounter = async () => {
const tx = new Transaction();
tx.moveCall({
target: `${PACKAGE_ID}::counter::increment`,
arguments: [tx.object(COUNTER_ID)],
});
// Sign and execute via connected wallet
};
return (
<div>
<ConnectButton />
{account && <button onClick={incrementCounter}>Increment</button>}
</div>
);
}
Compared To
| Concern | EVM | SVM | Sui |
|---|---|---|---|
| SDK | ethers.js / viem | @solana/web3.js | @mysten/sui |
| React hooks | wagmi | wallet-adapter-react | @mysten/dapp-kit |
| Wallet connect | WalletConnect / MetaMask | Phantom adapter | Sui Wallet + zkLogin |
| Seedless onboarding | ERC-4337 (complex) | None (native) | zkLogin (protocol-level) |
| Sponsored transactions | ERC-4337 paymaster | None (native) | Built-in gas sponsorship |
| Transaction preview | Simulation via RPC | Simulation via RPC | PTB dry-run (1024 ops visible) |
zkLogin removes the wallet installation barrier entirely. Users sign in with Google/Apple, a ZK proof maps their OAuth credential to a Sui address. No seed phrase, no extension, no onboarding friction.
Security Patterns
What the compiler prevents vs what you must prevent yourself:
| Vulnerability | EVM | SVM | Sui |
|---|---|---|---|
| Re-entrancy | You prevent (guards) | Runtime prevents (CPI depth) | Compiler prevents (no recursive calls) |
| Asset duplication | You prevent (accounting) | Runtime prevents (slot checks) | Compiler prevents (linear types) |
| Access control | You prevent (modifiers) | You prevent (signer checks) | Compiler prevents (capabilities) |
| Overflow | Auto-checked (0.8+) | Debug: panic, Release: wrap | Always checked (bytecode verifier) |
| Dangling references | N/A (no references) | Borrow checker (Rust) | Borrow checker (Move) |
Capability Pattern
/// Only the holder of AdminCap can call admin functions
public struct AdminCap has key, store {
id: UID,
}
/// This function cannot be called without possessing AdminCap
public fun admin_action(cap: &AdminCap, /* ... */) {
// AdminCap is the proof of authorization
// No runtime check needed — if you have it, you're authorized
}
Compare to Solidity's onlyOwner modifier (convention, not enforcement) or Solana's manual require!(ctx.accounts.authority.key() == expected) (runtime check you might forget).
Deployment
# Build
sui move build
# Publish to devnet (get package ID back)
sui client publish --gas-budget 100000000
# Interact
sui client call \
--package $PACKAGE_ID \
--module counter \
--function create \
--gas-budget 10000000
| Deployment concern | EVM | SVM | Sui |
|---|---|---|---|
| Deploy cost | Gas-dependent (can be expensive) | ~2 SOL rent | Low (storage fund model) |
| Upgradeability | Proxy pattern (complex) | anchor upgrade | sui client upgrade (policy-controlled) |
| Finality | ~15 min (mainnet) | ~13s economic | ~390ms (Mysticeti) |
| Immutability | Optional (proxy defeats it) | Upgradeable by default | Configurable per package |
What We Built
16 Move packages, TypeScript SDK clients, and React safety components. Two packages deployed to devnet. Deployed at drmg-design-system.vercel.app.
~4,000 lines of production Move code. ~1,000+ lines of tests. Two complete test suites (collision: 644 lines, tokenomics: 80 lines).
Core Protocol
| Package | Status | Objects | What It Does |
|---|---|---|---|
| identity | Deployed (devnet) | Identity, Attestation | Proof-of-personhood with 4 entity types (Pseudonymous, Human Verified, AI Agent, Collective). Attestation providers (Gitcoin Passport, Worldcoin, Civic) issue confidence scores 0-100 with expiration. 327 lines. |
| link | Deployed (devnet) | Link, AttributionRule | Provable attribution chains with genealogy (parent/embedded links). 4 decay functions (none, linear, exponential, step). Creator/parent/platform revenue splits. Depends on identity module. 459 lines. |
| collision | Tested | Collision | Interaction tracking between identities for attribution graphs. Quality scoring (0-100) from positive/negative reactions. Spam detection (>3 flags + more flags than positives). Value attribution on conversion. Most tested module — 644 lines of tests covering 30+ scenarios. ~500 lines production. |
| mandate | Tested | IntentMandate, CartMandate | AP2 agent payments. IntentMandate = user/agent purchasing intent with budget. CartMandate = merchant counter-offer with items. Status flows: Intent (Open→Fulfilled→Cancelled), Cart (Proposed→Approved→Rejected). Agent identity verified via identity module (requires AI Agent entity type). 253 lines + 95 lines tests. |
| loyalty | In dev | LoyaltyAccount, PointsTransaction | Points accrual and redemption linked to link interactions. Cross-module composition (identity + link → loyalty). |
| depin_core | In dev | ProtocolConfig, ProtocolStats | Protocol kernel — version, admin, min_stake, reward_rate, slash_rate. Pause/resume, admin transfer, device/reward tracking. 242 lines. |
DePIN Infrastructure
| Package | Status | Objects | What It Does |
|---|---|---|---|
| device_registry | In dev | Device, DeviceCapability, Location | IoT device lifecycle. 5 types (Sensor, Actuator, Gateway, Compute, Storage), 4 states (Active, Inactive, Maintenance, Decommissioned). GPS location, stake/reputation, operator role separation from owner. 402 lines. |
| precision_agriculture | In dev | Farm, AgriculturalSensor, WeatherPrediction, YieldPrediction, CropInsurance | Farm IoT network. Soil moisture, temperature, humidity, light, pH, nitrogen, wind, rainfall sensors. AI-driven yield forecasting with confidence intervals. Insurance with risk calculation from weather data. 475 lines — most substantial vertical. |
| smart_city | Source only | CityZone | Urban infrastructure monitoring. 6 zone types (residential, commercial, industrial, transport, green, mixed). Traffic, air quality, noise, energy, water, waste metrics. |
Economic Layer
| Package | Status | Objects | What It Does |
|---|---|---|---|
| governance | Stub | DAO | Basic DAO struct with proposal counting. 17 lines — placeholder. |
| incentives | Stub | RewardPool | Reward pool with total_rewards tracking. 18 lines — placeholder. |
| tokenomics_validation | Tested | — | Mathematical proofs of economic correctness. Attribution percentages sum to 100. Value distribution conservation. Tests with real-world token pools (1M tokens). |
| test_framework | Utility | — | Property-based testing for all modules. Attribution scenarios, quality score properties, value conservation, spam detection monotonicity, reputation bounds [0-100], token supply conservation. 437 lines. |
Experiments
| Package | Status | What It Does |
|---|---|---|
| experiments/led_control | Prototype | LED device control on-chain. On/off, brightness 0-255, RGB color. Toggle/set commands with duration. IoT hello-world. |
| cross_chain_bridge | Source only | Multi-chain asset bridging. BridgeConfig with operator/validator set. 5 asset types (native, NFTs, DePIN rewards, insurance claims, yield tokens). Liquidity pool management. |
Deployment
| Package | Network | Date | Address |
|---|---|---|---|
| identity | Devnet | 2025-12-07 | Deployed |
| link | Devnet | 2025-12-07 | 0xbcf8d...fba01 |
| collision | Devnet | 2025-12-07 | 0xbcf8d...fba01 (same package) |
Design Patterns
| Pattern | Where Used | What It Proves |
|---|---|---|
| Module dependency layering | identity → link/mandate/loyalty → collision → tokenomics | Composable protocol stack |
| Event emitters on all state changes | All production modules | Indexer-friendly, auditable |
| Systematic error codes | 100s, 200s, 300s, 400s, 500s per module | Machine-parseable errors |
| Shared vs owned objects | mandate uses share_object; link uses transfer | Cross-party vs single-owner patterns |
test_scenario multi-tx tests | collision, mandate, tokenomics | Realistic transaction sequences |
| Capability pattern | identity (AdminCap), depin_core | Compiler-enforced access control |
TypeScript Clients
| Client | Operations |
|---|---|
| IdentityClient | Create/update identity, add attestations, query by type |
| LinksClient | Create links, track attribution chains, compute decay |
| LoyaltyClient | Earn/redeem points, query transaction history |
| DeviceRegistryClient | Register/transfer devices, update firmware, query by type |
| CollisionClient | Detect attribution collisions |
React Safety Components
| Component | What It Prevents |
|---|---|
| ZkLoginConnect | Wallet installation friction (OAuth → Sui address) |
| DestructiveOpGate | Accidental irreversible actions (countdown + typed confirmation + nuclear warning) |
| TransferPreview | Blind signing (PTB dry-run shows exact mutations) |
| CooldownTransfer | Panic-click transfers (time-gated) |
| PreDestructionInventory | Hidden asset loss (enumerate before destroy) |
| ValueAtRisk | Unaware exposure (balance summary dashboard) |
| GasEstimate | Gas surprise (PTB cost preview) |
| SponsoredSession | Gas barrier for new users (app covers gas) |
See Wallet Safety Benchmarks for the 5-dimension certification framework these components implement.
RFP Alignment
The Sui Foundation RFP program funds specific projects advancing the ecosystem. Our Move codebase maps to three RFP-relevant verticals:
| Vertical | Our Packages | RFP Fit | Readiness |
|---|---|---|---|
| DePIN + IoT | device_registry, depin_core, precision_agriculture, smart_city | Device identity, data verification, reward distribution on Sui | Core protocol deployed. Two verticals prototyped. |
| Agent Commerce | mandate, identity | AP2-compatible agent payments. AI agents with verified identity placing orders on behalf of users. | Identity deployed. Mandate tested with happy path. |
| Attribution + Loyalty | link, collision, loyalty, tokenomics_validation | Provable content attribution, creator economics, cross-platform loyalty. | Attribution chain deployed. Economic proofs validated. |
What the Foundation looks for: expertise, community engagement, defined scope, realistic budget, execution track record, compliance. Our deployed devnet packages and test suites demonstrate execution. The business factory thesis — standard interfaces that agents compose into ventures — aligns with Sui's "empowering builders" principle.
The gap: Mainnet deployment, audit readiness, and user-facing demos. The precision agriculture vertical (475 lines, insurance + predictions) is closest to a complete RFP submission — it has a clear domain, measurable outcomes, and multiple DePIN primitives working together.
See Sui Business Development for the full strategic analysis and Priorities for build order.
Verifiable Intent
The mandate module is a Sui-native implementation of Verifiable Intent — the open spec (Mastercard + Google) for cryptographic proof that agent actions match human-approved scope.
| VI Concept | Mandate Module | Difference |
|---|---|---|
| L1 Identity | identity module — 4 entity types, attestation providers | Compiler-enforced via capabilities, not SD-JWT |
| L2 Intent | IntentMandate — budget, items, constraints | On-chain object with explicit ownership |
| L3 Action | CartMandate — merchant counter-offer | Shared object for cross-party coordination |
| Verification | Status flow: Open → Fulfilled → Cancelled | Move's type system prevents invalid transitions |
| Constraint enforcement | Budget field + agent identity check | Compiler prevents unauthorized access |
Key difference: VI uses SD-JWT delegation chains (runtime cryptographic verification). Move uses linear types and capabilities (compile-time structural enforcement). Move eliminates classes of bugs that SD-JWT can't — you literally cannot write code that bypasses the authorization, because the compiler won't let you.
The bridge: A Sui-native VI implementation could use Move's capability pattern for on-chain enforcement while emitting SD-JWT credentials for off-chain verification — giving both compile-time safety AND cross-protocol interoperability. See Safety comparison.
Learning Path
| Step | Resource | Time |
|---|---|---|
| 1. Move basics | Move Book | 1-2 days |
| 2. Sui objects | Sui Docs — Object Model | 1 day |
| 3. First package | Create Sui dApp | Half day |
| 4. PTBs | Sui Docs — PTBs | Half day |
| 5. Testing | Sui Move Test | 1 day |
| 6. Frontend | dApp Kit | 1 day |
| 7. Deploy | Testnet → Mainnet | Half day |
Dig Deeper
| Directory | What Goes Here | EVM Equivalent |
|---|---|---|
| Platform | Sui runtime — objects, Mysticeti consensus, storage model, parallel execution | The EVM |
| Standards | Sui Coin, object types, PTBs, zkLogin patterns | ERC Standards |
| Patterns | Move design patterns — DePIN, DeFi, attribution, agent commerce | EVM Patterns |
| Protocols | Protocol integrations — Walrus, Seal, Nautilus, AP2 | EVM Protocols |
| Auditing | Move Prover, testing strategies, vulnerability classes | EVM Auditing |
Context
- Smart Contract Comparison — Safety, onboarding, speed, composability, ecosystem across EVM/SVM/Move
- EVM Development — Solidity onboarding path — the structural pattern we follow
- Solana Development — SVM onboarding path
- Sui Business Development — Strategic analysis, RFP opportunity, 5Ps scoring
- Sui Technical — Object model, Mysticeti consensus, agent economy primitives
- Agent Commerce — AP2 standard — Google chose Sui as launch partner
- Business Factory — The thesis: standard interfaces that agents compose into ventures
- Wallet Safety Benchmarks — 5-dimension safety certification framework
- Developer Experience — DX as northstar for crypto adoption
Links
- Move Book — Canonical Move language reference
- Sui Docs — Official developer documentation
- Sui Foundation RFP — Grant funding for ecosystem projects
- dApp Kit — React SDK for Sui
- SuiScan — Block explorer
- Move Prover — Formal verification
Questions
Which of the three RFP verticals — DePIN, agent commerce, or attribution — has the shortest path from devnet to a funded proposal?
- The identity module serves all three verticals. What happens when the shared primitive evolves faster than the verticals that depend on it?
- Precision agriculture has the most code (475 lines) but the smallest addressable market on Sui. Is code depth or market fit the better signal for RFP selection?
- The mandate module implements AP2 for agent payments. If Google's AP2 standard wins, does our early Move implementation become a moat or get replaced by an official SDK?
- What's missing between "deployed on devnet with tests" and "ready for Sui Foundation review"?