From f48d7bea975f309566e3bc77d4294a53ae29a017 Mon Sep 17 00:00:00 2001 From: Samuel Rufinatscha Date: Thu, 1 Aug 2024 09:33:08 +0200 Subject: [PATCH 01/78] docs(advanced-topics): Refactor `advanced-topics` (#1491) * refactor: Remove unnecessary files, update asset-tokenization.mdx * fix: Broken link * refactor: Add Stardust on Move * Rename to IOTA Co-authored-by: Dr-Electron * Rename to IOTA Co-authored-by: Dr-Electron * Rename to IOTA Co-authored-by: Dr-Electron * Rename to IOTA Co-authored-by: Dr-Electron * Rename to IOTA Co-authored-by: Dr-Electron * refactor: Add `asset_tokenization` ref * fix: Kiosk doc path * fix: OTW doc path * fix: example path * fix: remove wasm link * fix: host template as a package * fix: improve template intro * fix: Format * fix: Fix alteration * fix: Fix warning * fix: Fix warning * refactor: Restore _graphql-migration.mdx * refactor: Move content of stardust-on-move to migration-process.mdx * Fix overwritten changes * Apply suggestions from code review --------- Co-authored-by: Dr-Electron --- docs/content/developer/advanced.mdx | 6 - .../developer/advanced/_graphql-migration.mdx | 2 +- .../developer/advanced/asset-tokenization.mdx | 1324 ++++++----------- .../developer/advanced/custom-indexer.mdx | 163 -- .../advanced/move-2024-migration.mdx | 316 ---- .../developer/advanced/stardust-on-move.mdx | 165 -- .../developer/stardust/migration-process.mdx | 96 +- docs/content/sidebars/developer.js | 13 - .../asset_tokenization/Move.toml | 10 + .../asset_tokenization/sources/proxy.move | 115 ++ .../sources/tokenized_asset.move | 254 ++++ .../asset_tokenization/sources/unlock.move | 115 ++ .../asset_tokenization/tests/tests.move | 1186 +++++++++++++++ .../asset_tokenization/template/Move.toml | 12 + .../template/sources/genesis.move | 20 + .../template/sources/template.move | 54 + 16 files changed, 2264 insertions(+), 1587 deletions(-) delete mode 100644 docs/content/developer/advanced/custom-indexer.mdx delete mode 100644 docs/content/developer/advanced/move-2024-migration.mdx delete mode 100644 docs/content/developer/advanced/stardust-on-move.mdx create mode 100644 examples/move/asset_tokenization/asset_tokenization/Move.toml create mode 100644 examples/move/asset_tokenization/asset_tokenization/sources/proxy.move create mode 100644 examples/move/asset_tokenization/asset_tokenization/sources/tokenized_asset.move create mode 100644 examples/move/asset_tokenization/asset_tokenization/sources/unlock.move create mode 100644 examples/move/asset_tokenization/asset_tokenization/tests/tests.move create mode 100644 examples/move/asset_tokenization/template/Move.toml create mode 100644 examples/move/asset_tokenization/template/sources/genesis.move create mode 100644 examples/move/asset_tokenization/template/sources/template.move diff --git a/docs/content/developer/advanced.mdx b/docs/content/developer/advanced.mdx index c05cbda710f..ff2220fe649 100644 --- a/docs/content/developer/advanced.mdx +++ b/docs/content/developer/advanced.mdx @@ -12,12 +12,6 @@ Asset tokenization refers to the process of representing real-world assets, such Go to [Asset Tokenization](advanced/asset-tokenization.mdx). -## Custom Indexer - -You can build custom indexers using the IOTA micro-data ingestion framework. To create an indexer, you subscribe to a checkpoint stream with full checkpoint content. Establishing a custom indexer helps improve latency, allows pruning the data of your IOTA Full node, and provides efficient assemblage of checkpoint data. - -Go to [Custom Indexer](advanced/custom-indexer.mdx). - [//]: # () [//]: # (## Migrating to GraphQL ) diff --git a/docs/content/developer/advanced/_graphql-migration.mdx b/docs/content/developer/advanced/_graphql-migration.mdx index e00f9df6e8b..2e7ecfab2cf 100644 --- a/docs/content/developer/advanced/_graphql-migration.mdx +++ b/docs/content/developer/advanced/_graphql-migration.mdx @@ -144,7 +144,7 @@ The cursor is now passed in the `after` (or `before`) fields on the connection, ## Related links - + - [GraphQL reference](../../references/iota-graphql.mdx): Auto-generated GraphQL reference for IOTA RPC. - [GraphQL quick-start](../getting-started/graphql-rpc.mdx): Querying IOTA RPC with GraphQL gets you started using GraphQL to query the IOTA RPC for on-chain data. - [GraphQL concepts](../graphql-rpc.mdx): GraphQL for IOTA RPC examines the elements of GraphQL that you should know to get the most from the service. \ No newline at end of file diff --git a/docs/content/developer/advanced/asset-tokenization.mdx b/docs/content/developer/advanced/asset-tokenization.mdx index 5d2a8266464..885f876071b 100644 --- a/docs/content/developer/advanced/asset-tokenization.mdx +++ b/docs/content/developer/advanced/asset-tokenization.mdx @@ -3,50 +3,49 @@ title: Asset Tokenization description: Learn how to tokenize assets on the IOTA blockchain. Asset tokenization refers to the process of representing real-world assets, such as real estate, art, commodities, stocks, or other valuable assets, as digital tokens on the blockchain network. --- -import InitializeIOTAClientCli from "../../_snippets/initialize-iota-client-cli.mdx"; - Asset tokenization refers to the process of representing real-world assets, such as real estate, art, commodities, stocks, or other valuable assets, as digital tokens on the blockchain network. This involves converting the ownership or rights of an asset into digital tokens, which are then recorded and managed on the blockchain. ## High-level overview -The concept is to divide high-value assets into smaller, more affordable units, representing ownership or a fraction of the asset. +The concept is to divide high-value assets into smaller, more affordable units, representing ownership or a fraction of the asset. This strategy enables wider participation from investors who might want to mitigate risk by investing in a portion of a digital asset rather than being the sole owner, thereby expanding accessibility to a broader range of investors. This pattern is similar to the [ERC1155](https://eips.ethereum.org/EIPS/eip-1155) multi-token standard with additional functionality. This makes it a suitable choice for Solidity based use cases that one might want to implement on IOTA. - **Asset creation** - + Each asset is fractionalized into a total supply, with each fraction represented as either a non-fungible token (NFT) or fungible token (FT) type collectible. This ensures that each individual fraction maintains a balance equal to or greater than one, and when combined, all fractions collectively reach the total supply of the asset. Besides the total supply, each asset is defined by various other fields such as name, description, and more. These fields collectively form the metadata for the asset, and they remain consistent across all fractions of the asset. - + - **NFTs vs FTs distinction** - + Each time a tokenized asset is minted, there's a possibility for it to be created with new metadata. If new metadata is incorporated, the tokenized asset is deemed unique, transforming it into an NFT. In this case, its balance is limited to one, signifying that only a single instance of this asset exists. - - If there's no additional metadata, the tokenized asset is categorized as an FT, allowing its balance to exceed one, enabling multiple identical instances of the asset to exist. - + + If there's no additional metadata, the tokenized asset is categorized as an FT, allowing its balance to exceed one, enabling multiple identical instances of the asset to exist. + FTs possess the capability to merge (join) among themselves or be split when the balance is greater than one. This functionality allows for the aggregation or division of units of the token, offering flexibility in handling varying quantities as needed. - + As previously mentioned, all the collectibles of tokenized assets, whether NFTs or FTs, when combined, can amount to the maximum total supply of the asset. - + - **Burnability** - - When you create the asset, you can define whether the fractions of the asset are eligible for removal or destruction from circulation. The process of removing or destroying assets is called burning. - + + When you create the asset, you can define whether the fractions of the asset are eligible for removal or destruction from circulation. The process of removing or destroying assets is called burning. + If a tokenized asset is burnable, then burning a fraction causes the circulating supply to decrease by the balance of the burnt item. The total supply, however, remains constant, allowing you to mint the burned fractions again if needed, thus maintaining the predetermined total supply of the asset. ## Move packages -As with all smart contracts on IOTA, Move provides the logic that powers asset tokenization. +As with all smart contracts on Iota, Move provides the logic that powers asset tokenization. ### asset_tokenization package :::info -This reference implementation uses the Kiosk primitive to ensure that TAs created operate within their creator's defined policy. We recommend you use the implementation as it is in order to have marketable TAs that support Rules (e.g: royalties, commissions etc). -If operating within the Kiosk primitive is not a requirement, then the unlock module & some of the proxy's methods related to Transfer Policies can be excluded. +The [asset_tokenization](https://github.com/iotaledger/iota/blob/main/examples/move/asset_tokenization) reference implementation uses the [Kiosk standard](../standards/kiosk.mdx) to ensure that tokenized assets operate within their defined policy. Use the implementation as presented to have marketable tokenized assets that support rules like royalties, commissions, and so on. + +If using Kiosk is not a requirement, then you can exclude the unlock module and some of the proxy's methods related to transfer policies. ::: @@ -54,38 +53,36 @@ Select a module to view its details: - + -The `tokenized_asset` module operates in a manner similar to the `coin` library. + The `tokenized_asset` module operates in a manner similar to the `coin` library. -When it receives a new [one-time witness](../iota-101/iota-move-concepts/one-time-witness.mdx) type, it creates a unique representation of a fractional asset. This module employs similar implementations to some methods found in the `Coin` module. It encompasses functionalities pertinent to asset tokenization, including new asset creation, minting, splitting, joining, and burning. + When it receives a new [one-time witness](../iota-101/iota-move-concepts/one-time-witness.mdx) type, it creates a unique representation of a fractional asset. This module employs similar implementations to some methods found in the `Coin` module. It encompasses functionalities pertinent to asset tokenization, including new asset creation, minting, splitting, joining, and burning. + **Structs** - -**Structs** + - `AssetCap` -- `AssetCap` + Generate an `AssetCap` for each new asset represented as a fractional NFT. In most scenarios, you should create it as an owned object, which you can then transfer to the platform's administrator for access-restricted method invocation. - An AssetCap should be generated for each new Asset we wish to represent as a fractional NFT. In most scenarios, it is recommended to be created as an owned object, which can then be transferred to the platform's administrator for access restricted method invocation. - - ```rust - struct AssetCap { - id: UID, - // the current supply in circulation - supply: Supply, - // the total max supply allowed to exist at any time - total_supply: u64, - // Determines if the asset can be burned or not - burnable: bool + ```rust + public struct AssetCap { + id: UID, + // the current supply in circulation + supply: Supply, + // the total max supply allowed to exist at any time + total_supply: u64, + // Determines if the asset can be burned or not + burnable: bool } - ``` - -- `AssetMetadata` + ``` - The AssetMetadata struct defines the metadata representing the entire asset that we intend to fractionalize. It is recommended to be a shared object. - - ```rust - struct AssetMetadata has key, store { + - `AssetMetadata` + + The `AssetMetadata` struct defines the metadata representing the entire asset to fractionalize. This should be a shared object. + + ```rust + public struct AssetMetadata has key, store { id: UID, /// Name of the asset name: String, @@ -98,984 +95,545 @@ When it receives a new [one-time witness](../iota-101/iota-move-concepts/one-tim /// URL for the asset logo icon_url: Option } - ``` - -- `TokenizedAsset` + ``` - The TokenizedAsset will be minted with a specified balance where the balance is less than or equal to the remaining supply. If the VecMap of an asset is populated with values, indicating multiple unique entries, it is considered a NFT. Conversely, if the VecMap of an asset is not populated, indicating an absence of individual entries, it is considered an FT. - - ```rust - struct TokenizedAsset has key, store { - id: UID, - /// The balance of the tokenized asset - balance: Balance, - /// If the VecMap is populated, it is considered an NFT, else the asset is considered an FT. - metadata: VecMap, - /// URL for the asset image (optional) - image_url: Option, - } - ``` - -- `PlatformCap` - - The PlatformCap refers to the capability issued to the individual who deploys the contract. This capability grants specific permissions or authority related to the platform's functionalities, allowing the deployer certain controlled actions or access rights within the deployed contract. - - ```rust - /// Capability that is issued to the one deploying the contract - struct PlatformCap has key, store { id: UID } - ``` - + - `TokenizedAsset` -**Functions** + The `TokenizedAsset` is minted with a specified balance that is less than or equal to the remaining supply. If the `VecMap` of an asset is populated with values, indicating multiple unique entries, it is considered an NFT. Conversely, if the `VecMap` of an asset is not populated, indicating an absence of individual entries, it is considered an FT. -- `init` + ```rust + public struct TokenizedAsset has key, store { + id: UID, + /// The balance of the tokenized asset + balance: Balance, + /// If the VecMap is populated, it is considered an NFT, else the asset is considered an FT. + metadata: VecMap, + /// URL for the asset image (optional) + image_url: Option, + } + ``` - This function creates a PlatformCap and sends it to the sender. - - ```rust - fun init(ctx: &mut TxContext) {} - ``` - -- `new_asset` + - `PlatformCap` - This function holds the responsibility of creating a fresh representation of an asset, defining its crucial attributes. Upon execution, it returns two distinct objects: the AssetCap and AssetMetadata. These objects encapsulate the necessary information and characteristics defining the asset within the system. - - ```rust - public fun new_asset( - witness: T, - total_supply: u64, - symbol: ascii::String, - name: String, - description: String, - icon_url: Option, - burnable: bool, - ctx: &mut TxContext - ): (AssetCap, AssetMetadata) {} - ``` - -- `mint` + The `PlatformCap` refers to the capability issued to the individual who deploys the contract. This capability grants specific permissions or authority related to the platform's functionalities, allowing the deployer certain controlled actions or access rights within the deployed contract. - The function performs the minting of a tokenized asset. If new metadata is introduced during this process, the resulting tokenized asset is considered unique, resulting in the creation of an NFT with a balance set to 1. Alternatively, if no new metadata is added, the tokenized asset is classified as an FT, permitting its balance to surpass 1, as specified by a provided argument. Upon execution, the function returns the tokenized asset object. - - ```rust - public fun mint( - cap: &mut AssetCap, - keys: vector, - values: vector, - value: u64, - ctx: &mut TxContext - ): TokenizedAsset {} - ``` - -- `split` + ```rust + /// Capability that is issued to the one deploying the contract + public struct PlatformCap has key, store { id: UID } + ``` - This function, is provided with a tokenized asset of the FT type and a balance greater than 1, along with a value less than the object's balance, and performs a split operation on the tokenized asset. The operation divides the existing tokenized asset into two separate tokenized assets. The newly created tokenized asset will have a balance equal to the given value, while the balance of the provided object is reduced by the specified value. Upon completion, the function returns the newly created tokenized asset. This function does not accept or operate on tokenized assets of the NFT type. - - ```rust - public fun split( - self: &mut TokenizedAsset, - split_amount: u64, - ctx: &mut TxContext - ): TokenizedAsset {} - ``` - -- `join` + **Functions** - This function is given two tokenized assets of the FT type and executes a merge operation on the tokenized assets. The operation involves increasing the balance of the first tokenized asset by the balance of the second one. Subsequently, the second tokenized asset will be burned or removed from circulation. After the process concludes, the function returns the ID of the burned tokenized asset. + - `init` - This function does not accept or operate on tokenized assets of the NFT type. - - ```rust - public fun join( - self: &mut TokenizedAsset, - other: TokenizedAsset - ): ID {} - ``` - -- `burn` + This function creates a `PlatformCap` and sends it to the sender. - This function requires the assetCap as a parameter, thereby restricting its invocation solely to the platform admin. Additionally, it accepts a tokenized asset that will be burned as part of its operation. Upon burning the provided tokenized asset, the circulating supply decreases by the balance of the burnt item. It necessitates a tokenized asset which is burnable. - - ```rust - public fun burn( - cap: &mut AssetCap, - tokenized_asset: TokenizedAsset - ) - ``` - -- `total_supply` + ```rust + fun init(ctx: &mut TxContext) {} + ``` - This function retrieves and returns the value representing the total supply of the asset. - - ```rust - public fun total_supply(cap: &AssetCap): u64 {} - ``` - -- `supply` + - `new_asset` - This function retrieves and returns the value representing the current circulating supply of the asset. - - ```rust - public fun supply(cap: &AssetCap): u64 {} - ``` - -- `value` + This function holds the responsibility of creating a fresh representation of an asset, defining its crucial attributes. Upon execution, it returns two distinct objects: the `AssetCap` and `AssetMetadata`. These objects encapsulate the necessary information and characteristics defining the asset within the system. - This function takes a tokenized asset as input and retrieves its associated balance value. - - ```rust - public fun value(tokenized_asset: &TokenizedAsset): u64 {} - ``` - -- `create_vec_map_from_arrays` + ```rust + public fun new_asset( + witness: T, + total_supply: u64, + symbol: ascii::String, + name: String, + description: String, + icon_url: Option, + burnable: bool, + ctx: &mut TxContext + ): (AssetCap, AssetMetadata) {} + ``` - This internal helper function is utilized to populate a `VecMap`. It assists in the process of filling or setting key-value pairs within the VecMap data structure. - - ```rust - fun create_vec_map_from_arrays( - keys: vector, - values: vector - ): VecMap {} - ``` + - `mint` - + The function performs the minting of a tokenized asset. If new metadata is introduced during this process, the resulting tokenized asset is considered unique, resulting in the creation of an NFT with a balance set to 1. Alternatively, if no new metadata is added, the tokenized asset is classified as an FT, permitting its balance to surpass 1, as specified by a provided argument. Upon execution, the function returns the tokenized asset object. - + ```rust + public fun mint( + cap: &mut AssetCap, + keys: vector, + values: vector, + value: u64, + ctx: &mut TxContext + ): TokenizedAsset {} + ``` -The `proxy` module comprises methods that the type owner utilizes to execute publisher-related operations. + - `split` -**Structs** + This function is provided with a tokenized asset of the FT type and a balance greater than 1, along with a value less than the object's balance, and performs a split operation on the tokenized asset. The operation divides the existing tokenized asset into two separate tokenized assets. The newly created tokenized asset has a balance equal to the given value, while the balance of the provided object is reduced by the specified value. Upon completion, the function returns the newly created tokenized asset. This function does not accept or operate on tokenized assets of the NFT type. -- `Proxy` + ```rust + public fun split( + self: &mut TokenizedAsset, + split_amount: u64, + ctx: &mut TxContext + ): TokenizedAsset {} + ``` - The PROXY struct represents the one-time witness (OTW) utilized to claim the publisher. - - ```rust - struct PROXY has drop {} - ``` - -- `Registry` + - `join` - This is a shared object serves as a repository for the Publisher object, specifically intended to control and restrict access to the creation and management of transfer policies for tokenized assets. Mutable access to this object is exclusively granted to the actual publisher. - - ```rust - struct Registry has key { - id: UID, - publisher: Publisher - } - ``` - -- `ProtectedTP` - This is a shared object utilized to store an empty transfer policy. It is required to create one per type `` generated by a user. Its involvement is apparent in the unlock module. - - ```rust - struct ProtectedTP has key, store { - id: UID, - policy_cap: TransferPolicyCap, - transfer_policy: TransferPolicy - } - ``` - + This function is given two tokenized assets of the FT type and executes a merge operation on the tokenized assets. The operation involves increasing the balance of the first tokenized asset by the balance of the second one. Subsequently, the second tokenized asset is burned or removed from circulation. After the process concludes, the function returns the ID of the burned tokenized asset. -**Functions** + This function does not accept or operate on tokenized assets of the NFT type. -- `init` + ```rust + public fun join( + self: &mut TokenizedAsset, + other: TokenizedAsset + ): ID {} + ``` - This function is responsible for creating the Publisher object, encapsulating it within the Registry, and subsequently sharing the Registry object - - ```rust - fun init(otw: PROXY, ctx: &mut TxContext) {} - ``` - -- `setup_tp` + - `burn` - This function leverages the publisher nested within the registry and the sender's publisher. It generates and returns a transfer policy and the associated transfer policy cap specific to the `TokenizedAsset`. This type 'T' is derived from the Publisher object. + This function requires the `assetCap` as a parameter, thereby restricting its invocation solely to the platform admin. Additionally, it accepts a tokenized asset that is burned as part of its operation. Upon burning the provided tokenized asset, the circulating supply decreases by the balance of the burnt item. It necessitates a tokenized asset that is burnable. - It also generates an empty transfer policy wrapped in a `ProtectedTP` object, which is shared. You can use this functionality under specific conditions to override the kiosk lock rule. - - ```rust - public fun setup_tp( - registry: &Registry, - publisher: &Publisher, - ctx: &mut TxContext - ): (TransferPolicy>, - TransferPolicyCap>) {} - ``` - -- `new_display` + ```rust + public fun burn( + cap: &mut AssetCap, + tokenized_asset: TokenizedAsset + ) + ``` - This function utilizes the publisher nested within the registry in and the sender's publisher to generate and return an empty Display for the type `TokenizedAsset`, where 'T' is encapsulated within the Publisher object. - - ```rust - public fun new_display( - registry: &Registry, - publisher: &Publisher, - ctx: &mut TxContext - ): Display> {} - ``` - -- `transfer_policy` + - `total_supply` - This function provided with the protectedTP, returns the Transfer Policy specifically designed for the type `TokenizedAsset` - - ```rust - public(friend) fun transfer_policy( - protected_tp: &ProtectedTP - ): &TransferPolicy {} - - ``` - -- `publisher_mut` + This function retrieves and returns the value representing the total supply of the asset. - This function can only be accessed by the owner of the platform cap. It requires the registry as an argument to obtain a mutable reference to the publisher. - - ```rust - public fun publisher_mut( - _: &PlatformCap, - registry: &mut Registry - ): &mut Publisher {} - ``` + ```rust + public fun total_supply(cap: &AssetCap): u64 {} + ``` - + - `supply` - + This function retrieves and returns the value representing the current circulating supply of the asset. -The `unlock` module facilitates the unlocking of a tokenized asset specifically for authorized burning and joining. + ```rust + public fun supply(cap: &AssetCap): u64 {} + ``` -It allows tokenized asset type creators to enable these operations for Kiosk assets without necessitating adherence to the default set of requirements, such as rules or policies. + - `value` -**Structs** + This function takes a tokenized asset as input and retrieves its associated balance value. -- `JoinPromise` + ```rust + public fun value(tokenized_asset: &TokenizedAsset): u64 {} + ``` - A promise object is established to prevent attempts of permanently unlocking an object beyond the intended scope of joining. - - ```rust - struct JoinPromise { - /// the item where the balance of the burnt tokenized asset will be added. - item: ID, - /// burned is the id of the tokenized asset that will be burned - burned: ID, - /// the expected final balance of the item after merging - expected_balance: u64 - } - ``` - -- `BurnPromise` + - `create_vec_map_from_arrays` - A promise object created to ensure the permanent burning of a specified object. - - ```rust - struct BurnPromise { - expected_supply: u64 - } - ``` - + This internal helper function populates a `VecMap`. It assists in the process of filling or setting key-value pairs within the `VecMap` data structure. -**Functions** + ```rust + fun create_vec_map_from_arrays( + keys: vector, + values: vector + ): VecMap {} + ``` -- `asset_from_kiosk_to_join` + - This helper function is intended to facilitate the joining of tokenized assets locked in kiosk. It aids in unlocking the tokenized asset that is set for burning and ensures that another tokenized asset of the same type will eventually contain its balance by returning a `JoinPromise.` - - ```rust - public fun asset_from_kiosk_to_join( - self: &TokenizedAsset, // A - to_burn: &TokenizedAsset, // B - protected_tp: &ProtectedTP>, // unlocker - transfer_request: TransferRequest> // transfer request for b - ): JoinPromise {} - ``` - -- `prove_join` + - A function utilized to demonstrate that the unlocked tokenized asset has been successfully burned and its balance has been incorporated into an existing tokenized asset. - - ```rust - public fun prove_join( - self: &TokenizedAsset, - promise: JoinPromise, - proof: ID) {} - ``` - -- `asset_from_kiosk_to_burn` + The `proxy` module comprises methods that the type owner utilizes to execute publisher-related operations. - This helper function is intended to facilitate the burning of tokenized assets locked in kiosk. It assists in their unlocking while ensuring a promise that the circulating supply will be reduced, achieved by returning a `BurnPromise`. - - ```rust - public fun asset_from_kiosk_to_burn( - to_burn: &TokenizedAsset, - asset_cap: &AssetCap, - protected_tp: &ProtectedTP>, - transfer_request: TransferRequest>, - ): BurnPromise {} - ``` - -- `prove_burn` + **Structs** - This function ensures that the circulating supply of the asset cap has indeed been reduced by the balance of the burned tokenized asset. - - ```rust - public fun prove_burn( - asset_cap: &AssetCap, - promise: BurnPromise) {} - ``` + - `Proxy` - + The `PROXY` struct represents the one-time witness (OTW) to claim the publisher. - + ```rust + public struct PROXY has drop {} + ``` -### template package + - `Registry` -An example use case package, that enables utilization of Rust WASM functionality to support seamless asset creation on the browser. -This is similar to the launchpad approach and will serve as the template package whenever a new asset requires representation as a tokenized asset. -Effectively allowing users to edit fields of this template contract on the fly and publish it with the edits included. -This package implements two essential modules, each catering to distinct functionalities required for asset tokenization. -More details regarding how Rust WASM was implemented can be found in the [Web Assembly](#webassembly-wasm-and-template-package) section. - -- **Modules** - - template - - This is the module where a new asset can be defined. - - When there's a necessity to represent a new asset as a fractional asset, this module will undergo modification to `