Back to list
raintree-technology

aptos-object-model

by raintree-technology

Platform-agnostic, production-ready Claude Code configurations with hooks, commands, skills, examples, and more.

34🍴 5📅 Jan 21, 2026

SKILL.md


name: aptos-object-model description: Expert on Aptos Object Model for composable, transferable assets. Covers ObjectCore, Object wrapper, ConstructorRef, ExtendRef, DeleteRef, TransferRef capabilities, object ownership, named vs generated objects, and composability patterns. allowed-tools: Read, Write, Edit, Grep, Glob, Bash model: sonnet license: MIT metadata: author: raintree version: "1.0"

Aptos Object Model Expert

Expert on the Aptos Object Model for building composable, transferable on-chain assets.

Triggers

  • object model, objectcore, Object
  • constructorref, extendref, deleteref, transferref
  • named object, generated object
  • object ownership, composable object
  • soul-bound, nesting

Core Concepts

The Object Model enables:

  • Transferable resources - Objects can move between accounts
  • Composability - Objects can own other objects
  • Lifecycle management - Create, extend, delete via refs
  • Ownership separation - Owner address != object address

ObjectCore

Every object has an ObjectCore:

struct ObjectCore has key {
    owner: address,
    allow_ungated_transfer: bool,
}

Object Wrapper

struct Object<phantom T> has copy, drop, store {
    inner: address  // Pointer to object
}

Object Creation

Named Objects (Deterministic)

let constructor_ref = object::create_named_object(creator, b"SEED");
// Address = hash(creator_address, seed)

Generated Objects (Random)

let constructor_ref = object::create_object(creator);
// Non-deterministic address

Sticky Objects (Cannot Delete)

let constructor_ref = object::create_sticky_object(creator);

References (Capabilities)

ConstructorRef - Master Key (Creation Only)

let constructor_ref = object::create_object(creator);

// Generate all other refs during creation
let extend_ref = object::generate_extend_ref(&constructor_ref);
let transfer_ref = object::generate_transfer_ref(&constructor_ref);
let delete_ref = object::generate_delete_ref(&constructor_ref);
let object_signer = object::generate_signer(&constructor_ref);

// Store refs at object address
move_to(&object_signer, Refs { extend_ref, transfer_ref, delete_ref });

ExtendRef - Access Later

// Get signer after creation
let object_signer = object::generate_signer_for_extending(&refs.extend_ref);

TransferRef - Control Transfers

// Disable transfers (soul-bound)
object::disable_ungated_transfer(&refs.transfer_ref);

// Enable transfers
object::enable_ungated_transfer(&refs.transfer_ref);

// Force transfer
object::transfer_with_ref(&refs.transfer_ref, new_owner);

DeleteRef - Destroy Objects

// Remove all resources first, then delete
let MyResource { value: _ } = move_from<MyResource>(object_addr);
object::delete(delete_ref);

Ownership & Transfer

// Get object info
let object_addr = object::object_address(&obj);
let owner = object::owner(obj);
let transferable = object::ungated_transfer_allowed(obj);

// User transfer (if allowed)
object::transfer(owner, obj, new_owner);

Common Patterns

Soul-Bound Token

public fun create_sbt(creator: &signer, recipient: address) {
    let constructor_ref = token::create_named_token(...);
    
    let transfer_ref = object::generate_transfer_ref(&constructor_ref);
    object::disable_ungated_transfer(&transfer_ref);
    
    // One-time transfer to recipient
    let linear_ref = object::generate_linear_transfer_ref(&transfer_ref);
    object::transfer_with_ref(linear_ref, recipient);
    
    // Don't store transfer_ref - permanently non-transferable
}

Composable NFT (Nesting)

// Create parent
let parent_ref = token::create_named_token(...);
let parent_addr = object::address_from_constructor_ref(&parent_ref);

// Create child owned by parent
let child_ref = token::create_named_token(...);
let transfer_ref = object::generate_transfer_ref(&child_ref);
let linear_ref = object::generate_linear_transfer_ref(&transfer_ref);
object::transfer_with_ref(linear_ref, parent_addr);

Singleton/Registry

public fun get_or_create_registry(creator: &signer): address {
    let seed = b"REGISTRY";
    let addr = object::create_object_address(&signer::address_of(creator), seed);
    
    if (!object::object_exists<Registry>(addr)) {
        let ref = object::create_named_object(creator, seed);
        let signer = object::generate_signer(&ref);
        move_to(&signer, Registry { items: simple_map::create() });
    };
    
    addr
}

Upgradeable Module Data

struct DataRefs has key { extend_ref: ExtendRef }

public fun upgrade_config(new_config: Config) acquires DataRefs {
    let refs = borrow_global<DataRefs>(data_addr);
    let signer = object::generate_signer_for_extending(&refs.extend_ref);
    // Modify resources at data_addr
}

Best Practices

  • Store refs at object address, not creator address
  • Generate all needed refs during creation (ConstructorRef is ephemeral)
  • Use named objects for singletons, generated for collections
  • Disable ungated transfer for soul-bound tokens
  • Clean up all resources before deletion
  • Document object ownership hierarchy

Common Errors

"Object does not exist"

assert!(object::object_exists<T>(addr), ERROR);

"Ungated transfer not allowed"

// Use TransferRef for forced transfer
object::transfer_with_ref(&refs.transfer_ref, recipient);

"Object already exists"

// Check existence before creating named object
if (!object::object_exists<ObjectCore>(addr)) {
    object::create_named_object(creator, seed);
}

Score

Total Score

75/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon