Cross Mint V1

📌

July 15th, 2021: Changes are coming. 😄 Take a look here and see what we mean!

The Cross Mint product is a new member of the Cross Product Suite that offers a secure and decentralised way of minting NFTs using the two most popular specs, namely ERC721 and ERC1155.

High level architecture

Below we can see the high level architecture.

image

Each component is running on different environments. More specifically the following environments are utilized:

  1. Ethereum blockchain
  2. Binance Smart Chain
  3. Web environment
  4. VM running the Cross Mint Indexer process and the Cross Mint Api
  5. Content addressable decentralized storage network (Arweave)
  6. AWS S3 bucket

Below we briefly describe each component:

Cross Mint 721

This is an extension of the ERC721 spec which will represent each collection within the cross mint ecosystem. Hotcross itself will be the first collection of ERC721 NFTs that the platform will support. Users could mint new NFTs within the Hotcross collection or choose to create their own collection (the Custom ERC721 in the above diagram illustrates this concept). Creating a new collection is includes deploying a new CrossMintERC721 contract. This will be handled by the designated factory smart contract as described below.

Minting is a restricted action.The main minter account is the Cross Mint smart contract described below. Additionally, custom collections will allow the owner of the collection to mint new NFTs.

Cross Mint 1155

Similar to the ERC721 counterpart, this is an extension of the ordinary ERC1155 smart contract. The same concept of collections applies here, as well.

The same exact minting restrictions are valid for Cross Mint ERC1155, as well.

Cross Mint 721 Factory

This is the on-chain entity that has a single function, which is to accept some parameters and deploy a new Cross Mint ERC721 smart contract. Essentially, this is how new ERC721 collections are deployed.

Cross Mint 1155 Factory

This is the on-chain entity that has a single function, which is to accept some parameters and deploy a new Cross Mint ERC1155 smart contract. Essentially, this is how new ERC1155 collections are deployed.

💡

Note that we refer to ERC721 and ERC1155, however by no means this implies that these contracts are destined to be deployed on the Ethereum network. The same exact concepts apply for the Binance Smart Chain, as well.

Fee Manager

A smart contract that is responsible to verify that the correct fee amount is sent along with each request. This applies both for minting and creating new collections. The fee can be as low as zero and is configurable.

Cross Mint

This is the central point of interaction from the off-chain world. This smart contract supports the following actions:

  1. Tigger the deployment of a new CrossMint721 Collection
  2. Tigger the deployment of a new CrossMint1155 Collection
  3. Mint a new CrossMint721 NFT within a specific CrossMint721 collection
  4. Mint a new CrossMint1155 NFT within a specific CrossMint1155 collection

Cross Mint DApp

A web based applications that will be the main interaction point between the users and the rest of the system. User will be able to

  • Mint a new NFT
  • Upload a file associated with an NFT
  • Attach metadata to a new NFT
  • Deploy a new NFT collection either CrossMint721 or CrossMint1155
  • View the list of all NFTs
  • Transfer NFTs

Cross Mint SDK

A JavaScript library that implements most of the actions that allow the interaction of any client with the Cross Mint Api and the smart contracts on the blockchain. The first client of the SDK will be the Cross Mint DApp.

Cross Mint API

A Restful Api that is used by the Cross Mint DApp to query data, as well as, upload files that will be stored on the S3 bucket and the Arweave network.

NFT metadata

The uniqueness of each NFT is secured by the means of a record within the corresponding smart contract. However, due to blockchain limitations, we can’t just upload the textual and media context that describe it. Thus, we store that information in an external storage layer as described in the next sections.

A typical NFT metadata is encoded as an JSON object and can contain arbitrary properties which users will be able to choose via the Cross Mint DApp.

An example of a metadata file is this:

{
	"title": "Hotcross",
	"description": "Hotcross logo",
	"date": "August 2020",
	"tokenId": "#1124455",
	"file": "https://arweave.net/Tpl5QYNzEEXtzUTwE2RPZ8eXIhLwYBQ6OjjaxUTjJnY"
}

NFT Storage

Each NFTs that is minted on the Cross Mint platform goes through two steps:

  1. Mint the NFT (either 721 or 1155) on the corresponding blockchain i.e. Ethereum or BSC
  2. Upload the metadata to an external storage layer. This is the uri that will be associated with the NFT on-chain.
  3. Upload the media file associated with the NFT to an external storage layer

At the moment we are storing the metadata and the media file on two different platforms:

  1. Arweave: A decentralised storage solution built on top of IPFS.
  2. AWS S3 Bucket: A decentralised file server that will allow for faster retrievals

The end-goal is to allow users to upload a medial file and the associated files into a storage that neither Cross Mint nor the user controls. This is a step forward into providing a solution that allows users mint NFTs and be sure that the corresponding files are not destroyed or wiped out because the Hotcross company goes out of business. This is a critical guarantee that we want to provide to our users and thus we have to use a decentralised storage solution.

The challenge with the first solution is two folds:

  1. We need to make sure that uploading the metadata file, as well as, the media file are done in an atomic manner.
  2. We need to ensure that the minting of the NFT and the storage of the metadata URI are finalised before uploading the files on Arweave.

The challenge here is that atomicity is not guaranteed since we’re spanning across different systems that do not communicate with each other i.e. there is no way to verify within the CrossMint721 contract, for example, that the metadata of the NFT that is being minted has bee successfully uploaded into the Arweave network.

The solution we are planning to implement includes the concept of Arweave Data Bundles described below. In essence, the uploader will have to pre-compute the address of the uploaded files in a deterministic way and use that address when sending the mint request. Once the request is finalised on the blockchain it can upload those files into the Arweave network.

One more reason why this approach is suitable is the cost of Arweave data storage. It would be disastrous for the Cross Mint platform to allow users upload multiple files and spam the system. The issue with that is that each data upload on Arweave incurs a cost. That cost is covered by the Cross Mint platform for a single reason that we don’t expect users to have Arweave wallet which is needed to pay for data uploads. In addition to that, data uploads are done via the Cross Mint Api and it’s the Arweave wallet we store on the API that is responsible for uploading the files and paying the cost.

Pre-calculating the addresses of the metadata and media files will allow us to mint a new NFT with a single blockchain transaction. It also allows the Cross Mint contract to collect any fees to cover the cost of a file upload via the Fee Manager. Although we pay the cost of a file upload on the Cross Mint API, we can still indirectly charge users though the Cross Mint smart contract.

The fee will be a fixed value which we can calculate by getting the worst case scenario in terms of file size in multiplying that by the cost of Arweave storage per MB. For example, if we set the maximum upload size to 100MB and the cost of 1 MB is 0.005USD (according to https://ardrive.io/pricing/) then we set a fixed cost of 0.5 USD (in the native currency i.e. ETH or BNB).

Arweave Data Bundles

We’re going to use DataBundles for creating the Arweave transactions. DataBundles are special transactions that allow us to bundle multiple inner transactions together, called DataItems. This means that the DataBundle transaction is the one that will be mined.In our use case, we need to have 2 DataItems:

  1. The uploaded file (image, video, etc.)
  2. The metadata JSON file

The Cross Mint Api will sign those DataItems and get their ids, which we will then use in the NFT mint call. Since we only use the ids of the DataItems and not the DataBundle, we can create the DataBundle at the time of submitting it onto Arweave, right after the NFT minting is complete. In case the Arweave upload fails, we can re-try it without needing to change the internal DataItems ids.

In a nutshell the steps are as follows:

  1. Create a DataItem with the uploaded file
  2. Create a second DataItem with the metadata
  3. Mint the NFT on ETH/BSC, using the 2nd DataItem’s id
  4. Create DataBundle, and include the two DataItems above
  5. Submit DataBundle to Arweave
  6. In case it fails, re-submit it

Performance Considerations

Cross Mint DApp is a web-based application that will run on desktop and mobile browsers. It is also connected to the blockchain and can read data directly from the smart contracts. More specifically, the DApp would need to show the list of all user’s NFTs/Collections. This piece of data is stored on the blockchain in one or another form. However, directly querying it would either be expensive or impossible.

For example, if we shall show the history of all user NFT transfers, then it would be impossible to directly load that from the smart contract in an efficient manner. It would require the following:

  1. Load all the Cross Mint NFT smart contracts (collections) that have ever been deployed by reading a specific type of events from the blockchain
  2. For each such contract, load all the Transfer events
  3. Filter those events that are relevant to the current user account
  4. Present that list in the UI layer

This process would have every time the user reloads the DApp page. It’s needless to say that this is not a viable solution and that an indexing and persistent storage layer will have to be employed so the DApp can simply load that and present it in the UI layer.

This is exactly the purpose of the Cross Mint indexer, the MongoDB and the Cross Mint API system modules. These are all external services that simplifies the work of the DApp leaving it with the responsibility of representing useful pre-fetched data on the UI.

The Cross Mint Indexer as the name suggests creates an index of the data that are stored in the blockchain. More specifically, it listens to events emitted within the Cross Mint smart contracts stores them in specific schema within the database. The schema is designed in such a way so it’s simple enough to query data that otherwise would need on-the fly calculations. The Cross Mint DApp can then query that data via the Cross Mint Api and display it to the user.

One such use query can be:

“Bring me all NFTs across owned by given address”.

Our off-chain services will make sure that this data is already pre-fetched and stored in the DB; thus the Cross Mint API will need to simply read the data from MongoDB and return it to the Cross Mint DApp.

💡

Throughout the document we refer to multiple collections. Although this is already baked into the smart contract logic, we will use a single Hotcross 721 and 1155 collections in version 1. The reason is purely the indexing logic. It will be slightly challenging to implement an indexer that listens across hundreds or thousands of individual collection

How it works

TODO:: Add screenshot of the user journeys when the UI is finished

Open Issues

Minting permissions: The minting of a new NFT depends on which collection it is minted in. If it’s the Hotcross CrossMint 721/1155 collection then it can only be minted via the CrossMint smart contract. However, if it’s a custom collection then the CrossMint is the first minter and the collection owner is the second owner. In reality, the collection owner can decide whether the minting is a protected action or not; that is a collection owner can leave the minting of NFTs within their collection open to anyone who would want to do that. This functionality was introduced to cater for flexibility.

In version 1, as noted above, we will have only two collection which both belong to Hotcross; thus the discussion will be relevant within the Cross Mint V2. However, it still worth deciding whether we want to support such features. The options regarding minting are:

  1. Allow only the CrossMint to mint new NFTs for any collection. This gives us control over the fees. For example, if we charge a small fee for each NFT minting then users wouldn’t be able to directly mint within their collection without paying that fee. In essence, CrossMint smart contract acts as the central gateway to the NFTs.
  2. Allow both CrossMint and the collection owner to deploy the mint. In this case, the owner of the collection will be able to programmatically mint new NFTs within his collection and thus avoid paying fees. However, that would require manually uploading metadata and media file to the storage of their choice.

View layer: Version 1 of Cross Mint will only show the NFTs that have been minted within the Hotcross NFT collections.

  • This is partly for compatibility reasons; there is no an open standard for NFT metadata and thus it will be difficult to load the media file and any relevant information regarding a particular NFT.
  • The second reason is that we don’t index the NFT ownership across the entire blockchain. To get that kind of information we would need to implement a blockchain-wide indexer that stores the NFT ownership for all the users on the network.

References

  1. https://github.com/ArweaveTeam/arweave-standards/blob/master/ans/ANS-102.md
  2. https://ardrive.io/pricing/