Wrapping Token v1 to Digital Assets

Samundra Karki
MokshyaProtocol
Published in
5 min readJun 23, 2023

This blog is written over the pretext that reader has already gone through the previous blog ,on writing modules in Aptos Move. The Aptos ecosytem has opted for the name “Digital Assets Standard” for the new standard

Aptos has started using a new resource management model i.e. Object Model. The Object Model enables the storage of resources within a single address and provides a comprehensive model for managing a variety of resource control and ownership. This enables common interfaces like tokens to be managed efficiently. This has led to the introduction of a new token standard — “Digital Asset Standard” which is aimed at increasing the functionality associated with tokens and leveraging the full potential of the Object Model.

In this medium article, we go through the token wrap program from Mokshya Protocol. The program burns token-v1 NFT and mints the same NFT in Digital Assets. The program should be useful to projects which are trying to utilize the functionality of Digital Assets in the future. Here is the GitHub repo to view the complete code.

Mokshya is an open-source protocol building smart contracts, SDKs and developers tools on the Aptos Blockchain.

Introduction to Digital Assets Wrapper Module

The Digital Assets Wrapper module is designed to wrap Token v1 into Digital Assets, allowing for seamless migration while preserving the ownership and properties of the original tokens. By leveraging the capabilities of tokenv1(burn capability), this module simplifies the process of upgrading token standards.

Assumptions

A variety of tokens are minted in a variety of ways. Most of them utilize the resources account for minting which sets the creator to be the resource account (which is bound to the module). In this regard, the program has two main assumptions:

  1. For a collection to initiate wrapping, it must have the royalty payee address account. This is to verify that the initiator is indeed an authority of the collection
  2. The collection must have” burn_by_owner” set to true.

Understanding the Code

Let’s dive into the code and understand the key components of the Token v2 Wrapper module.

Dependencies

The module relies on various dependencies, mostly tokenv1 (0x3) and tokenv2(0x4) imported as tokenv1 and tokenv2 respectively. Below is the Move.toml file where the packages are imported:

[package]
name = 'wrapper'
version = '1.0.0'
[addresses]
std = "0x1"
aptos_std = "0x1"
aptos_framework = "0x1"
aptos_token_objects = "0x4"
aptos_token="0x3"
wrapper="_"
[dependencies]
AptosFramework = {git = 'https://github.com/aptos-labs/aptos-core.git',rev='main',subdir = 'aptos-move/framework/aptos-framework'}
AptosTokenObjects = {git = 'https://github.com/aptos-labs/aptos-core.git',rev='main',subdir = 'aptos-move/framework/aptos-token-objects'}
AptosStdlib = {git = 'https://github.com/aptos-labs/aptos-core.git',rev='main',subdir = 'aptos-move/framework/aptos-stdlib'}
AptosToken = {git = 'https://github.com/aptos-labs/aptos-core.git',rev='main',subdir = 'aptos-move/framework/aptos-token'}

ERRORS

The module defines the following errors as well

- `ENO_COLLECTION_DOESNT_EXIST`: Indicates that the collection doesn’t exist.

- `ENO_NOT_ROYALTY_RECEIVER`: Indicates that the royalty receiver doesn’t match.

- `ENO_NO_TOKEN_IN_TOKEN_STORE`: Indicates that no tokens are available in the token store.

- `ENO_ALREADY_INITIATED`: The collection is already initiated

- `ENO_NO_WRAP_OBJ`: The collection is not initiated

Struct: Wrapper

The `Wrapper` struct is stored in an object which verifies on creation the collection owner has initiated the wrapping to tokenv2 for the collection.

        struct Wrapper has key
{
collection:String,
creator_address:address,
treasury_cap:account::SignerCapability,

}

Each field is explained below:

- `collection`: The name of the collection associated with the token.

- `creator_address`: The address of the token creator.

- `treasury_cap`: The signer capability for the treasury account.

Function: init_module

This function creates a map to store the object address used to store the Wrapper struct.

        struct ObjectMap  has key {
wraopObjMap: SimpleMap<vector<u8>,address>,
}

Simple Map is used to map the name of the collection with the object address.

Function: initiate_collection

The `initiate_collection` function initializes the token wrapping process. It accepts the following parameters:

- `owner`: The signer reference for the owner of the token.

- `creator_address`: The address of the token creator.

- `collection_name`: The name of the collection.

- `token_name`: The name of the token.

- `property_version`: The version of the token’s properties.

One important factor is the creator must send in a token from the collection to obtain the royalty-payee address which in Token V1 wasn’t stored in CollectionData instead stored in TokenData. This is a major distinction between the two token standards

The function performs the following steps:

1. Verifies the existence of the collection in Token v1 using `tokenv1::check_collection_exists`.

2. Extracts the royalty payee address from the token’s royalty information and verify that it matches the owner’s address.

3. Creates a named object for the collection using `object::create_named_object` and generates a signer using `object::generate_signer`.

4. Creates a resource account for the collection using `account::create_resource_account`.

5. Retrieves mutability configuration for the collection and token from Token v1 using various `tokenv1` functions.

6. Calls `tokenv2::create_collection` to create the corresponding collection in Token v2, providing the necessary information.

7. Stores the object address in the simple map

Function: wrap_token

The `wrap_token` function wraps a Token v1 token into Digital Assets. It takes the following parameters:

- `token_holder`: The signer reference for the token holder.

- `token_name`: The name of the token.

- `property_version`: The version of the token’s properties.

- `wrap_obj`: The wrapped token object.

The function performs the following steps:

1. Retrieves the token holder’s address from the signer reference.

2. Retrieves the information of the wrapped token from the global storage.

3. Creates a signer from the treasury capability of the wrapped token using `account::create_signer_with_capability`.

4. Generates a new token creation number using `account::get_guid_next_creation_num`.

5. Retrieves the token data ID for the Token v1 token using `tokenv1::get_tokendata_id`.

6. Burns one Token v1 token from the token holder using `tokenv1::burn`.

7. Mints a new Digital Asset using `tokenv2::mint`, providing the necessary information.

8. Transfers the minted Digital Asset to the token holder using `object::transfer`.

View Function: wrap_obj_address

The function sends the address of the object which stores the Wrapper struct for the collection.

Publishing Module

Firstly, let’s create an account and designate test-net as our cluster

aptos init

Aptos CLI is now set up for account 20634774e3d40bf68fa86101723f2bc36c7b57bc5220e401475f2f1b27377a10 as profile default! Run `aptos — help` for more information about commands
{
“Result”: “Success”
}

Now, you can use the address obtained to compile your code

aptos move compile --named-addresses token_vesting="0xaddress_obtained_in_above_command"

Try to debug any errors mentioned during compiling.

Now, we are ready to publish the module. Use the following command in terminal

aptos move publish --named-addresses wrapper="0xaddress_obtained_in_above_command"

SDK AND TEST CODE

The SDK for testing and utilizing the smart contract is added in the repo respectively.

Conclusion

The Digital Asset Wrapper module simplifies the migration process from Token v1 to Digital Asset. By encapsulating the necessary functions and providing a straightforward interface, developers can easily upgrade their token standards while preserving ownership and properties. This module is an example of how to achieve the transition between the two standards.

To explore further and implement the Digital Asset Wrapper module in your projects, refer to the official APTOS framework documentation and relevant library references. Happy coding and enjoy the enhanced capabilities of Digital Asset!

--

--