Aptos Global Storage

In Aptos (and Diem/Movement), global storage is a map from (address, resource type) to a value:

26.1 The model

In Aptos (and Diem/Movement), global storage is a map from (address, resource type) to a value:

Each address can hold at most one resource of each type. A resource type must have key. Only the module that defines the type can perform storage operations on it.

GlobalStorage = Map<(address, StructType), value>

26.2 Storage operators

Effect / aborts move_to<T>(&signer, T) Publish T under the signer's address Aborts if T already exists there move_from<T>(addr): T Remove and return T Aborts if missing borrow_global<T>(addr): &T borrow_global_mut<T>(addr): &mut T exists<T>(addr): bool

Move 2 index: &T[addr], &mut T[addr], T[addr].field Sugar for borrow_global(_mut)

Note that move_to requires a &signer — you can only publish into an account that authorized the transaction (or for which you hold a signer from an object/resource-account capability). Reads (borrow_global, exists) work on any address.

26.3 A complete example: a simple bank of notes

module my_addr::notes {
    use std::signer;
    use std::string::String;
    use std::vector;
    use std::error;

    const E_NOT_INITIALIZED: u64 = 1;
    const E_ALREADY_INITIALIZED: u64 = 2;
    const E_INDEX: u64 = 3;

    struct NoteBook has key {
        notes: vector<String>,
    }

    public entry fun init_notebook(account: &signer) {
        let addr = signer::address_of(account);
        assert!(!exists<NoteBook>(addr), error::already_exists(E_ALREADY_INITIALIZED));
        move_to(account, NoteBook { notes: vector::empty() });
    }

    public entry fun add_note(account: &signer, note: String) acquires NoteBook {
        let addr = signer::address_of(account);
        assert!(exists<NoteBook>(addr), error::not_found(E_NOT_INITIALIZED));
        let book = &mut NoteBook[addr];              // Move 2 resource indexing
        book.notes.push_back(note);
    }

    public entry fun remove_note(account: &signer, index: u64) acquires NoteBook {
        let addr = signer::address_of(account);
        let book = borrow_global_mut<NoteBook>(addr);  // classic form
        assert!(index < book.notes.length(), error::out_of_range(E_INDEX));
        book.notes.remove(index);
  
…

26.4 Generic resources

struct Vault<phantom CoinType> has key {
    coins: aptos_framework::coin::Coin<CoinType>,
}
// An address can hold Vault<USDC> and Vault<AptosCoin> simultaneously:
// they are distinct types.

26.5 Resource groups

Aptos stores resource groups together in a single storage slot to reduce IO costs. The Object framework uses ObjectGroup:

#[resource_group_member(group = aptos_framework::object::ObjectGroup)]
struct Profile has key { name: String }

26.6 Parallel execution note

Aptos executes transactions optimistically in parallel (Block-STM). Transactions touching the same resource conflict and re-execute. Avoid single global "hot" resources (e.g., one counter everyone writes); prefer per-user resources or aggregators (aptos_framework::aggregator_v2) for concurrent counters such as total supply.