Aptos Object and Token V2.0 Explained in 10,000 Words - OverMind

Author:TC_OverMind

Aptos Object Standard, Token V2 and Sword of a Thousand Truths tasks.

AIP-10 Object It was introduced before the implementation of Token V2 and Fungible Assets, but it is only through real-life use cases that we can better understand AIP-10.

The Object Standard is highly composable, and with Token V2, we can see that an NFT of type V2 consists of four components:

  1. Token Object - The Token itself.
  2. Collection Object - The collection to which the Token belongs.
  3. PropertyMap Object - Holds customizable properties about the Token, such as game data, rarity, and so on.
  4. Royalty Object - the percentage of royalties paid to the creator.

These four components make up the complete Token V2 and are stored in the aptos-token-object directory of the aptos_token file. In addition, Aptos implements a Fungible Asset module and provides Metadata Objects for Fungible Assets to cover the most common usage scenarios, but developers are still able to create unlimited customized assets through the Object Standard.

In a medium-difficulty task for Overmind, inspired by South Park's "Make love, not Warcraft" episode, we delved into Token V2 and explored the use of property maps, capabilities, and collections. capabilities, and collections.

Object Standard

Objects, Accounts, and Events

Objects and accounts are very important in Aptos Move. They are the only two resources that can emit events. We can easily verify this in the events module, since only the object respond in singing accountThe two modules are declared as friend modules. This means that only these two modules can invoke the functions in the event module labeled public(friend) The function of the

As a refresher: a friend is a move function visibility declaration that sits between public and private. A friend module can access a module labeled public(friend) The function of the

If an address is stored below the Account This resource, we will consider it as an account.

struct Account has key, store {
authentication_key: vector,
sequence_number: u64,
guid_creation_num: u64,
coin_register_events: EventHandle,
key_rotation_events: EventHandle,
rotation_capability_offer: CapabilityOffer,
signer_capability_offer: CapabilityOffer,
}

Similarly, if an address is stored below ObjectCore This resource is considered to be an object.

struct ObjectCore has key {
guid_creation_num: u64,
owner: address,
allow_ungated_transfer: bool,
transfer_events: event::EventHandle,
}

We can do this through the Account The GUID of the object is used to create the object, and the number of objects created is recorded. Because the object (object) has its own address, and can generate its own signer (signer), so the object (Object) can use the same method to generate sub-objects. Object (object) also has several functions for interacting with accounts, such as object creation and retrieving objects with account addresses and GUIDs. However, Aptos no longer recommends the UUID method of object creation, and will instead use the transaction_context AUID (aptos unique identifier).

Of course there are some differences between the two, accounts are more focused on users and wallets while objects are more focused on data and transfers. A good way to quickly see what is important in a module is to look at the events it emits. These are permanently recorded on the chain for all to index. Both account and object modules can be accessed via the new_event_handle function to create user defined events and natively defined events. EventHandle, the native events defined in the account are KeyRotationEvent respond in singing CoinRegistrationEventand the object contains only TransferEvent Structure .

Key rotation allows a wallet to employ different public and private keys and still recover correctly; we have done this through the coin (loanword)modular register function to enable an account to send and receive coins it has registered, similar to the approve function in Solidity.

The `TransferEvent` contains only three events of type address The fields of the to(math.) genusfrom respond in singing objectThis means for tokens, capabilities, or special features associated with the object such as royalties. This means that the transfer of tokens, capabilities, or special features associated with objects such as royalties - all of these are done in a flexible and combinable way.

struct TransferEvent has drop, store {
object: address,
from: address,
to: address.
}

Here's another thing to keep in mind.ObjectStructures contain only one field of type address, which is used to point to the address of the object, and the structure itself is generic.

struct Object has copy, drop, store {
inner: address,
}

This makes it easy to convert different resources at the same address into objects. See the object module's convertfunction. The generalization T will only be used to verify that a resource of that type exists at the current address.

public fun convert(object: Object): Object {
address_to_object(object.inner)
}
public fun address_to_object(object: address): Object {
assert!(exists(object), error::not_found(EOBJECT_DOES_NOT_EXIST));
assert!(exists_at(object), error::not_found(ERESOURCE_DOES_NOT_EXIST));;
Object { inner: object }
}

As a refresher: accounts and objects are at the heart of Move. Accounts are for wallets and users, and objects focus on digital assets and their transfer.

Object Standards Explained

Looking at the Aptos reference documentation, the first thing that strikes me is that the object has a large number of structs and functions. However, they can be easily grouped together, as many of the operations are similar or encapsulate underlying functions.

First, take a look. ObjectCore This resource. It has four fields.

  1. guid_creation_num Ensure that all objects are unique when created and can be tracked and identified.
  2. ownerUsed to specify ownership, which can be the user or another person who has an interest in the
  3. allow_ungated_transferUsed to control the transfer of objects. If the transfer of tokens is unlimited(ungated), it can be distributed freely as in an airdrop. If not, it can only be distributed through the TransferRefmaybe LinearTransferRef to explicitly authorize, which is useful for locking (freezing) tokens in use cases for betting, investing, or even fraud prevention strategies
  4. transfer_eventsIssued when there is a change in ownership TransferEventevent

TransferRef is one of many "refs". Further, we see that there are two more object structures (they are not as good as the ObjectCore important), and some other refs (essentially various licenses):

  • ConstructorRef - It is only generated when the object is created and can be used to configure the object, generating other "refs". Looking through the code we see that it only drop`This capacity, no.' copyrespond in singing storeSo it can't be stored or copied, it can only be used once. Just like the constructor in a Solidity contract.
  • DeleteRef - Used to delete objects.
  • ExtendRef- Allows additional events or resources to be stored under the address of the object.
  • TransferRef - For object transfer.
  • LinearTransferRef- Objects can only be transferred from the current owner once.
  • DeriveRef- Allows creation of derived objects from the current object.

In all refs.ConstructorRef It's the most important. Let's see. generate_x_ref series of functions, all of which require ConstructorRef as input and directly from the ConstructorRefitself generates the corresponding ref.ConstructorRefIt can also be accessed through the (address|object)_from_constructor_ref to get the address of the object or the object itself, as well as through the generate_signer to generate a signer for the object, in a manner similar to the `signer_capability` of a resource account.

The second most important ref is DeleteRefImagine if someone could delete tokens or NFTs at will. Imagine if someone could delete tokens or NFTs at will, there would be a lot of lost assets. Functions can_generate_delete_ref` is used to check whether the creation of DeleteRefIt requires `ConstructorRef` as a parameter.

The core operation of an object is transfer. For this reason, the object module provides a series of transfer (transfer) related functions, convenient in different scenarios call. Let's look directly at the core one transfer_raw, most of the transfer-related functions are wrapped with the transfer_raw Functions. In addition, there are functions specialized for unrestricted(ungated) transfers.

Let's look at the right side of the transfer_raw function, which at line 421 checks that the object and all its descendants (i.e., nested objects) are also unbounded (ungated). This check for descendants only allows up to 8 levels of nesting. The next few lines check to see if the sender and receiver are the same, then emit an event and set the new owner to the receiver's address.

We'll dive deeper into how to freeze objects that are transferred(ungated) without restriction in Part 2, which explores the token V2 standard. You can use the LinearTransferRef Covering and performing threshold transfers is beyond the scope of this task.

This is what the Object Standard is all about! This module makes improvements to ownership, composability, capabilities, and transfer management.

II: About Token V2 and its combinable objects.

In Part I, we discussed the Object standard and its composability, ownership, transfer, and capability. Next, let's look at the specific implementation of object in NFT - Token V2.

For a quick overview of what's in `aptos_token.move`, look at the followingreference document. We can categorize these functions based on the beginning of the function name:

- A view function that starts with "is / are" returns a boolean value indicating whether the state is true or false.
- The ones that start with "set / update / add" are setter functions, which change the internal value of an object.

In addition to these two types of functions, there are a few key functions that we can look at:

  • create_collection: First a Collection object and a Royalty object are created, then an `AptosCollection` object is created and stored at the address of the Collection object. The `Collection` structure is used to hold the basic properties of the collection, such as description, name, etc. The `AptosCollection` holds additional properties, such as the description of whether or not modification is allowed, and various collection-related `refs`, such as `collection::MutatorRef`.
  • mint_internal::mintrespond in singing mint_soulbound Both of them mainly call this function internally. This function creates a `Token` object, and then creates the required `refs`, such as `MutatorRef` and `BurnRef`, based on the corresponding Collection objects, which are used to create the `AptosToken` object, and similarly, the new `AptosToken` is stored under the address of the `Token` object. These 'refs' will be used to create `AptosToken` objects, and similarly, the new `AptosToken` will be stored under the address of the `Token` object. Finally, the `Token`'s `constructor_ref` is used to create a `PropertyMap` object, which is used to hold the token's custom properties. Similar to `AptosCollection`, `AptosToken` is used to store `Token` related 'refs', such as `token::MutatorRef`.
  • freeze / unfreeze_transfer: These two functions call the `enable / disable_ungated_transfer` function of the object module. Essentially, `freeze_transfer` disables free transfers of NFTs, allowing only authorized transfers (via `TransferRef`).
  • burn: Objects are destroyed by deconstruction, after which the `burn` function of the `property_map` module and the `token` module is called to destroy the corresponding object.

If you've developed Solidity programs before, this may seem a bit familiar. The `aptos_token` object has its own address and signing authority, reminiscent of the ERC721 token contract, and the casting and destruction of NFTs can be accomplished by calling the appropriate methods of the aptos_token module without first determining the user's address. In terms of implementation, the aptos_token module creates four objects and stores them at different addresses.

We won't be discussing the royalty object in this article because we don't use it in our Longswords and Dragons quest.

There are four main objects that make up aptos_token

Simply put, if under the following address there is ObjectCoreThis resource is considered to be an Object. Usually every object has a main object, such as `Token`. The `Token` object also contains two objects, `PropertyMap` and `Royalty`, which are stored at the same address, and are secondary to `Token`, so we call them resources, and refer to them in code with `Object` or `Object`. Royalty>`. The same is true for a `Collection` object. During creation, it creates its own `Royalty` object with its internal Supply structure, but we consider them all resources of the `Collection` object.

Collection objects

There are three types of `Collections`:

- Fixed Supply: The `FixedSupply` structure is used internally to keep track of the max supply and current supply of the set.

- Unlimited Supply collection: internally uses the `UnlimitedSupply` struct, which keeps track of the current casting and circulation (current supply = total minted - total burned), but has no maximum limit.

- Untracked collection: no record of supply or circulation. We can create such collections using `create_untracked_collection`. Note that this function has a TODO: "Hide this until we bring back meaningful way to enforce burns".

For collections, the most important attributes are creator, name, description and uri. As we can see, there are most functions that modify and view these fields. Additionally, collections need to use their name as a seed (seed) and the creator's address to generate a deterministic address, which is done internally by calling the `object` module `create_named_object`, which creates the address of the collection's object by using a sha-256 hash of these two inputs.

In addition to the events that can be triggered in a custom module (as shown in the Longswords and Dragons task), the Supply structure contained in the Collection object also triggers events when a Token is cast and destroyed.

Token Objects

A `Token` combines all the aspects needed for an NFT. It has its own description, name, and uri, and also stores the collection it belongs to and the index - its unique identifier within the collection.

To understand the process of creating a Token object, let's look at the `create_common` inline function. It first gets information about the collection to which the token belongs, uses the total_minted number of casts in the collection to generate the token index, and then creates the `Token` object, along with the token's royalty resources if needed. This function takes `ConstructorRef` as an argument, and all other functions call the object module's object creation function to get a `ConstructorRef` before calling `create_common`. If `create_named_token` is called to create a Token, the seed (seed) is created from a hash of its collection name and its own name.

Note: token::create_from_account is currently marked as deprecated, but is still in use. It may be possible to move to using the uuid from the transaction context.

PropertyMap Objects

Here we need to understand two structures `PropertyMap` and `PropertyValue`. The `PropertyMap` itself is a wrapper around the `SimpleMap`. The name of the property (of type String) is used as the key; the type and value of the property are converted to UTF-8 bytes, and together they form `PropertyValue`, which is used as the value of `SimpleMap`. In order to use `PropertyMap` better, we need to distinguish the type of each part, so we summarize it:

  • keys - `String`
  • types - `u8`, each type pair has a corresponding value
  • values - `vector`, serialized via BCS

Note that the `prepare_input` function takes three parameters of type `String`, `String`, `vector`, which are different from the three fields that make up the `PropertyMap`, which is a bit confusing. Here, for convenience/readability, the type of the value is passed in as `String`. Inside `prepare_input`, an inline function `to_internal_type` is used to convert the type input to a value of 0-9 (u8). Similarly, there is a `to_external_type` function that converts this internal representation back to a more readable string.

The property_map module also has some functions similar to the simple_map module, such as `contains_key`, `length`, `add` and so on. The `init` function stores the `PropertyMap` object generated by `prepare_input` at the address of the `Token`; `burn` is used to delete the corresponding `PropertyMap` object when the `Token` is destroyed. The rest are read functions, which are used to read values of a certain type conveniently, such as `read_bool`, `read_u8`, and so on.

Move serialization: bcs and from_bcs

As a strongly typed language, Move can only convert integers to integers of different sizes (e.g., u8 to u16). The rest of the types can be converted to different sizes (e.g., u8 to u16) with the BCS to sequence the data into a byte array (bytes):

  • bcs::to_bytes(variable): Convert any type to an array of bytes in BCS format (vector). This is the only function in the bcs module.
  • from_bcs::to_x(variable): converts data in BCS format to the desired Move type. Replace x with the type, e.g. from_bcs::to_u8from_bcs::to_boolThe

This allows us to convert between Move types and byte groups (bytes, vector) in a unified way, very cleanly.

OverMindis a Move language education platform where you can learn Aptos Move smart contracts, participate in challenges to earn rewards and build a blockchain resume just for you.

All of the above content is reproduced from the Internet, does not represent the position of AptosNews, is not investment advice, investment risk, the market need to be cautious, such as infringement, please contact the administrator to delete.

Like (0)
Donate WeChat Sweep WeChat Sweep Alipay Sweep Alipay Sweep
Previous July 2, 2023 at 2:06 pm
Next July 5, 2023 at 7:52 pm

Related posts

Leave a Reply

Please Login to Comment
WeChat Sweep
Baidu Sweep

Subscribe to AptosNews

Subscribe to AptosNews to stay on top of Aptos.


This will close in 0 seconds

This site has no investment advice, investment risk, the market needs to be cautious.