Your First Module
6.1 Sui: a counter object
module counter::counter; is the Move 2024 module label form (no braces needed).
UID, TxContext, object, transfer, and tx_context are implicitly imported in the 2024 edition.
public struct — struct declarations must state their visibility in Move 2024.
Build, publish, and call:
// sources/counter.move
module counter::counter;
/// A shared counter anyone can increment.
public struct Counter has key {
id: UID,
owner: address,
value: u64,
}
/// Create a new counter and share it.
public fun create(ctx: &mut TxContext) {
let counter = Counter {
id: object::new(ctx),
owner: ctx.sender(),
value: 0,
};
transfer::share_object(counter);
}
public fun increment(counter: &mut Counter) {
counter.value = counter.value + 1;
}
public fun value(counter: &Counter): u64 {
counter.value
}
/// Only the owner may reset.
public fun reset(counter: &mut Counter, ctx: &TxContext) {
assert!(counter.owner == ctx.sender(), 0);
counter.value = 0;
}sui move build
sui client publish
# copy the package ID from the output, then:
sui client call --package 0xPKG --module counter --function create
sui client call --package 0xPKG --module counter --function increment --args 0xCOUNTER6.2 Aptos: a counter resource
// sources/counter.move
module my_addr::counter {
use std::signer;
struct Counter has key {
value: u64,
}
const E_ALREADY_EXISTS: u64 = 1;
const E_NOT_FOUND: u64 = 2;
public entry fun create(account: &signer) {
let addr = signer::address_of(account);
assert!(!exists<Counter>(addr), E_ALREADY_EXISTS);
move_to(account, Counter { value: 0 });
}
public entry fun increment(account: &signer) acquires Counter {
let addr = signer::address_of(account);
assert!(exists<Counter>(addr), E_NOT_FOUND);
let counter = borrow_global_mut<Counter>(addr);
counter.value = counter.value + 1;
}
#[view]
public fun value(addr: address): u64 acquires Counter {
borrow_global<Counter>(addr).value
}
}aptos move compile --named-addresses my_addr=default
aptos move publish --named-addresses my_addr=default
aptos move run --function-id default::counter::create
aptos move run --function-id default::counter::increment
aptos move view --function-id default::counter::value --args address:default6.3 What is different?
| | Sui | Aptos | |-|-----|-------| | Where data lives | Counter is a standalone shared object | Counter lives under the creator's account | | Who can increment | Anyone with the object ID (it is shared) | Only the account (needs its &signer) | | Identity | id: UID field required | Identified by (address, type) | | Read-only queries | Read object via RPC/SDK, or devInspect | #[view] functions | | Module syntax | Module label module a::b; | Block module a::b { ... } |