← Back to list

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
