Fully On-Chain Cardano NFT Distribution Model
How we pulled off the first and cleanest completely on-chain Cardano NFT vending machine-styled giveaway in history.
For one hour, fans were able to take part in Yasen Chariyski’s Artifact69 1000 NFT giveaway. Each person only needed to send 2 ADA to a given address and they received their token in about a minute, including complete refund of any unspent ADA.
The team wanted to giveaway 1000 NFTs to the community. However, we wanted to ensure that every follower had a chance of getting their hands on a token.
It is impossible to restrict each person to only one token without more stringent form of identity management. In order to enforce this limit as much as possible, we restricted each wallet to only one token (as return addresses can differ from wallet to wallet, all addresses within a wallet share the same stake key, which we used to determine if a wallet had already received a token). While this does not completely stop exploits, it added friction to discourage such behavior.
The second consideration that we had was about performance. There have been a number of recent launches in the CNFT space that have been rough and as such, we wanted to find a solution that would be robust to high volume.
From studying other CNFT launches that failed, it was apparent that the bottleneck in the entire process was web hosting. In all cases, the point of failure was not the blockchain but rather the web server being unable to withstand the traffic. As such, we opted not to have a website but to leverage on the robustness of the Cardano blockchain itself, using it as an interface to the community.
An address was announced on the Discord channel of the project. Then, the transactions started streaming in. The rest of the heavy lifting was done by the vending machine script on the server.
At regular intervals of 30s, UTXOs at the payment wallet address were queried via the automint library (a library written to access and automate
cardano-cli operations). For each txHash, the return address and associated stake key were acquired. If addresses associated with the stake key had received a token previously or all the tokens had already been distributed, then the full amount minus fees in the UTXO was refunded to the address. Otherwise, a token was sampled from a pool of remaining unminted tokens and sent together with the balance of the UTXO to the return address.
Keeping track of mints
Given that the tokens were minted on the fly as part of the sending transaction, we had to keep track of which tokens had already been minted in a persistent manner that was able to withstand crashes. To accomplish this, we used TinyDB to store transaction and minting records, allowing us to ensure that there was no double minting of any token.
This vending machine application is the first real application of the automint package. Automint is a Python wrapper around
cardano-cli developed by the team to enable easy and programmatic access to
cardano-cli functions. One of the difficulties in transactions (and minting transactions) has to do with the accounting of input and output amounts as the two have to be equal, by the UTXO model. Further, sending transactions is a multistep process with computations done between some steps (calculating and deduction of transaction fees, for example).
Automint revolves around the idea of doing token arithmetic, allowing tokens to be added and removed from objects known as
Accounts which keep track of sets of tokens (both lovelace and native tokens). Hence, it is trivial to add tokens to accounts with simple
account.add_native_token() function calls. The end result can then be converted to string representation that precisely aligns with the expected input to
--tx-out fields of the
cardano-cli transactions program.
An example of how easy it is to implement refunds using automint is as follows
As you can see, there is no need to wrestle with CLI outputs but rather, everything can be handled programmatically using Python.
The event was a proof of concept for the potential of faucet/vending machine distribution styles. As the transactions are sent via the Cardano blockchain, we leverage on the robustness of the blockchain itself to handle the volume and throughput required. This allowed our application to be independent of the transaction load as “snapshots” of the wallet were acquired periodically via
cardano-cli query utxo ... commands and then each one processed. Therefore, there is never any increased load or spikes on the server. We believe that such a distribution format holds a lot of potential, and has applications for all levels of NFT artists from small low-mint collections to 10k drops.
Building on the success of the vending machine format, we have also been
- exploring the use of vending machines to conduct sale of tokens (and not just giveaways)
- using automint to build an automated auction bot where lower bids are automatically refunded and the highest bidder sent the tokens at the end of the auction
- crafting systems with NFTs
This project could not have been pulled off without the support and servers from TYGAR stake pool.
The automint library can be found at https://github.com/non-fungible-waveforms/automint/tree/b8bb375321cef97d00d0850abeaad57bc2299c4c
Based on our experiments, we’ve been able to hit throughput of up to 2000 minting and sending transactions per minute.