<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Daniel</title>
    <description>The latest articles on Forem by Daniel (@danielkestrel).</description>
    <link>https://forem.com/danielkestrel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3205792%2Fa8bfe1e8-9c75-429a-ae38-1eb7378a7a93.png</url>
      <title>Forem: Daniel</title>
      <link>https://forem.com/danielkestrel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/danielkestrel"/>
    <language>en</language>
    <item>
      <title>Understanding Objects in Cedra Move: The Complete Beginner's Guide (Part 1/3)</title>
      <dc:creator>Daniel</dc:creator>
      <pubDate>Fri, 21 Nov 2025 09:25:12 +0000</pubDate>
      <link>https://forem.com/danielkestrel/understanding-objects-in-cedra-move-the-complete-beginners-guide-part-13-2c6o</link>
      <guid>https://forem.com/danielkestrel/understanding-objects-in-cedra-move-the-complete-beginners-guide-part-13-2c6o</guid>
      <description>&lt;p&gt;If you're new to Cedra (Aptos) Move and Objects confuse you, you're absolutely not alone.&lt;br&gt;
Coming from Solidity, Rust, or any traditional smart-contract model, the Object system in Move can feel like an entirely different universe.&lt;/p&gt;

&lt;p&gt;This three-part series breaks everything down step-by-step — what Objects are, why they exist, and how to use them without the confusion. Cedra Move and Aptos Move work the same way, so we’ll use both terms interchangeably.&lt;/p&gt;

&lt;p&gt;Let’s jump straight into today’s topic: why Objects exist and what problem they solve.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Why Objects Even Exist&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First, I'll attempt to define what an Object is in Move:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Objects are containers that hold your data and live at their own address, separate from your account.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In basic Move, when you create &lt;a href="https://dev.to/danielkestrel/understanding-structs-and-abilities-in-move-the-building-blocks-of-aptos-smart-contracts-4hnl"&gt;a struct&lt;/a&gt;, it must live inside someone's account as a resource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct GameItem has key {
    name: vector&amp;lt;u8&amp;gt;,
    power: u64,
}

// this GameItem MUST live in an account
public entry fun create_item(owner: &amp;amp;signer) {
    move_to(owner, GameItem {
        name: b"Sword",
        power: 100,
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates several limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Resources are glued to accounts → hard to transfer ownership&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only one account can own it → no shared ownership&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Either you own it or you don’t → no complex permissions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It's hard to compose -&amp;gt; Can't build on top of others' resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inflexible Storage -&amp;gt; Stuck in the original account forever&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Solution: Objects&lt;/strong&gt;&lt;br&gt;
Objects are smart containers that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Live at their own address (not in user accounts)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Have built-in ownership tracking&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can be transferred like assets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support complex permission models&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow modular composition&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Where Objects Actually Live
&lt;/h2&gt;

&lt;p&gt;In my opinion, this is the number 1 source of confusion for beginners.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Common Misconception&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Objects are stored in the creator's account address&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is FALSE!&lt;/p&gt;

&lt;p&gt;The Truth&lt;br&gt;
When you create an Object:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It gets its own unique address in global storage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This address is either deterministic (based on seed) or random&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It exists independently in the blockchain&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your account just gets metadata about ownership&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What's Actually Stored Where&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In the Object's address (0xabc...):&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;=&amp;gt; ObjectCore - ownership info, transfer rules, GUID&lt;br&gt;
=&amp;gt; Your custom structs/resources&lt;br&gt;
=&amp;gt; Any capabilities (refs) you store there (We'll explore refs better in subsequent parts).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In your account (0x123):&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;=&amp;gt; Reference/proof that you own it&lt;br&gt;
=&amp;gt; NOT the actual data&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Types of Objects&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;=&amp;gt; &lt;strong&gt;Normal Objects (Random Address)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let constructor_ref = object::create_object(owner_address);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gets a random address&lt;/li&gt;
&lt;li&gt;Fully transferable by default&lt;/li&gt;
&lt;li&gt;It is deleteable&lt;/li&gt;
&lt;li&gt;Can be modified if you have refs&lt;/li&gt;
&lt;li&gt;Most common type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Example use cases:&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NFTs&lt;/li&gt;
&lt;li&gt;Gaming items&lt;/li&gt;
&lt;li&gt;Tradeable assets&lt;/li&gt;
&lt;li&gt;Assets that should change owners&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public entry fun mint_nft(creator: &amp;amp;signer) {
    let creator_addr = signer::address_of(creator);

    // create transferable object
    let constructor_ref = object::create_object(creator_addr);
    let object_signer = object::generate_signer(&amp;amp;constructor_ref);

    // add your NFT data
    move_to(&amp;amp;object_signer, NFTData {
        name: b"Cool Dragon",
        image_uri: b"ipfs://Qm...",
        ...
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;=&amp;gt; &lt;strong&gt;Named Objects (Deterministic Address)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let constructor_ref = object::create_named_object(
    creator, b"my_unique_seed"
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Address is derived from &lt;code&gt;creator_address + seed&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Same creator + seed = same address (predictable)&lt;/li&gt;
&lt;li&gt;Can only be created once per seed&lt;/li&gt;
&lt;li&gt;Not deleteable&lt;/li&gt;
&lt;li&gt;Transferable by default&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protocol-level resources (treasury, registry)&lt;/li&gt;
&lt;li&gt;Singleton patterns&lt;/li&gt;
&lt;li&gt;Global leaderboards&lt;/li&gt;
&lt;li&gt;Configuration objects&lt;/li&gt;
&lt;li&gt;Resources you need to find without storing the address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example - Game leaderboard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const NAME: vector&amp;lt;u8&amp;gt; = b"global_leaderboard_v1";
    const E_NOT_AUTHORIZED: u64 = 1;

    //the Init Function
    public entry fun init_leaderboard(admin: &amp;amp;signer) {
        let admin_addr = signer::address_of(admin);

        // strictly enforce that only the deployer can call this
        assert!(admin_addr == @my_module, E_NOT_AUTHORIZED);

        // create the object
        let constructor_ref = object::create_named_object(
            admin, NAME
        );

        // generate the signer so we can add resources to this object
        let object_signer = object::generate_signer(&amp;amp;constructor_ref);


        move_to(&amp;amp;object_signer, Leaderboard {
            top_players: vector::empty(),
            season: 1,
        });
    }

    // later, anyone can find it without storing the address
    #[view]
    public fun get_leaderboard(): address {
        let admin_addr = @my_module;
        object::create_object_address(&amp;amp;admin_addr, NAME)
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pro Tips: Use descriptive seeds with versioning&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;b"treasury_v1"
b"config_mainnet_v2" 
b"player_registry_2024"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;=&amp;gt; &lt;strong&gt;Sticky Objects (Non transferable)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let constructor_ref = object::create_sticky_object(owner_address);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PERMANENTLY bound to the owner&lt;/li&gt;
&lt;li&gt;Cannot be transferred under ANY circumstances&lt;/li&gt;
&lt;li&gt;Owner cannot even transfer it themselves&lt;/li&gt;
&lt;li&gt;Perfect for identity/reputation&lt;/li&gt;
&lt;li&gt;Not deletable&lt;/li&gt;
&lt;li&gt;Has random address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Soulbound tokens (SBTs)&lt;/li&gt;
&lt;li&gt;Achievement badges&lt;/li&gt;
&lt;li&gt;Certifications/credentials&lt;/li&gt;
&lt;li&gt;Identity tokens&lt;/li&gt;
&lt;li&gt;Reputation scores&lt;/li&gt;
&lt;li&gt;KYC/AML credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example - Achievement system&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public entry fun award_achievement(
    player: address,
    achievement_id: u64
) {
    // this achievement is permanently bound to the player
    let constructor_ref = object::create_sticky_object(player);
    let object_signer = object::generate_signer(&amp;amp;constructor_ref);

    move_to(&amp;amp;object_signer, Achievement {
        id: achievement_id,
        name: b"Dragon Slayer",
        earned_at: timestamp::now_seconds(),
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When NOT to use:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regular NFTs (use regular objects)&lt;/li&gt;
&lt;li&gt;Anything that might need to be traded&lt;/li&gt;
&lt;li&gt;Items that should be transferable "just in case"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Quick Decision Tree&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Need predictable address?
  └─→ Named Object

Should NEVER transfer?
  └─→ Sticky Object

Everything else (NFTs, items, etc.)?
  └─→ Normal Object
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Add Data to Objects
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public entry fun create_game_item(creator: &amp;amp;signer) {
    // step 1: create the object
    let constructor_ref = object::create_object(
        signer::address_of(creator)
    );

    // step 2: get a signer for the object's address
    let object_signer = object::generate_signer(&amp;amp;constructor_ref);

    // step 3: move your struct INTO the object's address
    move_to(&amp;amp;object_signer, GameItem {
        name: b"legendary Sword",
        attack: 150,
        durability: 100,
    });

    // this is optional
    // Store the object's address for later
    let object_addr = object::address_from_constructor_ref(&amp;amp;constructor_ref);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Key points:&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You need the &lt;code&gt;object_signer&lt;/code&gt; to move resources to the object's address&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;object_signer&lt;/code&gt; can only be created during object creation (via ConstructorRef)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your data lives at the object's address, not your account&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Accessing Objects Later
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Reading Object Data&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public fun get_item_stats(object_addr: address): (vector&amp;lt;u8&amp;gt;, u64) 
    acquires GameItem 
{
    let item = borrow_global&amp;lt;GameItem&amp;gt;(object_addr);
    (item.name, item.attack)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Modifying Object Data&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public entry fun upgrade_item(object_addr: address) 
    acquires GameItem 
{
    // check ownership first
    // ... ownership validation ...

    let item = borrow_global_mut&amp;lt;GameItem&amp;gt;(object_addr);
    item.attack = item.attack + 10;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Transferring Ownership&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public entry fun transfer_item(
    owner: &amp;amp;signer,
    object_addr: address,
    recipient: address
) {
    // verify owner has permission
    let owner_addr = signer::address_of(owner);
    assert!(object::owner(object_addr) == owner_addr, E_NOT_OWNER);

    // transfer
    object::transfer(owner, object_addr, recipient);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Now that you understand what Objects are and where they live, you're ready for the real power: Refs (Capabilities).&lt;/p&gt;

&lt;p&gt;In Part 2, we'll cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What are Refs and why they matter&lt;/li&gt;
&lt;li&gt;Types of Refs explained&lt;/li&gt;
&lt;li&gt;How to generate and store Refs&lt;/li&gt;
&lt;li&gt;When to use each Ref type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quick Reference Card&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Normal Object (transferable)
object::create_object(owner_addr)

// Named Object (predictable address)
object::create_named_object(creator, seed)

// Sticky Object (non-transferable)
object::create_sticky_object(owner_addr)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Found this helpful? Drop a like and stay tuned for Part 2 where we explore Refs.&lt;/p&gt;

&lt;p&gt;Questions? Drop them in the comments below.&lt;/p&gt;

&lt;p&gt;You can also reach me on &lt;a href="https://x.com/dankestrel" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; now X.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>web3</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Why Move on Aptos Is Better for Financial Accounts Than Traditional Languages</title>
      <dc:creator>Daniel</dc:creator>
      <pubDate>Thu, 07 Aug 2025 14:18:33 +0000</pubDate>
      <link>https://forem.com/danielkestrel/why-move-on-aptos-is-better-for-financial-accounts-than-traditional-languages-1g8h</link>
      <guid>https://forem.com/danielkestrel/why-move-on-aptos-is-better-for-financial-accounts-than-traditional-languages-1g8h</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ci4blaxwaafef1xaqsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ci4blaxwaafef1xaqsp.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;When we think about building a financial application, like a digital bank or a credit system, the core requirements are &lt;strong&gt;&lt;em&gt;security&lt;/em&gt;&lt;/strong&gt;, &lt;em&gt;&lt;strong&gt;reliability&lt;/strong&gt;&lt;/em&gt;, and &lt;strong&gt;&lt;em&gt;integrity&lt;/em&gt;&lt;/strong&gt;. The blockchain, with its decentralized and immutable ledger, offers a powerful foundation for meeting these demands. However, to truly harness this potential, you need a programming language designed specifically for the task.&lt;/p&gt;

&lt;p&gt;Come with me&lt;/p&gt;

&lt;p&gt;Traditional programming languages like Python or Java are versatile and widely used, but they were not designed from the ground up to handle high-value digital assets in a trustless environment. &lt;/p&gt;

&lt;p&gt;At this point, Aptos and its purpose-built programming language, Move, offer a compelling solution. Move was engineered to make it inherently difficult to write insecure code, a necessity for managing high-value digital assets. The fundamental design choices of Move make it a far superior choice for creating digital bank accounts and other financial services on the blockchain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Objects vs. Resources: A Foundational Difference&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The single most important feature that sets Aptos Move apart is its concept of resource-oriented programming. This stands in stark contrast to the object-oriented paradigm common in most programming languages.&lt;/p&gt;

&lt;p&gt;In traditional programming, objects and their data can be copied freely, and references can be shared. Memory management is often automatic but can be a source of subtle, error-prone bugs. A variable holding a value—say, a number representing a bank balance—can be duplicated or accidentally overwritten, which can be a catastrophic vulnerability in a financial system where every asset must have a unique, single owner.&lt;/p&gt;

&lt;p&gt;In Move programming, digital assets are treated as resources with unique ownership. The language and its compiler enforce strict rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A resource cannot be copied or accidentally dropped.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An explicit transfer of ownership is required for every asset movement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This design fundamentally prevents double-spending by design at the language level.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Move treats digital assets like a physical coin that can only be in one place at a time. This design forces developers to handle every asset with care, eliminating an entire class of security bugs that could lead to financial loss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Formal Verification: Mathematical Proof for Security&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For high-stakes applications like banking, simply trying to write secure code isn't enough. You need proof. And it's well known that when precision is non-negotiable, Move’s formal verification comes to the rescue.&lt;/p&gt;

&lt;p&gt;The Move ecosystem includes a powerful tool called the Move Prover. This tool can analyze the bytecode of a smart contract and mathematically prove that it meets certain security properties. For example, you can write a specification that proves a function for transferring funds will always result in the sender's balance decreasing by the exact amount transferred and the receiver's balance increasing by the same amount, without any overflow or underflow issues.&lt;/p&gt;

&lt;p&gt;This level of rigor is extremely difficult and costly to achieve in traditional languages, which rely heavily on extensive manual audits and unit tests. With Move, you can have a much higher degree of confidence that your financial logic is not only correct but also mathematically proven to be so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security by Design: Preventing Common Vulnerabilities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Beyond its core concepts, Move has been designed to prevent many other common vulnerabilities that plague smart contracts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Type Safety: The language is statically typed, which means it catches data type errors at compile time, long before they can cause a bug in production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No Dynamic Dispatch: Functions are linked at compile time, eliminating a key vulnerability vector known as reentrancy attacks, where a malicious contract can make a recursive call to drain funds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integer Overflow Prevention: Move’s arithmetic operations are designed to check for overflow and underflow, preventing a common source of exploits where a balance can be manipulated to an unexpected value.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By building these protections directly into the language, Move significantly lowers the risk and complexity of creating secure financial applications compared to traditional languages, which often require developers to use third-party libraries and manually implement security best practices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Verdict: A Language Built for Trust&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Traditional languages are general-purpose tools, but a bank account is not a general-purpose application. It is a system built on trust and a single, unshakeable ledger. The blockchain provides this ledger, but Move is the language that ensures the logic written on that ledger is sound. Its focus on asset management, formal verification, and security by design makes it an ideal foundation for a new generation of reliable and secure financial applications.&lt;/p&gt;

&lt;p&gt;I am eager to know what your thoughts are on this. Also, don't hesitate to reach out to me on &lt;a href="https://x.com/dankestrel" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; if you have any questions.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding Blockspace in Blockchains</title>
      <dc:creator>Daniel</dc:creator>
      <pubDate>Sat, 26 Jul 2025 11:11:26 +0000</pubDate>
      <link>https://forem.com/danielkestrel/understanding-blockspace-in-blockchains-3c85</link>
      <guid>https://forem.com/danielkestrel/understanding-blockspace-in-blockchains-3c85</guid>
      <description>&lt;p&gt;Blockspace refers to the &lt;a href="https://zerocap.com/insights/research-lab/blockspace-impacts-blockchain-dynamics/" rel="noopener noreferrer"&gt;finite capacity&lt;/a&gt; within a blockchain block that is available for storing transactions and other data. See a blockchain like a digital ledger (it's more than this anyway), and each "block" as a page in that ledger. Blockspace is essentially how much "writing room" is available on each page.&lt;/p&gt;

&lt;p&gt;This space is a critical resource because,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Limited Supply: Every blockchain has a maximum block size (measured in bytes or gas units) that dictates how much data can fit into a single block. This limit is set by the protocol to manage network load, prevent spam, and ensure decentralization (as larger blocks are harder for nodes to process and store).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;High Demand: As blockchain networks gain adoption, there's increasing demand from users and applications to include their transactions in the next available block.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auction Market: Because blockspace is limited and in high demand, it often becomes an auction market. Users bid with transaction fees (gas) to get their transactions included, especially during periods of high network congestion. This is why gas fees can spike dramatically on busy chains.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Impact on Throughput: The amount of blockspace directly influences a blockchain's maximum throughput (Transactions Per Second, or TPS). More blockspace (or more efficiently used blockspace) generally allows for more transactions to be processed within a given timeframe.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In essence, blockspace is the &lt;a href="https://www.aniccaresearch.tech/blog/things-hidden-since-foundation-of-blockspace" rel="noopener noreferrer"&gt;fundamental economic resource&lt;/a&gt; of a blockchain. It's what users are competing for when they send transactions.&lt;/p&gt;

&lt;p&gt;Blockspace on Aptos&lt;/p&gt;

&lt;p&gt;Aptos approaches blockspace with a focus on maximizing its utilization and ensuring efficient processing to deliver high throughput and low fees. While every blockchain has finite blockspace, Aptos' innovations are designed to make the most of it. &lt;/p&gt;

&lt;p&gt;The following make aptos standout:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Dynamic Block Content: Unlike some chains with very rigid block structures, Aptos' blocks can dynamically contain &lt;a href="https://aptos.dev/network/blockchain/blocks" rel="noopener noreferrer"&gt;varying numbers of transactions&lt;/a&gt; depending on network activity, up to a configurable maximum size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Efficient Utilization via Block-STM: This makes Aptos excel way more than other chains. Its &lt;a href="https://dev.to/danielkestrel/beyond-speed-how-aptos-achieves-ultra-low-gas-costs-at-scale-2ppc"&gt;Block-STM&lt;/a&gt; execution engine allows transactions within a block to be processed in parallel. Instead of executing transactions one by one, Block-STM identifies non-conflicting transactions and runs them simultaneously. This means that Aptos can process a much larger volume of transactions within its available blockspace in a given blocktime compared to a sequential execution model. This can be likened to having multiple scribes writing on the same page at once, without stepping on each other's toes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quorum Store's Role: &lt;a href="https://dev.to/danielkestrel/how-aptos-quorum-store-unlocks-true-scalability-28l9"&gt;As we discussed&lt;/a&gt;, Quorum Store ensures that raw transaction data is disseminated efficiently and in parallel before consensus. This means that when a block is proposed, it contains lightweight Proofs of Availability (PoAvs) instead of the bulky raw transactions. This makes the block itself smaller and faster to transmit through the consensus process. It allows more "logical" transactions to be ordered per unit of time, effectively maximizing the utility of the blockspace for ordering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Low Transaction Costs: By maximizing the number of transactions that can be processed per block (high throughput) and optimizing the underlying architecture, Aptos continues to keep transaction fees low, making its blockspace affordable and accessible for a wider range of applications and users. This is demand and supply in action as Aptos' architecture readily makes blockspace available for use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Future Scalability (Sharding): While Aptos already achieves high performance on a single ledger state, its modular design and parallel execution capabilities lay the groundwork for future horizontal scaling solutions like &lt;a href="https://medium.com/aptoslabs/shardines-aptos-sharded-execution-engine-blazes-to-1m-tps-71c5f9b8bf60" rel="noopener noreferrer"&gt;sharding&lt;/a&gt;. Sharding would effectively create multiple "blockspaces" (or shards) that can process transactions in parallel, further expanding the network's total capacity.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's safe to conclude that blockspace is the lifeblood of any blockchain, the fundamental resource users compete for. While its scarcity often leads to high fees and congestion on other networks, Aptos has engineered a different path.&lt;/p&gt;

&lt;p&gt;Don't hesitate to reach out to me on &lt;a href="https://x.com/dankestrel" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; if you have any questions.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How Aptos' Quorum Store Unlocks True Scalability</title>
      <dc:creator>Daniel</dc:creator>
      <pubDate>Fri, 18 Jul 2025 22:36:16 +0000</pubDate>
      <link>https://forem.com/danielkestrel/how-aptos-quorum-store-unlocks-true-scalability-28l9</link>
      <guid>https://forem.com/danielkestrel/how-aptos-quorum-store-unlocks-true-scalability-28l9</guid>
      <description>&lt;p&gt;Aptos has quickly made a name for itself with its impressive transaction throughput and sub-second finality. But how does it achieve such performance, especially when many blockchains struggle with scalability? One of the core innovations behind this is Quorum Store, a sophisticated mempool protocol that fundamentally transforms how transaction data is handled before it even reaches consensus.&lt;/p&gt;

&lt;p&gt;At its heart, Quorum Store is all about decoupling data dissemination from the consensus process, effectively removing a major bottleneck in traditional blockchain architectures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Bottleneck Problem: A Single Point of Failure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In many classic leader-based Byzantine Fault Tolerant (BFT) consensus protocols, the process often looks like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A leader validator is chosen for a specific round.&lt;/p&gt;

&lt;p&gt;This leader is responsible for gathering a block of transactions from its mempool.&lt;/p&gt;

&lt;p&gt;Crucially, the leader then broadcasts the entire block of raw transaction data to all other validators in the network.&lt;/p&gt;

&lt;p&gt;Only after receiving and validating this full block do other validators cast their votes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem here is glaring; the leader's network bandwidth and processing power become the single bottleneck for the entire network's throughput. &lt;/p&gt;

&lt;p&gt;If the leader can only send X transactions per second, the whole chain is limited to X, regardless of how powerful the other validators are. It's like having a single mail carrier trying to deliver every single newspaper (full transaction data) to every house (validator) in the city. This centralized data delivery limits overall system performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quorum Store: Decentralized Data Delivery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Quorum Store is a production-optimized implementation of the "Narwhal" design, introducing a parallel, decentralized approach to transaction data dissemination. It creates an intermediate layer between the mempool and the consensus protocol (AptosBFT), ensuring that raw transaction data is widely available before the consensus leader even needs to propose a block.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We will see how it works in three phases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Phase 1&lt;/em&gt;&lt;/strong&gt;: &lt;strong&gt;&lt;em&gt;Decentralized Data Dissemination (The "Full Newspaper" Delivery)&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the most critical shift. Instead of waiting for a leader,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All validators are active participants. Each validator's Quorum Store component continuously pulls batches of raw transactions from its local mempool (its queue of transactions received from users).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;These batches of complete, raw transaction data are then broadcasted in parallel from each validator to all other validators in the network.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It's like every newsstand (validator) in the city constantly printing its own batches of full newspapers (raw transactions) and sharing them directly with every other newsstand. This happens concurrently across the entire validator set.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This parallel, all-to-all dissemination ensures that the heavy lifting of moving transaction data around is distributed, eliminating the single-leader bottleneck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Phase 2: Proof of Availability (PoAv) Generation&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once a validator has successfully received and stored a batch of raw transactions (whether it originated the batch or received it from another validator),&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It cryptographically signs the metadata (a small identifier/hash) of that batch. This signature acts as an attestation that the validator has seen and stored that specific batch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The validator that originated the batch (or is tracking its dissemination) then collects these signatures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When it gathers signatures from a quorum (2f+1, where 'f' is the number of Byzantine/faulty validators) of other validators, it can construct a Proof of Availability (PoAv) for that batch.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What does a PoAv look like?&lt;/strong&gt; It's a lightweight cryptographic certificate. It typically includes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A cryptographic hash of the entire batch of raw transactions (a small, fixed-size fingerprint).&lt;/p&gt;

&lt;p&gt;A collection of aggregated or compressed signatures from the quorum of validators who attested to receiving the batch.&lt;/p&gt;

&lt;p&gt;(Optionally) Metadata like an expiration time for the proof.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Crucially, a PoAv does NOT contain the raw transaction data itself. It's just a small, verifiable proof that the data exists and is widely available.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Phase 3: Lightweight Consensus (Ordering the "Table of Contents")&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With transaction data already disseminated and proven available via PoAvs, the consensus leader's role becomes much more efficient:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When it's a validator's turn to be the consensus leader (as determined by AptosBFT), it looks at the pool of available PoAvs that have been successfully generated by the network.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The leader then proposes a block that contains only these small PoAvs (metadata), along with other essential block information (like the previous block's hash and round number). It does not need to include or re-send the large raw transaction data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The consensus protocol then focuses solely on ordering these lightweight PoAvs. This makes block proposals much smaller and faster to transmit and verify, reducing consensus latency.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once a block (containing ordered PoAvs) is committed by the consensus, the execution engine (Block-STM) can then use these PoAvs to retrieve the actual transaction data (which validators likely already have from Phase 1) for parallel execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Benefits of Aptos' Quorum Store&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The integration of Quorum Store provides several advantages for the Aptos blockchain. They include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Throughput Increase: By offloading the heavy data dissemination task from the leader and distributing it, Quorum Store directly tackles the primary bottleneck, enabling significantly higher Transactions Per Second (TPS).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Horizontal Scalability: The system can scale horizontally. As network load increases, more validators can contribute to the parallel data dissemination, improving overall capacity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lower Latency: Transactions become available to validators much faster, contributing to the sub-second finality that Aptos is known for.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Efficient Resource Utilization: All validators are actively engaged in the data pipeline. This leads to a more balanced and efficient use of network resources compared to leader-centric models.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhanced Reliability and Data Availability: The Proof of Availability mechanism ensures that once a batch is included in a block, the underlying transaction data is guaranteed to be available across a supermajority of the network, even if some nodes go offline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modular and Pipelined Architecture: Quorum Store fits perfectly into Aptos' modular design. It allows different components (mempool, data dissemination, consensus, execution, storage) to operate concurrently and be optimized independently.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aptos' Quorum Store isn't just a mempool; it's a fundamental architectural innovation which, by far, optimizes how blockchain networks can achieve high performance and scalability. &lt;/p&gt;

&lt;p&gt;By intelligently decoupling data dissemination from consensus, Aptos ensures that transaction data flows efficiently and reliably.&lt;/p&gt;

&lt;p&gt;Understanding Quorum Store is key to appreciating why Aptos is positioned as a leading blockchain for mainstream Web3 adoption.&lt;/p&gt;

&lt;p&gt;Don't hesitate to reach out to me on &lt;a href="https://x.com/dankestrel" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; if you have any questions.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Your Digital Identity on Aptos: Accounts, Addresses, and Wallets Explained</title>
      <dc:creator>Daniel</dc:creator>
      <pubDate>Fri, 11 Jul 2025 04:45:10 +0000</pubDate>
      <link>https://forem.com/danielkestrel/your-digital-identity-on-aptos-accounts-addresses-and-wallets-explained-205g</link>
      <guid>https://forem.com/danielkestrel/your-digital-identity-on-aptos-accounts-addresses-and-wallets-explained-205g</guid>
      <description>&lt;p&gt;Understanding how your identity and assets are managed on the blockchain is crucial to decentralized finance and web3 generally. On Aptos, this involves a sophisticated interplay between accounts, addresses, and the wallets you use every day. Let's break down these fundamental concepts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aptos Accounts: Not Just a Balance
&lt;/h3&gt;

&lt;p&gt;Unlike some older blockchain models where an account might simply represent a numerical balance, an &lt;strong&gt;Aptos account is a robust, on-chain container&lt;/strong&gt;. It can be likened to a personal, smart digital vault on the blockchain.&lt;/p&gt;

&lt;p&gt;Every Aptos account is designed to hold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resources:&lt;/strong&gt; These are your actual digital assets, such as APT tokens, NFTs, stablecoins, or any other programmable digital item. Aptos uses the &lt;strong&gt;Move programming language's strict resource model&lt;/strong&gt;, which ensures these assets are "first-class citizens." This means they can only be explicitly moved or destroyed, making them secure against accidental duplication or loss.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modules:&lt;/strong&gt; These are the Move smart contract code that dictates the rules for how resources are managed within that account, or how external interactions with it can occur. An account can publish and own its own custom modules, allowing for unique on-chain logic and behaviors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This "account as a smart container" is what provides developers and users with greater flexibility and security directly at the account level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Addresses: Your Permanent Public Identifier
&lt;/h3&gt;

&lt;p&gt;Every Aptos account is assigned a unique &lt;strong&gt;32-byte (256-bit) hexadecimal address&lt;/strong&gt;, typically displayed with a &lt;code&gt;0x&lt;/code&gt; prefix. This address serves as your public identifier on the Aptos blockchain. It's the digital equivalent of your mailing address. You share it with others to receive tokens, NFTs, or for them to interact with your published smart contracts.&lt;/p&gt;

&lt;p&gt;A key distinction on Aptos is that an account, as an on-chain container, must be &lt;strong&gt;explicitly created&lt;/strong&gt; before it can transact or hold resources. This creation process often happens seamlessly when you receive your first APT tokens or when your wallet initializes your presence on the chain. In other words, your account creation on Aptos is only complete when you send APT token into it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication Keys: The Power of Key Rotation
&lt;/h3&gt;

&lt;p&gt;Aptos stands out when it comes to security and user experience. That's because the core of every Aptos account's control lies with its authentication key.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you initially set up an Aptos account, an &lt;strong&gt;authentication key&lt;/strong&gt; is derived from your public key (which, in turn, is generated from your secret private key). This initial authentication key &lt;em&gt;is&lt;/em&gt; also your account's address.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Rotation.&lt;/strong&gt; Aptos uniquely allows you to &lt;strong&gt;&lt;a href="https://dev.to/danielkestrel/fortifying-your-aptos-assets-a-practical-guide-to-key-account-rotation-1mmm"&gt;rotate your authentication key&lt;/a&gt;&lt;/strong&gt;. This means you can change the underlying private key that controls your account &lt;em&gt;without changing your public Aptos address&lt;/em&gt;.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;This sets a new standard for blockchain account management:&lt;/strong&gt; If you ever suspect your private key has been compromised (e.g., through a phishing attempt or malware), you can generate a brand new, secure private key and perform a key rotation on your Aptos account. Your existing address, all your assets, NFTs, and entire transaction history remain intact at the same address, but control is instantly transferred to your new, secure private key. This is a great leap in cryptographic security, similar to changing a password for a critical online service, but with the immutable guarantees of the blockchain.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Wallets: Your Access to Aptos
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;wallet&lt;/strong&gt; (such as Petra, Pontem, or others) is the essential software application that serves as your primary interface to the Aptos blockchain. &lt;/p&gt;

&lt;p&gt;Wallets perform several critical functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Secure Key Management:&lt;/strong&gt; Wallets securely store your private keys (or facilitate connections to hardware wallets for offline key storage). Private keys are fundamental for signing transactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Address Management:&lt;/strong&gt; They display your Aptos addresses and allow you to manage multiple accounts from a single interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction Creation and Signing:&lt;/strong&gt; Wallets simplify the process of creating transactions (e.g., sending APT, interacting with decentralized applications). They present the transaction details for your review and then use your private key to generate a unique digital signature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Balance and History Tracking:&lt;/strong&gt; By connecting to the Aptos network, your wallet provides a real-time view of your asset balances and a comprehensive history of your transactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DApp Interaction:&lt;/strong&gt; Wallets enable a secure and seamless connection to decentralized applications (dApps), allowing you to interact with smart contracts and services on Aptos without ever exposing your sensitive private keys.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How It All Comes Together: A Seamless Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Key Generation:&lt;/strong&gt; Your wallet helps you generate a secure &lt;strong&gt;private key&lt;/strong&gt; (often derived from a mnemonic seed phrase).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Address Derivation:&lt;/strong&gt; From your private key, a &lt;strong&gt;public key&lt;/strong&gt; is derived, which then forms your &lt;strong&gt;authentication key&lt;/strong&gt;, and ultimately your unique &lt;strong&gt;Aptos address&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Transaction Authorization:&lt;/strong&gt; When you decide to perform an action on the blockchain, your wallet constructs the transaction details.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Digital Signature:&lt;/strong&gt; Your wallet uses your &lt;strong&gt;private key&lt;/strong&gt; to create a cryptographic &lt;strong&gt;signature&lt;/strong&gt; for that specific transaction. This signature proves that &lt;em&gt;you&lt;/em&gt; authorized the action.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Broadcast to Network:&lt;/strong&gt; The signed transaction is then broadcast to the Aptos validators.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Verification and Execution:&lt;/strong&gt; Aptos validators use the &lt;strong&gt;authentication key&lt;/strong&gt; (derived from your public key) associated with your address to verify the signature's authenticity. If valid, the transaction is executed, updating your account's resources or interacting with its modules, and the changes are permanently recorded on the blockchain.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Adaptive Control:&lt;/strong&gt; Should the need arise, the &lt;strong&gt;authentication key&lt;/strong&gt; can be rotated, seamlessly linking your existing address to a new private key.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This sophisticated account model, coupled with the inherent safety guarantees of the Move language, means Aptos is built from the ground up for robust security, user control, and a superior digital experience.&lt;/p&gt;

&lt;p&gt;Thanks for reading. If anything's unclear or you have more questions, please ask in the comments or reach out directly on &lt;a href="https://x.com/dankestrel" rel="noopener noreferrer"&gt;Twitter.&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Beyond Speed: How Aptos Achieves Ultra-Low Gas Costs at Scale</title>
      <dc:creator>Daniel</dc:creator>
      <pubDate>Sun, 29 Jun 2025 11:12:48 +0000</pubDate>
      <link>https://forem.com/danielkestrel/beyond-speed-how-aptos-achieves-ultra-low-gas-costs-at-scale-2ppc</link>
      <guid>https://forem.com/danielkestrel/beyond-speed-how-aptos-achieves-ultra-low-gas-costs-at-scale-2ppc</guid>
      <description>&lt;p&gt;Aptos is engineered from the ground up to keep gas fees low, even as the network scales. It's not just one solution, but a combination of several technical innovations that contribute to its cost efficiency. Why are transactions fees so low on aptos? Let's get straight to the point...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;High Throughput and Parallel Execution (Block-STM):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Core Principle: When a blockchain can process a massive number of transactions per second (high throughput theoretically at 160k per sec), the demand for block space is spread across a much larger capacity. This naturally drives down the price per unit of that space.&lt;/li&gt;
&lt;li&gt;Aptos' Advantage: Aptos' block-stm engine allows for parallel transaction execution. Unlike older blockchains where transactions are processed one by one (like a single-lane road), Block-STM executes many transactions concurrently. This means the network can handle significantly more transactions without getting congested.    &lt;/li&gt;
&lt;li&gt;Impact on Gas: Less congestion means less competition for transaction inclusion. When there's ample capacity, users don't need to bid extremely high gas prices to get their transactions processed quickly, leading to consistently low base fees.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Efficient Resource Accounting (Move Language):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Problem: Some older blockchain environments can be inefficient in how they measure and charge for computational resources (cpu, memory, storage). This can lead to overcharging or under-optimization.&lt;/li&gt;
&lt;li&gt;Aptos' Advantage: The move programming language, designed with resources as first-class citizens, allows for very precise and fine-grained accounting of the actual computational and storage resources consumed by a transaction.  &lt;/li&gt;
&lt;li&gt;Impact on Gas: Because the network can accurately measure the exact gas units used for instructions, i/o, and storage, transactions are only charged for what they truly consume. This granular control, combined with optimization principles baked into Move, helps developers write more gas-efficient smart contracts.
  &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Storage Fees and Refunds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Problem: Storing data on a blockchain is a long-term cost for the entire network. Some chains charge high, non-refundable fees for storage, even if the data is later deleted.&lt;/li&gt;
&lt;li&gt;Aptos' Advantage: Aptos separates "transient" computation/execution costs from "persistent" storage costs. While you pay a fee for allocating new storage slots, Aptos has a mechanism to refund a portion (currently the entirety) of the storage fee when data is deleted from the blockchain.  &lt;/li&gt;
&lt;li&gt;Impact on Gas: This incentivizes efficient data management. Developers and users are encouraged to clean up unnecessary state, which keeps the overall state of the blockchain lean, reduces validator costs for storing data, and ultimately keeps transaction costs lower by not penalizing temporary storage. Even though gas is burned and minted for refunds, the net effect encourages efficient storage use.  &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dynamic Gas Fee Model (Adaptive Pricing):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Principle: Like many modern blockchains, Aptos employs a dynamic gas fee model that adjusts based on network demand.  &lt;/li&gt;
&lt;li&gt;Aptos' Implementation: While there's a minimum gas unit price set by governance, the actual gas price per unit can fluctuate. When the network is less busy, the gas unit price can drop very low. The system also prioritizes transactions with higher gas unit prices if needed (e.g., during periods of high demand), but it's designed to keep the base cost low during normal operations.&lt;/li&gt;
&lt;li&gt;Impact on Gas: This allows transaction costs to remain affordable during periods of low to moderate activity, preventing consistently high fixed costs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Efficient State Synchronization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Problem: Keeping all nodes synchronized with the latest state changes can be a resource-intensive process, impacting network efficiency and indirectly gas costs. &lt;/li&gt;
&lt;li&gt;Aptos' Advantage: Aptos uses advanced state synchronization techniques that allow nodes to keep updated rapidly and efficiently. This reduces the overhead for validators and the overall network.  &lt;/li&gt;
&lt;li&gt;Impact on Gas: A more efficient and less resource-intensive network infrastructure means validators can operate at lower costs, which translates into lower operational costs passed on to users in the form of gas fees.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Conclusively, Aptos achieves cheap gas fees by combining massive parallel processing (Block-STM) to handle high transaction volumes, precise resource accounting with Move to only charge what's truly consumed, smart storage refund mechanisms to encourage efficiency, and a dynamic fee model that scales with network load, all built upon an optimized, modular architecture. This collective approach ensures that the network can sustain low transaction costs even as it grows to accommodate billions of users and complex applications.&lt;/p&gt;

&lt;p&gt;Thank you for coming this far. Need any clarifications, don't hesitate to ask in comments or reach out to me on &lt;a href="https://x.com/dankestrel" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Aptos docs on gas and storage fees:&lt;br&gt;
&lt;a href="https://aptos.dev/en/network/blockchain/gas-txn-fee" rel="noopener noreferrer"&gt;https://aptos.dev/en/network/blockchain/gas-txn-fee&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Aptos docs on execution and block-stm: &lt;a href="https://aptos.dev/en/network/blockchain/execution" rel="noopener noreferrer"&gt;https://aptos.dev/en/network/blockchain/execution&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Aptos docs on state synchronization (consensus observer): &lt;a href="https://aptos.dev/en/network/nodes/configure/state-sync" rel="noopener noreferrer"&gt;https://aptos.dev/en/network/nodes/configure/state-sync&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Medium article by aptos labs: &lt;br&gt;
&lt;a href="https://medium.com/aptoslabs/the-path-to-10x-lower-gas-fees-on-aptos-with-community-driven-feedback-7cca875a513f" rel="noopener noreferrer"&gt;the path to 10x lower gas fees on aptos with community-driven feedback&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;General documentation on the move programming language and its resource model.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Fortifying Your Aptos Assets: A Practical Guide to Key Account Rotation</title>
      <dc:creator>Daniel</dc:creator>
      <pubDate>Tue, 17 Jun 2025 10:18:19 +0000</pubDate>
      <link>https://forem.com/danielkestrel/fortifying-your-aptos-assets-a-practical-guide-to-key-account-rotation-1mmm</link>
      <guid>https://forem.com/danielkestrel/fortifying-your-aptos-assets-a-practical-guide-to-key-account-rotation-1mmm</guid>
      <description>&lt;p&gt;While blockchain technology offers transparency and immutability, the security of your funds ultimately rests on the strength and management of your private keys. One of the most critical, yet often overlooked, security practices is key rotation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Key Rotation and Why is it Crucial?&lt;/strong&gt;&lt;br&gt;
At its core, key rotation involves periodically replacing an existing cryptographic key with a new one. In the context of blockchain accounts, this means changing the key that authorizes transactions for your address. Why is this a security imperative?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Mitigating Compromised Keys: Even with the best security practices, keys can be compromised through phishing attacks, malware, insider threats, or accidental exposure. Regular rotation limits the damage a compromised key can inflict, as its validity period is inherently shortened.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Preventing Long-Term Exposure: The longer a key is active, the greater the window of opportunity for attackers to find vulnerabilities or brute-force their way in (though highly improbable for strong keys, it's a risk).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhancing Insider Threat Protection: For organizations or teams managing shared accounts, key rotation ensures that if an insider's access is revoked, their old keys are no longer valid.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aptos offers a significant advantage in this regard. Unlike some other blockchains where your address is inextricably linked to your initial public key, Aptos decouples the authentication key from the account address. This native support for key rotation without changing your permanent Aptos address is a powerful security feature, making it a critical aspect of Aptos account security.&lt;/p&gt;

&lt;p&gt;This guide is designed as a practical resource for developers, DApp operators, institutional users, and advanced individual users seeking to fortify their Aptos assets. I'll walk you through the practical steps, CLI commands, and essential security considerations for seamless and secure key rotation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Account Address: This is the permanent, 32-byte identifier for your Aptos account (e.g., 0x123...abc). It's derived from the initial authentication key when the account is created. Crucially, your account address remains constant even if you rotate your authentication key. This provides stability and avoids the need to update your address across various platforms after a key change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authentication Key: This is the cryptographic key responsible for authorizing transactions originating from your account address. It's a 32-byte hash that can be rotated. When you sign a transaction, it's this key (or more accurately, the private key associated with it) that provides the digital signature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Public Key &amp;amp; Private Key: Behind every authentication key is a public-private key pair. The private key is the secret credential you use to sign transactions, while the public key is mathematically derived from the private key and is used to verify signatures. Your authentication key is a hash of your initial public key.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The Aptos account model facilitates the unique ability to rotate an account’s private key. Since an account’s address is the initial authentication key, the ability to sign for an account can be transferred to another private key without changing its public address.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;How Aptos Enables Key Rotation (Native Support)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A key differentiator for Aptos is its built-in support for key rotation. The blockchain's architecture allows you to change the underlying authentication key without altering your account address. This is achieved through specific Move functions and CLI commands, notably involving the &lt;code&gt;account::set_originating_address&lt;/code&gt; function which facilitates the secure transition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pre-Rotation Checklist: Preparing for a Smooth Transition&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A successful key rotation is not just about executing commands; it's about meticulous preparation. A well-planned approach prevents potential loss of access to your secure Aptos assets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. Identify and Document All Key Usages:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the most critical step. Create an exhaustive list of every place your current Aptos key is used. Think broadly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decentralized Applications (DApps): Are you staking, providing liquidity, or interacting with any DApps using this key?&lt;/li&gt;
&lt;li&gt;Scripts and Automations: Do you have any automated scripts (e.g., for node operations, data collection, or wallet interactions) that rely on this key?&lt;/li&gt;
&lt;li&gt;Integrations: Is your key integrated with any third-party services or platforms?&lt;/li&gt;
&lt;li&gt;Staking and Validator Operations: If you are running an Aptos validator, your consensus key is paramount.&lt;/li&gt;
&lt;li&gt;Wallets: Which wallets (software, hardware) currently hold or derive this key?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Map out dependencies to ensure you update credentials everywhere, preventing service disruption.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Backup Existing Keys Securely:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before making any changes, ensure you have multiple, secure backups of your current private key and seed phrase.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offline Storage: Hardware wallets, encrypted USB drives, or air-gapped computers are ideal.&lt;/li&gt;
&lt;li&gt;Redundancy: Store backups in physically separate, secure locations.&lt;/li&gt;
&lt;li&gt;Seed Phrase Management: Understand that your seed phrase is the ultimate backup for keys derived from it. Treat it with the utmost care, never storing it digitally or sharing it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;C. Ensure Sufficient APT for Gas Fees:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Key rotation is an on-chain transaction and, like all transactions, incurs gas fees. Confirm your account has enough APT tokens to cover these costs before initiating the process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D. Choose Your New Key Management Strategy:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Decide how you will manage your new key. This decision significantly impacts your ongoing security posture.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hardware Wallet Integration: For the highest level of security, especially for mainnet operations and significant funds, a hardware wallet (like Ledger) is strongly recommended. The private key never leaves the device. &lt;/li&gt;
&lt;li&gt;Multi-Signature (Multisig) Accounts: For shared treasuries, organizational funds, or enhanced personal security, consider moving to an Aptos multisig account. This requires multiple approvals for transactions, significantly reducing the risk of single-point-of-failure compromise. &lt;/li&gt;
&lt;li&gt;Dedicated Hot Wallets: For specific operational needs requiring frequent transactions, a "hot" wallet (online software wallet) might be used, but with extreme caution and limited funds. Implement strict access controls and regular auditing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Practical Steps for Aptos Key Account Rotation
&lt;/h2&gt;

&lt;p&gt;I presume you're using a Unix-like system.&lt;/p&gt;

&lt;p&gt;Now, let's get hands-on with the Aptos CLI to perform the key rotation. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
First step is to set up a local network. Run the following command on your terminal.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Setting up a local network is having a local Aptos blockchain network on your machine, suitable for development and testing.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos node run-localnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see some key outputs like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Readiness endpoint: http://127.0.0.1:8070/

Completed generating configuration:

.........more info

Aptos is running, press ctrl-c to exit

Faucet is starting, please wait...
Node API is starting, please wait...
Transaction stream is starting, please wait...

.......more into

Applying post startup steps...

Setup is complete, you can now use the localnet!

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, to have this process running in background, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p localnet-data
aptos node run-localnet \
    --assume-yes \
    --test-dir localnet-data \
    --force-restart \
    &amp;gt; localnet.log 2&amp;gt;&amp;amp;1 &amp;amp; 
export LOCALNET_PID=$!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To terminate it, use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kill $LOCALNET_PID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Next, generate a private key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a private key corresponding to an authentication key, and thus initial account address, that starts with the vanity prefix &lt;code&gt;0xdae&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos key generate \
    --assume-yes \
    --output-file private-key-a \
    --vanity-prefix 0xdae
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": {
    "PublicKey Path": "private-key-a.pub",
    "Account Address:": "0xdaeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5",
    "PrivateKey Path": "private-key-a"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note that the prefix for your vanity prefix must consist of valid hexadecimal characters (0-9, a-f, A-F), else my vanity prefix would have been dan.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two files containing the private key and public keys are generated simultaneously:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;private-key-a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;private-key-a.pub&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Use the command &lt;code&gt;ls&lt;/code&gt; to see them on your terminal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next, we're initializing a profile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will use the generated private key to initialize &lt;code&gt;test-profile-1&lt;/code&gt; on the localnet. Here's the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos init \
    --assume-yes \
    --network local \
    --private-key-file private-key-a \
    --profile test-profile-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terminal Output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Configuring for profile test-profile-1
Configuring for network Local
Using command line argument for private key
Account 0xdaeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5 has been already found onchain

---
Aptos CLI is now set up for account 0xdaeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5 as profile test-profile-1!
---

See the account here: https://explorer.aptoslabs.com/account/0xdaeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5?network=local
{
  "Result": "Success"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: The command was meant to fund the account with test APT but doesn't. So you can do that with this command &lt;code&gt;aptos account fund-with-faucet --profile test-profile-1 --amount octas&lt;/code&gt;. Replace octas with the exact octa value you want. e.g 100000000 for 1 test APT&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can view the just initialized profile with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos config show-profiles --profile test-profile-1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example Output&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe4a350azo89xiq85td21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe4a350azo89xiq85td21.png" alt="Profile Output" width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that the above output doesn't contain my private key. To output the private key, I'll have to use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos config show-private-key --profile test-profile-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Next, let's look up our address using the command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos account lookup-address \
    --public-key-file private-key-a.pub \
    --url http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Store address in a shell variable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ADDRESS_A=dae...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;ADDRESS_A=dae... The &lt;code&gt;dae...&lt;/code&gt; notation is just a way for documentation or explanations to represent "an Aptos address goes here" without showing a very long, specific address that would vary for each user.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's the command to store the address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export ADDRESS_A=$(
    aptos account lookup-address \
        --public-key-file private-key-a.pub \
        --url http://localhost:8080 \
            | jq -r '.Result'
)
echo $ADDRESS_A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Next, we look up the authentication key, which is identical to the account address when first created. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the command for checking the authentication key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos move view \
    --args address:$ADDRESS_A \
    --function-id 0x1::account::get_authentication_key \
    --url http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": [
    "0xdaeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5"
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Store the authentication key in a shell variable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AUTH_KEY_A=$ADDRESS_A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note, however, since the account has not yet had its authentication key rotated, there is no corresponding entry in the &lt;code&gt;account::OriginatingAddress&lt;/code&gt; table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos move view \
    --args address:$AUTH_KEY_A \
    --function-id 0x1::account::originating_address \
    --url http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, you'll get an empty vector as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": [
    {
      "vec": []
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Next, set originating address &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To ensure an entry in the &lt;code&gt;account::OriginatingAddress&lt;/code&gt; table for this new account, run &lt;code&gt;account::set_originating_address&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;You need gas for this. Ensure you have some testAPT.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos move run \
    --assume-yes \
    --function-id 0x1::account::set_originating_address \
    --profile test-profile-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result should like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Transaction submitted: https://explorer.aptoslabs.com/txn/0xbf0eac2f8a0818b9af14a5028b4116d6bff387771b5c916ab76b71573c567854?network=local
{
  "Result": {
    "transaction_hash": "0xbf0eac2f8a0818b9af14a5028b4116d6bff387771b5c916ab76b71573c567854",
    "gas_used": 444,
    "gas_unit_price": 100,
    "sender": "daeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5",
    "sequence_number": 0,
    "success": true,
    "timestamp_us": 1750150021132281,
    "version": 16439,
    "vm_status": "Executed successfully"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run the &lt;code&gt;account::OriginatingAddress&lt;/code&gt; function again. You'd see an entry now, no longer an empty vector. Let's do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos move view \
    --args address:$AUTH_KEY_A \
    --function-id 0x1::account::originating_address \
    --url http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": [
    {
      "vec": [
        "0xdaeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5"
      ]
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Next, rotate authentication Key &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, generate a new private key&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos key generate \
    --assume-yes \
    --output-file private-key-b \
    --vanity-prefix 0xbbb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result here&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": {
    "Account Address:": "0xbbb6e2c504a6faac5f6d61286cf90ce69bc86265edd27d709fd65223fe00fb6",
    "PrivateKey Path": "private-key-b",
    "PublicKey Path": "private-key-b.pub"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, rotate the authentication key of the existing onchain account to the new private key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos account rotate-key \
    --assume-yes \
    --new-private-key-file private-key-b \
    --profile test-profile-1 \
    --save-to-profile test-profile-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": {
    "message": "Saved new profile test-profile-2",
    "transaction": {
      "transaction_hash": "0x274e528b08381e39367bfb9c0820945fefb9e4015cbf7cc136656bf7791adda1",
      "gas_used": 449,
      "gas_unit_price": 100,
      "sender": "daeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5",
      "sequence_number": 1,
      "success": true,
      "timestamp_us": 1750150549220890,
      "version": 17458,
      "vm_status": "Executed successfully"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Next, we'll compare both profiles using the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos config show-profiles --profile test-profile-1
aptos config show-profiles --profile test-profile-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": {
    "test-profile-1": {
      "network": "Local",
      "has_private_key": true,
      "public_key": "ed25519-pub-0xf43cd7cd787c061c2864784e9cc62ded86310fe450ffd52e91c436ba12c18a22",
      "account": "daeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5",
      "rest_url": "http://localhost:8080",
      "faucet_url": "http://localhost:8081"
    }
  }
}
{
  "Result": {
    "test-profile-2": {
      "network": "Local",
      "has_private_key": true,
      "public_key": "ed25519-pub-0xe0501701ee022c2a1a3a665957ab4c5a668970ca5ba86caffb0638482d6b6ffe",
      "account": "daeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5",
      "rest_url": "http://localhost:8080",
      "faucet_url": "http://localhost:8081"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now lookup the authentication key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos move view \
    --args address:$ADDRESS_A \
    --function-id 0x1::account::get_authentication_key \
    --url http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": [
    "0x0bbb6e2c504a6faac5f6d61286cf90ce69bc86265edd27d709fd65223fe00fb6"
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Store the authentication key in a shell variable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AUTH_KEY_B=bbb...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export AUTH_KEY_B=$(
    aptos move view \
        --args address:$ADDRESS_A \
        --function-id 0x1::account::get_authentication_key \
        --url http://localhost:8080 \
        | jq -r '.Result[0]'
)
echo $AUTH_KEY_B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Next, look up originating address:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos move view \
    --args address:$AUTH_KEY_B \
    --function-id 0x1::account::originating_address \
    --url http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": [
    {
      "vec": [
        "0xdaeb4e5126ce109437a8a5159b4d8821ec5db0d904097da88a68ed9231c7a8f5"
      ]
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, check the originating address for the old authentication key, you'll find out it's now empty. Use the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos move view \
    --args address:$AUTH_KEY_A \
    --function-id 0x1::account::originating_address \
    --url http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": [
    {
      "vec": []
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The initial authentication key is gone!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finally, let's clean up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Delete the test profiles we setup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aptos config delete-profile --profile test-profile-1
aptos config delete-profile --profile test-profile-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Result": "Deleted profile test-profile-1"
}
{
  "Result": "Deleted profile test-profile-2"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, stop the local network and delete the private and public key files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm private-key-*
kill $LOCALNET_PID
rm -fr localnet-data
rm -fr localnet.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;You've now successfully navigated the intricate yet vital process of Aptos key account rotation.&lt;/p&gt;

&lt;p&gt;Aptos' unique account model, which decouples the authentication key from the account address, allows you to implement this critical security practice without disrupting your on-chain identity. This guide walked you through the practical steps, from setting up your local environment and generating new keys to updating your on-chain authentication and verifying the changes.&lt;/p&gt;

&lt;p&gt;As the Aptos blockchain continues to grow and evolve, so too will its security features and the best practices surrounding them. &lt;/p&gt;

&lt;p&gt;Don't hesitate to reach out to me on &lt;a href="https://x.com/dankestrel" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>privatekey</category>
      <category>security</category>
      <category>aptos</category>
      <category>web3</category>
    </item>
    <item>
      <title>Build Smarter with Aptos Move Objects: A Hands-on Tutorial for DApp Development. (Part 1)</title>
      <dc:creator>Daniel</dc:creator>
      <pubDate>Wed, 04 Jun 2025 06:23:59 +0000</pubDate>
      <link>https://forem.com/danielkestrel/build-smarter-with-aptos-move-objects-a-hands-on-tutorial-for-dapp-development-part-1-54nf</link>
      <guid>https://forem.com/danielkestrel/build-smarter-with-aptos-move-objects-a-hands-on-tutorial-for-dapp-development-part-1-54nf</guid>
      <description>&lt;p&gt;In our &lt;a href="https://dev.to/aptosnoob/understanding-structs-and-abilities-in-move-the-building-blocks-of-aptos-smart-contracts-4hnl"&gt;previous article&lt;/a&gt;, we explored Move’s struct abilities (key, store, copy, drop), the foundation of secure smart contract development. Now, let’s level up and unlock Aptos Objects, the framework that powers everything from NFTs to fungible tokens.&lt;/p&gt;

&lt;p&gt;This tutorial takes it even further by going deep into one of the most powerful concepts in Aptos Move: Objects. Move Objects provide a flexible and secure way to manage on-chain data, enabling developers to build more sophisticated and composable DApps. Whether you're looking to create advanced NFTs, manage complex game assets, or build intricate DeFi protocols, understanding Move Objects is crucial.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Composable DApps:  DApps and protocols that can interact with each other seamlessly, much like Lego bricks. If data is structured as well-defined Objects with clear interfaces, one DApp can easily read from or write to another DApp's objects (with proper authorization), leading to a highly interconnected and innovative ecosystem. For instance, an NFT created in one DApp could be used as collateral in a lending protocol built by another team, precisely because it's a well-understood "Object."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By the end of this hands-on guide, you will have a comprehensive understanding of what Move Objects are, how they function, and how to apply them in your DApp development. We'll explore their core capabilities, walk through practical code examples, and discuss best practices to help you build smarter and more securely on Aptos.&lt;/p&gt;

&lt;p&gt;Let's begin. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding Move Objects&lt;/strong&gt;&lt;br&gt;
At its heart, Move is a "resource-oriented" programming language. Unlike traditional object-oriented languages where objects are merely data structures, in Move, resources are first-class citizens that cannot be copied or implicitly discarded; they can only be moved. This fundamental principle is extended and enhanced by Move Objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are Move Objects?&lt;/strong&gt;&lt;br&gt;
In Aptos Move, an Object is a special kind of resource that acts as a container for other resources. It's safe to also view it as a smart contract account that can hold various assets and data structures, but crucially, it itself is a resource that can be owned and transferred. Imagine what flexibility this brings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key characteristics of Move Objects:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Self-Contained Entities: Objects group related resources together, allowing them to be treated as a single, cohesive entity on the blockchain.&lt;/li&gt;
&lt;li&gt;Unique Address: Every object has its own unique address on the Aptos blockchain, derived from its creation. This address allows for direct interaction and referencing.&lt;/li&gt;
&lt;li&gt;Ownership: Objects have an owner field within their &lt;code&gt;ObjectCore&lt;/code&gt; (which we'll discuss shortly). This owner can be an account address or even another object's address, enabling nested ownership structures.&lt;/li&gt;
&lt;li&gt;Resource Container: Objects can own other resources. This means you can store custom data structs (defined with &lt;code&gt;has key&lt;/code&gt; ability) directly under an object's address.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Objects have their own address and can own resources similar to an account. They are useful for representing more complicated data types on-chain as Objects can be used in &lt;code&gt;entry functions&lt;/code&gt; directly, and can be transferred as complete packages instead of one resource at a time.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Key Features and Capabilities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Move Objects are designed with flexibility and security in mind, offering several powerful capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ownership: The owner field within an object's &lt;code&gt;ObjectCore&lt;/code&gt; dictates who controls the object. This owner can be an external account or another object, enabling complex ownership hierarchies.&lt;/li&gt;
&lt;li&gt;Transferability: By default, objects are transferable. However, this can be finely controlled. You can make an object:

&lt;ul&gt;
&lt;li&gt;Ungated Transferable: Freely transferable by its owner.&lt;/li&gt;
&lt;li&gt;Untransferable: Cannot be transferred at all (e.g., for soulbound tokens).&lt;/li&gt;
&lt;li&gt;Controlled Transferable: Requires specific permissions or logic for transfer.&lt;/li&gt;
&lt;li&gt;Linear Transferable: Allows a one-time transfer by the owner.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Extensibility: Objects can be designed to be extensible, meaning new resources can be added to their storage after creation. This is crucial for dynamic DApps where an object's properties might evolve over time (e.g., adding new traits to an NFT).&lt;/li&gt;
&lt;li&gt;Immutability: While objects can be extended, certain aspects of their configuration (like whether they are deletable or initially transferable) are set at creation time and cannot be changed later. This ensures predictable behavior.&lt;/li&gt;
&lt;li&gt;Deletion: Objects can be made "deletable" at creation. Deleting an object removes it from global storage and can even refund gas costs associated with its storage, promoting efficient resource management on-chain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*&lt;em&gt;Object Creation and Configuration *&lt;/em&gt;&lt;br&gt;
Creating and configuring an object involves using specific functions and references provided by the &lt;code&gt;aptos_framework::object&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;The core of every object is the &lt;code&gt;ObjectCore&lt;/code&gt; struct, which is automatically added to any struct declared with &lt;code&gt;has key&lt;/code&gt; and used to create an object via &lt;code&gt;object::create_object&lt;/code&gt;, &lt;code&gt;object::create_named_object&lt;/code&gt; or &lt;code&gt;object::create_sticky_object&lt;/code&gt;, depending on the type of object you want to create.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct ObjectCore has key {
        /// Used by guid to guarantee globally unique objects and create event streams
        guid_creation_num: u64,
        /// The address (object or account) that owns this object
        owner: address,
        /// Object transferring is a common operation, this allows for disabling and enabling
        /// transfers bypassing the use of a TransferRef.
        allow_ungated_transfer: bool,
        /// Emitted events upon transferring of ownership.
        transfer_events: event::EventHandle&amp;lt;TransferEvent&amp;gt;,
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This leads us to the types of objects there are.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Normal Object&lt;/li&gt;
&lt;li&gt;Named Object&lt;/li&gt;
&lt;li&gt;Sticky Object&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ll explain them in details later in the second part of this article article. &lt;/p&gt;

&lt;p&gt;When you create an object, you receive a &lt;code&gt;ConstructorRef&lt;/code&gt;, that is, creating an object returns a &lt;code&gt;ConstructorRef&lt;/code&gt;, which is a one-time-use capability that allows you to configure the object during its initial setup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct ConstructorRef has drop {
    self: address;
    can_delete: bool; //true if object can be deleted. named objects are not deletable
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;ConstructorRef&lt;/code&gt; is vital for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating a Signer: &lt;code&gt;object::generate_signer(&amp;amp;constructor_ref)&lt;/code&gt; allows the object itself to act as a signer, enabling it to own and manage its own resources.&lt;/li&gt;
&lt;li&gt;Adding Initial Resources: Moving resources into the object's storage using &lt;code&gt;move_to(&amp;amp;object_signer, MyResource { ... })&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;Configuring Capabilities: Creating &lt;code&gt;TransferRef&lt;/code&gt;, &lt;code&gt;DeleteRef&lt;/code&gt;, or &lt;code&gt;ExtendRef&lt;/code&gt; from the ConstructorRef to define the object's behavior. We’ll explain these other refs shortly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Working with Objects in Move&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, we’ll see the mechanics of interacting with Aptos move objects. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Object Address Generation&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
An object's address is generated when it's created. This ensures that each object has a unique identifier on the blockchain. The object::create_object function handles this generation and returns a ConstructorRef for the newly created object's address. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Object Storage&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Objects, being resources themselves, are stored on the blockchain. When an object is created, its &lt;code&gt;ObjectCore&lt;/code&gt; is stored at its unique object address. Any additional resources that the object "owns" are also stored at this same object address. This centralizes all data related to an object under its specific on-chain address.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Object References and Abilities&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Move's type system uses "abilities" to define how a struct can be used. For objects, these abilities are crucial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;has key&lt;/code&gt;: This ability is essential for any struct that you want to store directly under an account's (or object's) address. The ObjectCore itself has key.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;has store&lt;/code&gt;: This ability means a value of this type can be stored in global storage (i.e., on-chain).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;has copy&lt;/code&gt;: Allows values of this type to be copied.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;has drop&lt;/code&gt;: Allows values of this type to be implicitly dropped at the end of their scope.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We explained abilities in details in our last class, they also apply to objects. &lt;/p&gt;

&lt;p&gt;Beyond the &lt;code&gt;ConstructorRef&lt;/code&gt;, the &lt;code&gt;aptos_framework::object&lt;/code&gt; module provides several other important references that grant specific capabilities:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DeleteRef&lt;/code&gt;: Grants the ability to delete the object from storage. This reference can only be created at object construction time if the object is configured to be deletable.&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct DeleteRef has drop, store { self: address, }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;ExtendRef&lt;/code&gt;: Allows adding new resources to the object's storage after its initial creation. This is useful for dynamic objects.&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct ExtendRef has drop, store { self: address, }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;TransferRef&lt;/code&gt;: Provides control over the object's transferability. This reference can be used to disable or re-enable ungated transfers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct TransferRef has drop, store { self: address, }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;LinearTransferRef&lt;/code&gt;: A one-time-use reference derived from a TransferRef that allows for a single, controlled transfer of the object. This is useful for "soulbound" or single-transfer assets.&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct LinearTransferRef has drop { self: address, owner: address, }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;DeriveRef&lt;/code&gt;: Used to create "derived objects" from a given object, allowing for hierarchical object structures.&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct DeriveRef has drop, store { self: address, }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conclusively, we've covered the core concepts of Aptos Move Objects, from their fundamental resource-oriented nature and key characteristics to their powerful features like &lt;code&gt;ownership&lt;/code&gt;, &lt;code&gt;transferability&lt;/code&gt;, and &lt;code&gt;extensibility&lt;/code&gt;. Understanding the &lt;code&gt;ObjectCore&lt;/code&gt; and the various &lt;code&gt;Ref&lt;/code&gt; types is crucial for configuring and interacting with objects.&lt;/p&gt;

&lt;p&gt;Mastering Move Objects isn't just about learning a technical feature; it's about gaining the ability to design sophisticated, composable DApps on Aptos.&lt;/p&gt;

&lt;p&gt;In the next part of this series, we'll look into practical code examples, demonstrating how to leverage &lt;code&gt;Normal&lt;/code&gt;, &lt;code&gt;Named&lt;/code&gt;, and &lt;code&gt;Sticky&lt;/code&gt; Objects to build smarter and more securely on Aptos. Stay tuned!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding Structs and Abilities in Move: The Building Blocks of Aptos Smart Contracts</title>
      <dc:creator>Daniel</dc:creator>
      <pubDate>Wed, 28 May 2025 14:33:12 +0000</pubDate>
      <link>https://forem.com/danielkestrel/understanding-structs-and-abilities-in-move-the-building-blocks-of-aptos-smart-contracts-4hnl</link>
      <guid>https://forem.com/danielkestrel/understanding-structs-and-abilities-in-move-the-building-blocks-of-aptos-smart-contracts-4hnl</guid>
      <description>&lt;p&gt;For developers looking to build on the Aptos blockchain, understanding Structs and Abilities in Move is not just beneficial, it's absolutely essential. These two concepts are the very bedrock upon which every Move module is constructed, especially when creating digital assets like tokens, including those conforming to the modern Fungible Asset (FA) standard on Aptos.&lt;/p&gt;

&lt;p&gt;At its core, a Move smart contract's power lies in its ability to define and manage custom data. Structs provide the blueprint for this, allowing you to encapsulate related pieces of information into organized, meaningful data types. Without them, you'd be limited to basic primitive types like booleans,  and addresses, which simply isn't enough to model complex real-world assets or application states.&lt;/p&gt;

&lt;p&gt;Intrinsically linked to structs are Abilities. These are keywords that dictate the fundamental properties and behaviors of your custom data types. Abilities define how a struct can be used, copied, stored, or dropped, acting as crucial guardrails for Aptos Move's famed resource safety guarantees. Every struct you define will inherently possess (or lack) these abilities, directly impacting how it interacts within your module and across the blockchain's global state.&lt;/p&gt;

&lt;p&gt;This guide will simplify structs and abilities, making them relatable and easy to understand without sacrificing technical accuracy. We'll explore how structs are defined, what each ability signifies, and crucially, how they collaborate to enable the secure and efficient management of digital assets. You'll learn how these concepts underpin the creation of tokens, where assets are often represented as special structs called "resources”: unique data types that cannot be duplicated or implicitly discarded. By the end, you'll have a solid grasp of how to leverage structs and abilities to write safe, composable, and efficient smart contracts on Aptos, helping you to build compelling dApps and define your own valuable digital assets. Let’s get in!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structs: Your Custom Data Blueprints&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As mentioned, a struct in Move is like a custom blueprint or a template for creating your own data types. It allows you to group related pieces of information, called "fields," into a single, organized unit. It is similar to structs in other languages like Rust or C, but with stronger restrictions in Move due to its resource-oriented model. &lt;/p&gt;

&lt;p&gt;We'll go through four stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No abilities → won't compile for most real-world usage&lt;/li&gt;
&lt;li&gt;Add drop → can discard&lt;/li&gt;
&lt;li&gt;Add store → can store in global storage&lt;/li&gt;
&lt;li&gt;Add key → can publish under an account&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Minimal &lt;code&gt;Token struct&lt;/code&gt; - No Abilities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's start with a simple, no-abilities struct: defining a Token struct. Note that a struct must be defined inside a module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module my_address::token_copy {
    use std::signer;
    use std::string::{Self, String};

    struct Token {
        name: String,
        supply: u64,
    }
    //functions go here
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;struct Token { ... }&lt;/code&gt; declares a new struct named &lt;code&gt;Token&lt;/code&gt;. It holds a &lt;code&gt;name&lt;/code&gt;, which is the name of the token, and a &lt;code&gt;supply: u64&lt;/code&gt;, which defines the total supply of the token as an unsigned 64-bit integer.&lt;/p&gt;

&lt;p&gt;Any time you create an instance of &lt;code&gt;Token&lt;/code&gt;, it will consistently have these two fields, ensuring that your data is always well-structured.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abilities: The Permissions and Powers of Your Data
&lt;/h2&gt;

&lt;p&gt;If structs are the blueprints for your data, abilities are the rules or permissions that dictate how instances of those structs can be handled by the MoveVM. They are fundamental to Move's security model, especially its "resource safety" guarantees. Each struct you define can be declared with one or more of four core abilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Four Core Abilities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The &lt;code&gt;drop&lt;/code&gt; ability&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;drop&lt;/code&gt; is a permission that allows a struct to be automatically discarded when it goes out of scope (like when a function ends). Without it, the Move compiler forces you to explicitly handle the value, meaning you must either move it somewhere useful or destroy it manually.&lt;/p&gt;

&lt;p&gt;It is used for memory management during execution only… not related to publishing or storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens with vs without drop&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, we'll create/instantiate a &lt;code&gt;Token&lt;/code&gt; struct without the &lt;code&gt;drop&lt;/code&gt; ability to observe how Move enforces explicit value handling&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module my_address::token_drop {
    use std::signer;
    use std::string::{Self, String};

    struct Token {
        name: String,
        supply: u64,
    }

    public entry fun initialize(admin: &amp;amp;signer, name: String, supply: u64) {
        let token = Token {
            name,
            supply,
        };
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without drop, the &lt;code&gt;Token&lt;/code&gt; cannot be silently discarded when the function ends, hence the error below. You must either transfer ownership or explicitly destroy it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbi5oicd8hd92r6eg50o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbi5oicd8hd92r6eg50o.png" alt="Compilation error message showing code wouldn't work without the drop ability in aptos move" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To fix this, we have to add &lt;code&gt;drop&lt;/code&gt; ability to the token struct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module my_address::token_drop {
    use std::signer;
    use std::string::{Self, String};

    struct Token has drop {
        name: String,
        supply: u64,
    }

    public entry fun initialize(admin: &amp;amp;signer, name: String, supply: u64) {
        let token = Token {
            name,
            supply,
        };
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Ideally, a token should not be droppable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This will compile with the result below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphzeti3mmdwyprxyzzde.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphzeti3mmdwyprxyzzde.png" alt="Code compiles successfully with drop ability" width="800" height="107"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The &lt;code&gt;copy&lt;/code&gt; ability&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;copy&lt;/code&gt; ability in Aptos Move is a fundamental feature that determines whether a struct can be duplicated. It plays a crucial role in how data is handled, ensuring safety and preventing unintended behavior in smart contracts.&lt;/p&gt;

&lt;p&gt;It allows a struct to be explicitly duplicated using the copy keyword. Without copy, a struct cannot be copied; it can only be moved (that is, ownership transferred).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens with vs without &lt;code&gt;copy&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below is an example of code without the copy ability.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module my_address::token_copy {
    use std::signer;
    use std::string::{Self, String};

    struct Token has drop {
        name: String,
        supply: u64,
    }

    fun consume_token(t: Token){}

    public entry fun initialize(admin: &amp;amp;signer, name: String, supply: u64) {
        let token = Token {
            name,
            supply,
        };

        consume_token(token);
        consume_token(token);
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;Token&lt;/code&gt; is not &lt;code&gt;copy&lt;/code&gt;able, calling &lt;code&gt;consume_token(token)&lt;/code&gt; moves the value. After this call, &lt;code&gt;token&lt;/code&gt; can’t be used again because its ownership has been transferred.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;token&lt;/code&gt; is no longer valid in this scope.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The memory that held &lt;code&gt;token&lt;/code&gt;'s data is now owned by the first &lt;code&gt;consume_token&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An attempt to pass &lt;code&gt;token&lt;/code&gt; again will result in error, and will not compile.&lt;/p&gt;

&lt;p&gt;See the error message here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wf67zxujc6907samy3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wf67zxujc6907samy3a.png" alt="Compilation error message showing code wouldn't work without the copy ability in aptos move" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's add &lt;code&gt;copy&lt;/code&gt; ability to Token.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module my_address::token_copy {
    use std::signer;
    use std::string::{Self, String};

    struct Token has drop, copy {
        name: String,
        supply: u64,
    }

    public entry fun initialize(admin: &amp;amp;signer, name: String, supply: u64) {
        let token = Token {
            name,
            supply,
        };

        consume_token(token);
        consume_token(token);
    }

     fun consume_token(t: Token){}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Ideally, a token shouldn't be copyable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here we go. Compiled successfully. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foruim6m74p4v8wy4ydu8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foruim6m74p4v8wy4ydu8.png" alt="Successful compilation message" width="800" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can also make the copy operation explicit by writing &lt;code&gt;consume_token(copy token)&lt;/code&gt;, which indicates that the &lt;code&gt;token&lt;/code&gt; value should be duplicated before being passed to the function.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The &lt;code&gt;key&lt;/code&gt; ability&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In Aptos Move, a struct becomes a resource when it has the key ability (and typically also store). This combination marks the struct as a persistent, account-bound data type that can be stored in global storage. Here's the definitive explanation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct Token has key, store {  // this is a resource
    name: String,
    supply: u64
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If a struct has the key ability, it automatically has the store ability, even if it's not explicitly declared.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;key&lt;/code&gt; ability implies the struct, in this case &lt;code&gt;Token&lt;/code&gt;, can be stored in global storage, and can be accessed from same. This makes &lt;code&gt;Token&lt;/code&gt; a Resource. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Characteristics of Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Stored in Global Storage&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lives under an account (move_to(account, resource))&lt;/li&gt;
&lt;li&gt;Accessed via borrow_global/move_from&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Singular Per Account&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only one instance per (account_address, struct_type) pair&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Explicit Lifetime Management&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be explicitly stored/retrieved/deleted&lt;/li&gt;
&lt;li&gt;Cannot be implicitly dropped or copied (no drop ability)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Global Storage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Operations around global storage are critical to the functioning of the &lt;code&gt;key&lt;/code&gt; ability.&lt;/p&gt;

&lt;p&gt;Global Storage is the on-chain storage where values are persistently stored at an account address. Unlike local variables that disappear after a function finishes running, global storage persists across transactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global Storage Operators&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2qh4oc3vjiu26te2ywg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2qh4oc3vjiu26te2ywg.png" alt="Image from aptos docs showing the different global storage operators" width="800" height="371"&gt;&lt;/a&gt;&lt;br&gt;
Image source: &lt;a href="https://aptos.dev/en/build/smart-contracts/book/global-storage-operators" rel="noopener noreferrer"&gt;Aptos docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These operators all work with &lt;code&gt;key&lt;/code&gt; ability.&lt;/p&gt;

&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module my_address::token_key {
    use std::signer;
    use std::string::{Self, String};

    struct Token has key {
        name: String,
        supply: u64,
    }

    public entry fun initialize(admin: &amp;amp;signer, name: String, supply: u64) {
        let token = Token {
            name,
            supply,
        };

        move_to(admin, token); // move the token to the admin's account
    }   
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code compiles successfully. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;move_to(admin, token);&lt;/code&gt;&lt;br&gt;
Stores the token under the admin's account in global storage. This is why Token needs the key ability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Acquires&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;acquires&lt;/code&gt; keyword in Move is used to explicitly declare that a function may access or modify a resource type stored in global storage. It's a safety feature that ensures the compiler knows which resources a function interacts with. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This annotation tells the Move compiler that this function will access the &lt;code&gt;Resource&lt;/code&gt; from global storage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It's required whenever a function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads a resource (borrow_global)&lt;/li&gt;
&lt;li&gt;Modifies a resource (borrow_global_mut)&lt;/li&gt;
&lt;li&gt;Removes a resource (move_from)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example using the &lt;code&gt;acquires&lt;/code&gt; keyword. Note this is a basic code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module my_address::token_key {
    use std::signer;
    use std::string::{Self, String};

    struct Token has key {
        name: String,
        supply: u64,
    }

    public entry fun initialize(admin: &amp;amp;signer, name: String, supply: u64) {
        let token = Token {
            name,
            supply,
        };

        move_to(admin, token); // move the token to the admin's account
    }

//use acquires
    public fun get_balance(addr: address): u64 acquires Token {
        let token = borrow_global&amp;lt;Token&amp;gt;(addr);
        token.supply
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, &lt;code&gt;acquires&lt;/code&gt; grants the &lt;code&gt;get_balance&lt;/code&gt; function access to the Token resource. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;borrow_global&amp;lt;Token&amp;gt;(addr);&lt;/code&gt; gets an immutable reference to the Token resource stored at addr, returns a reference that allows reading but not modifying.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Acquires is optional in Move 2.x as the compiler can now infer this annotation when necessary&lt;/em&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We'll dive deeper into other global operators in our subsequent classes. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The &lt;code&gt;store&lt;/code&gt; ability&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And now, to &lt;code&gt;store&lt;/code&gt; ability.&lt;br&gt;
According to the aptos move docs, &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;store&lt;/code&gt; ability allows values of types with this ability to exist inside a struct (resource) in global storage, but not necessarily as a top-level resource in global storage. This is the only ability that does not directly gate an operation. Instead, it gates the existence in global storage when used in tandem with &lt;code&gt;key&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module my_address::token_store {
    use std::signer;
    use std::string::{Self, String};

    struct Token has key, store {
        name: String,
        supply: u64,
    }

    struct Vault has key {
        token: Token,
    }

    /// initialize a Vault that wraps a Token and store it in the signer's account
    public entry fun initialize(admin: &amp;amp;signer, name: String, supply: u64) {
        let token = Token {
            name,
            supply,
        };

        let vault = Vault {
            token,
        };

        move_to(admin, vault); 
    }


    public fun get_token_supply(addr: address): u64 acquires Vault {
        let vault = borrow_global&amp;lt;Vault&amp;gt;(addr);
        vault.token.supply
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we try to compile this without the &lt;code&gt;store&lt;/code&gt; ability on &lt;code&gt;Token&lt;/code&gt;, the compiler will throw an error because storing a value inside another struct requires the &lt;code&gt;store&lt;/code&gt; ability. You can try removing it to see the error for yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Struct Ability Requirements in Aptos Move&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Golden Rule:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When a struct has an ability, all its fields must have:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmde5m7d2utz5i45d8v2h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmde5m7d2utz5i45d8v2h.png" alt="A simple diagram showing different behaviours of structs with respective abilities in aptos move" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why This Matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;copy+drop = Temporary data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;key+store = Global storage resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prevents unsafe combinations at compile time&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conclusively, remember these constraints aren't limitations. They are Move's way of eliminating whole classes of bugs at compile time. Whether you're storing assets globally with key or working with temporary copy data, these rules ensure your contracts behave predictably. Now that you understand how abilities propagate through structs, you're ready to design safer, more efficient Move modules.&lt;/p&gt;

&lt;p&gt;How will you apply these rules in your next smart contract?&lt;/p&gt;

&lt;p&gt;You can access the examples on &lt;a href="https://github.com/Move-Mastery-Path/aptos-move-tutorials/tree/main/04-strut-abilities" rel="noopener noreferrer"&gt;github&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;You can also reach me on &lt;a href="https://x.com/AptosNoob" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; now X.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>aptos</category>
      <category>smartcontract</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
