Open tonimateos opened 7 months ago
The goal of this investigation is to devise a format that dApp developers can use to refer to any NFT inside the LAOS parachain or on other chains like Ethereum and Polygon. This is particularly relevant when setting up the tokenURI
during the minting of a token on LAOS.
Understanding the MultiLocation format is crucial as it forms the basis of our proposed Universal Location Format. MultiLocation is designed to identify any single location within the world of consensus, always relative to the current location and hierarchical in nature.
The MultiLocation struct in Rust is defined as follows:
pub struct MultiLocation {
pub parents: u8,
pub interior: Junctions,
}
Which means we need to specify the parents or how many levels we go up, and then the junctions or how many levels we go down.
I am in ParaB and I wish to locate AccountId32 from ParaA the MultiLocation would be: ../Parachain(1000)/AccountId32(0x00..)
More info on MultiLocation format can be found here:
Knowing how a MultiLocation is formed and since there is no clear documentation on how the Universal Location format should look like, let's try to derive it from the pieces of information at hand.
XCM Implementation: A comment from Gavin in the XCM implementation suggests that a universal location begins with a GlobalConsensus
tag. Which implies Universal Location is just a vector of junctions starting with a GlobalConsensus
junction. This can be seen in the implementation here.
Written Multilocation Example: An example of a written multilocation is provided in the XCM format documentation here.
Universal Location as a Vector of Junctions: This concept is exemplified here, showing that a universal location is a vector of junctions starting with global consensus.
Following the XCM format and the above example, a universal location for a specific location (e.g., ../PalletInstance(3)/GeneralIndex(42)
) on the Kusama network could be GlobalConsensus(3)/PalletInstance(3)/GeneralIndex(42)
.
Essentially, a universal location format is a multilocation with no parents, starting with the GlobalConsensus junction.
Before using the Universal Location format for NFT identification there is another type on xcm that does just that, identifying a fungible/non-fungible asset. Let's introduce the concept of a MultiAsset.
We can see the MultiAsset type as a wrapper of the MultiLocation type that adds the ability to specify the fungibility of our target.
Take a look at the struct of the MultiAsset in Rust.
pub struct MultiAsset {
pub id: AssetId,
pub fun: Fungibility,
}
If we wish to identify non-fungible assets in a concrete and unambiguous manner, a MultiAsset
value is represented by an assetId
, which is a MultiLocation
(in our case, a universal location) and the type of fungibility, which is non-fungible in our particular case.
The problem about the MultiAsset format is that it does not have a written format as the MultiLocation/UniversalLocation has, so we would need to create a new one if we want to use it in our tokenURI.
There are two ways we can go forward either by implicitly assuming that the Universal Location as a tokenURI is pointing to a non fungible token, or by creating a new format that explicitly states that we are pointing to a concrete nft asset.
Keeping the format as a "pure" universal location without additional tags. That would mean that a tokenURI inside the LAOS evochain will always be an Universal Location that points to a non fungible asset.
tokenURI for NFT in parachain from kusama network: GlobalConsensus(3)/Parachain(1000)/GeneralIndex(42)
tokenURI for NFT in eth network: GlobalConsensus(7)/GeneralIndex(42)
Adding new junctions tags to the universal location format to indicate that it refers to an asset and its fungibility type. However, this approach may lead to interpretations that are not aligned with the XCM format and Polkadot community perspective as the string format diverges too much from the actual xcm implementation.
tokenURI for NFT in parachain from kusama network: nft://GlobalConsensus(3)/Parachain(1000)/GeneralIndex(42)
tokenURI for NFT in eth network: nft://GlobalConsensus(7)/AccountKey20(7, 0x..)/GeneralIndex(42)
tokenURI for NFT in parachain from kusama network: GlobalConsensus(3)/Parachain(1000)/NFTGeneralIndex(42)
tokenURI for NFT in eth network: GlobalConsensus(7)/AccountKey20(7, 0x..)/NFTGeneralIndex(42)
As per a team agreement the format that we wish to settle on is GlobalConsensus(3)/Parachain(3336)/AccountKey20(3, 0x..00a)/GeneralKey(tokenId)
Although there was some discussion about maybe having the pallet instance junction on it: GlobalConsensus(3)/Parachain(3336)/PalletInstance(8)/AccountKey20(3, 0x..00a)/GeneralKey(tokenId)
You can read the public issue here: https://github.com/freeverseio/laos/issues/177
As a DApp dev, and a Universal Node dev, I want to make sure I use a Universal Location format that is well understood by the all parties using LAOS, and that adheres as much as possible as to what the Polkadot community of developers would like.
e.g. /polkadot/chainId/collectionAddress/tokenId e.g. ul://polkadot/paraid/pallet/collectionAddress/tokenId e.g. ul://v1/polkadot/paraid/pallet/collectionAddress/tokenId
consider including versioning on it
We have started this issue as the spec
ACCEPTANCE:
A publicly accessible spec with the format to be used in the
tokenURI
methods to refer, via UL, to:if Polkadot:
Good links: