Aptos Objects & Resource Accounts

Account-based storage ties data to a user account.

27.1 Why objects?

Account-based storage ties data to a user account. The Object framework (0x1::object, 2023+) creates standalone addresses that hold resources, have an owner, can be transferred, and can be composed (objects owning objects). Fungible assets and digital assets (NFTs) are built on it.

27.2 Creating objects and refs

module my_addr::pets {
    use std::signer;
    use std::string::String;
    use aptos_framework::object::{Self, Object, ConstructorRef, ExtendRef, TransferRef, DeleteRef};

    #[resource_group_member(group = aptos_framework::object::ObjectGroup)]
    struct Pet has key {
        name: String,
        level: u64,
        extend_ref: ExtendRef,
        transfer_ref: TransferRef,
        delete_ref: DeleteRef,
    }

    public entry fun mint(owner: &signer, name: String) {
        let constructor_ref: ConstructorRef = object::create_object(signer::address_of(owner));
        let obj_signer = object::generate_signer(&constructor_ref);
        move_to(&obj_signer, Pet {
            name,
            level: 1,
            extend_ref: object::generate_extend_ref(&constructor_ref),
            transfer_ref: object::generate_transfer_ref(&constructor_ref),
            delete_ref: object::generate_delete_ref(&constructor_ref),
        });
    }

    public entry fun level_up(owner: &signer, pet: Object<Pet>) acquires Pet {
        assert!(object::is_owner(pet, signer::address_of(owner)), 1);
        let p = borrow_global_mut<Pet>(object::object_address(&pet));
        p.level = p.level + 
…

27.3 Object creation functions

Unique, derived from a GUID object::create_named_object(&creator, seed) Deterministic from creator + seed

Singletons, collections, well-known config Objects that must persist

27.4 Refs = capabilities

ConstructorRef exists only during creation; from it you generate long-lived refs:

Get the object's signer later (object::generate_signer_for_extending) to add resources or act as the object

Transfer regardless of owner; disable/enable ungated transfer (soulbound) Delete the object One-time transfer authorization Create derived objects

Object<T> is a typed handle (copy, drop, store) to an object address known to hold T. Entry functions can take Object<T> parameters directly.

27.5 Resource accounts (legacy pattern)

Before objects, protocols used resource accounts — accounts without a private key, controlled by a SignerCapability:

init_module(&signer) runs once when a module is first published (the Aptos analogue of Sui's init). New code should prefer objects with ExtendRef over resource accounts.

use aptos_framework::account::{Self, SignerCapability};

struct ModuleData has key { signer_cap: SignerCapability }

fun init_module(deployer: &signer) {
    let (resource_signer, signer_cap) = account::create_resource_account(deployer, b"seed");
    // resource_signer can move_to resources into the resource account
    move_to(deployer, ModuleData { signer_cap });
}

fun get_resource_signer(): signer acquires ModuleData {
    account::create_signer_with_capability(&borrow_global<ModuleData>(@my_addr).signer_cap)
}