Skip to main content

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?

StepEVM (Solidity)SVM (Rust/Anchor)Move (Sui)
1. InstallNode + Foundry (2 min)Rust + Solana CLI + Anchor (10 min)Rust + Sui CLI (5 min)
2. IDEHardhat LSP, Foundry extensionrust-analyzer (excellent)Move Analyzer VSCode extension
3. Browser IDERemix (zero install)Solana PlaygroundNone (CLI required)
4. First contractforge init → edit .solforge testanchor init → edit lib.rsanchor testsui move new → edit .movesui move test
5. Mental modelGlobal state + msg.senderAccounts + PDAs + CPIsObjects + ownership + capabilities
6. Deployforge script --broadcastanchor deploysui client publish
7. Frontendethers.js / viem + wagmi@solana/web3.js + wallet-adapter@mysten/sui + dApp Kit
8. Wallet connectMetaMask / WalletConnectPhantom / wallet-adapter-reactSui Wallet + zkLogin (seedless)
9. Test in contract languageYes (Foundry)No (TypeScript separate)Yes (Move #[test])
10. Time to "it works"HoursDaysHours (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
ToolPurpose
Sui CLIBuild, test, publish, interact
Move AnalyzerVSCode LSP for Move syntax
sui move testBuilt-in test runner (tests written in Move)
Move ProverFormal verification of contracts
SuiScanBlock explorer (suiscan.xyz)

Compared To

ConcernEVMSVMSui
Package managerFoundry remappings / npmCargo + Anchor.tomlMove.toml (built-in)
Local networkAnvil (fork mainnet)solana-test-validatorsui start (local network)
Formal verificationCertora, HalmosTrident (early)Move Prover (mature)

Core Concepts

Objects vs Accounts

The fundamental difference. EVM and Solana use account-based models. Sui uses objects.

ConceptEVMSVMSui
State unitStorage slot in contractAccount (data + owner)Object (ID + type + owner + data)
OwnershipImplicit (mapping balances)Program-derived (PDA)Explicit (object field)
TransferUpdate balance mappingChange account ownerMove object to new address
ParallelismSequential (global state)Implicit (Sealevel)Explicit (disjoint object sets)
Identitymsg.senderSigner accounttx_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

StandardEVMSVMSui
FungibleERC-20 (interface)SPL Token / Token-2022sui::coin (module)
Non-fungibleERC-721 (interface)Metaplex NFT standardAny object with key ability
Semi-fungibleERC-1155SPL Token-2022Composable objects
ApproachStandard interface, any implementationProgram accountsObjects 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 concernEVMSVMSui
Unit testsFoundry (Solidity)Rust #[test] + BanksClientMove #[test] + test_scenario
IntegrationFork tests (Anvil)TypeScript + anchor testPTB simulation (dry-run)
FuzzingFoundry built-in, EchidnaTrident (early)Move Prover, Belobog
Formal verificationCertora (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

ConcernEVMSVMSui
SDKethers.js / viem@solana/web3.js@mysten/sui
React hookswagmiwallet-adapter-react@mysten/dapp-kit
Wallet connectWalletConnect / MetaMaskPhantom adapterSui Wallet + zkLogin
Seedless onboardingERC-4337 (complex)None (native)zkLogin (protocol-level)
Sponsored transactionsERC-4337 paymasterNone (native)Built-in gas sponsorship
Transaction previewSimulation via RPCSimulation via RPCPTB 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:

VulnerabilityEVMSVMSui
Re-entrancyYou prevent (guards)Runtime prevents (CPI depth)Compiler prevents (no recursive calls)
Asset duplicationYou prevent (accounting)Runtime prevents (slot checks)Compiler prevents (linear types)
Access controlYou prevent (modifiers)You prevent (signer checks)Compiler prevents (capabilities)
OverflowAuto-checked (0.8+)Debug: panic, Release: wrapAlways checked (bytecode verifier)
Dangling referencesN/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 concernEVMSVMSui
Deploy costGas-dependent (can be expensive)~2 SOL rentLow (storage fund model)
UpgradeabilityProxy pattern (complex)anchor upgradesui client upgrade (policy-controlled)
Finality~15 min (mainnet)~13s economic~390ms (Mysticeti)
ImmutabilityOptional (proxy defeats it)Upgradeable by defaultConfigurable 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

PackageStatusObjectsWhat It Does
identityDeployed (devnet)Identity, AttestationProof-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.
linkDeployed (devnet)Link, AttributionRuleProvable 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.
collisionTestedCollisionInteraction 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.
mandateTestedIntentMandate, CartMandateAP2 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.
loyaltyIn devLoyaltyAccount, PointsTransactionPoints accrual and redemption linked to link interactions. Cross-module composition (identity + link → loyalty).
depin_coreIn devProtocolConfig, ProtocolStatsProtocol kernel — version, admin, min_stake, reward_rate, slash_rate. Pause/resume, admin transfer, device/reward tracking. 242 lines.

DePIN Infrastructure

PackageStatusObjectsWhat It Does
device_registryIn devDevice, DeviceCapability, LocationIoT 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_agricultureIn devFarm, AgriculturalSensor, WeatherPrediction, YieldPrediction, CropInsuranceFarm 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_citySource onlyCityZoneUrban infrastructure monitoring. 6 zone types (residential, commercial, industrial, transport, green, mixed). Traffic, air quality, noise, energy, water, waste metrics.

Economic Layer

PackageStatusObjectsWhat It Does
governanceStubDAOBasic DAO struct with proposal counting. 17 lines — placeholder.
incentivesStubRewardPoolReward pool with total_rewards tracking. 18 lines — placeholder.
tokenomics_validationTestedMathematical proofs of economic correctness. Attribution percentages sum to 100. Value distribution conservation. Tests with real-world token pools (1M tokens).
test_frameworkUtilityProperty-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

PackageStatusWhat It Does
experiments/led_controlPrototypeLED device control on-chain. On/off, brightness 0-255, RGB color. Toggle/set commands with duration. IoT hello-world.
cross_chain_bridgeSource onlyMulti-chain asset bridging. BridgeConfig with operator/validator set. 5 asset types (native, NFTs, DePIN rewards, insurance claims, yield tokens). Liquidity pool management.

Deployment

PackageNetworkDateAddress
identityDevnet2025-12-07Deployed
linkDevnet2025-12-070xbcf8d...fba01
collisionDevnet2025-12-070xbcf8d...fba01 (same package)

Design Patterns

PatternWhere UsedWhat It Proves
Module dependency layeringidentity → link/mandate/loyalty → collision → tokenomicsComposable protocol stack
Event emitters on all state changesAll production modulesIndexer-friendly, auditable
Systematic error codes100s, 200s, 300s, 400s, 500s per moduleMachine-parseable errors
Shared vs owned objectsmandate uses share_object; link uses transferCross-party vs single-owner patterns
test_scenario multi-tx testscollision, mandate, tokenomicsRealistic transaction sequences
Capability patternidentity (AdminCap), depin_coreCompiler-enforced access control

TypeScript Clients

ClientOperations
IdentityClientCreate/update identity, add attestations, query by type
LinksClientCreate links, track attribution chains, compute decay
LoyaltyClientEarn/redeem points, query transaction history
DeviceRegistryClientRegister/transfer devices, update firmware, query by type
CollisionClientDetect attribution collisions

React Safety Components

ComponentWhat It Prevents
ZkLoginConnectWallet installation friction (OAuth → Sui address)
DestructiveOpGateAccidental irreversible actions (countdown + typed confirmation + nuclear warning)
TransferPreviewBlind signing (PTB dry-run shows exact mutations)
CooldownTransferPanic-click transfers (time-gated)
PreDestructionInventoryHidden asset loss (enumerate before destroy)
ValueAtRiskUnaware exposure (balance summary dashboard)
GasEstimateGas surprise (PTB cost preview)
SponsoredSessionGas 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:

VerticalOur PackagesRFP FitReadiness
DePIN + IoTdevice_registry, depin_core, precision_agriculture, smart_cityDevice identity, data verification, reward distribution on SuiCore protocol deployed. Two verticals prototyped.
Agent Commercemandate, identityAP2-compatible agent payments. AI agents with verified identity placing orders on behalf of users.Identity deployed. Mandate tested with happy path.
Attribution + Loyaltylink, collision, loyalty, tokenomics_validationProvable 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 ConceptMandate ModuleDifference
L1 Identityidentity module — 4 entity types, attestation providersCompiler-enforced via capabilities, not SD-JWT
L2 IntentIntentMandate — budget, items, constraintsOn-chain object with explicit ownership
L3 ActionCartMandate — merchant counter-offerShared object for cross-party coordination
VerificationStatus flow: Open → Fulfilled → CancelledMove's type system prevents invalid transitions
Constraint enforcementBudget field + agent identity checkCompiler 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

StepResourceTime
1. Move basicsMove Book1-2 days
2. Sui objectsSui Docs — Object Model1 day
3. First packageCreate Sui dAppHalf day
4. PTBsSui Docs — PTBsHalf day
5. TestingSui Move Test1 day
6. FrontenddApp Kit1 day
7. DeployTestnet → MainnetHalf day

Dig Deeper

DirectoryWhat Goes HereEVM Equivalent
PlatformSui runtime — objects, Mysticeti consensus, storage model, parallel executionThe EVM
StandardsSui Coin, object types, PTBs, zkLogin patternsERC Standards
PatternsMove design patterns — DePIN, DeFi, attribution, agent commerceEVM Patterns
ProtocolsProtocol integrations — Walrus, Seal, Nautilus, AP2EVM Protocols
AuditingMove Prover, testing strategies, vulnerability classesEVM Auditing

Context

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"?