Native tokens on Cardano have their strengths, but there are a few associated drawbacks, the biggest being the imposition of conditions on settlement. As such, there may be times where it makes sense for the accounting of tokens to be handled by smart contracts rather than the ledger. I am proposing the introduction of a standard for non-native tokens (second class citizens) on Cardano to facilitate the ability to impose conditions on settlement with smart contracts. This provides token issuers choice in selecting between native tokens and non-native tokens when minting, and all associated benefits and drawbacks.
Indeed, the FAQ for native tokens alludes to this, indicating it has always been a natural step to take for native tokens on Cardano:
Spending tokens : Users can spend the tokens in their wallet, or tokens in outputs locked by scripts that allow this user to spend the output.
Benefits include all advantages that come with handling accounting with smart contracts, such as the ability to set custom transaction fees (issuer-defined fees on top of network fees) for peer-to-peer transfers, distributing these fees as well as a portion of all native tokens transacted to all token holders, and more. In short - more advanced tokenomics.
I recognise that this is something that has no doubt been considered before, but I have not been able to find any thread on discussion for the creation and codification of a standard now that Alonzo is upon us. I would like to start the discussion with this thread, and begin the process of the community working together on a standard.
These are my thoughts on how such a system may be implemented. I am new to developing on Cardano and as such welcome greatly your thoughts and contributions in directing this discussion - my intention is purely to commence it.
Backed by native tokens
A suitable approach would be to mint a set of native tokens, then lock these native tokens away in a script. The smart contract then handles the accounting of the native tokens, fragmenting and recombining UTXOs containing these native tokens based on user interaction. At all times, the native tokens reside in UTXOs located at the script address, with the arrangement of UTXOs providing accounting information.
This provides several advantages - firstly, legitimate UTXOs are naturally identified by the presence of the corresponding native token. Secondly, the metadata for the native token is easily accessible; as such, all existing standards for native tokens are still valid - they are just hidden behind one layer of abstraction. In a way, the script address becomes its own UTXO-based public ledger for the particular native token, except transactions are subject to their own set of rules and conditions.
Need for a standard
It is easy to implement this solution for one particular token on one particular script address. Unfortunately, this would either require the token issuer to build their own web app to provide the off-chain code for every user interaction, or require that wallet providers have a copy of every script for every token, since the interpretation of the script addresses and the building of transactions, including UTXO selection, recombination and implementation of the distribution conditions, will be on the part of wallets and their PABs.
It would be unreasonable to require wallet providers to maintain their own registry of scripts. As such, there is a need for a unified standard - this is the reason behind this proposal.
The proposal: A registry contract for scripts
One possible solution would be to implement a single ‘identifier’ contract as a decentralised registry that contains the logic for all tokens that exist under this standard.
When the Plutus script address of the standard is loaded with its corresponding token for the first time, a transaction is sent that ‘activates’ the script by minting and locking at the identifier contract a native token bearing the policy ID and the raw code for the off-chain component of the token script itself in the metadata, pertaining to implementations for the functions specified in the standard that govern the token’s dynamics.
This is possible because boilerplate code defining the token and the script itself is not needed - these can be read from the standard or the native tokens themselves. As such, only implementations for a few functions would be required, and these can be losslessly compressed and stored on-chain. This gives us 16KB (for now) to play with to write these methods.
This information is then locked at the identifier contract forever. This ‘registers’ the token and allows wallet providers (and anyone else) to access a public mapping from policy ID to script (and therefore script address).
Furthermore, the tokens and the code governing their behaviour exist completely on chain, and as such wallet developers would only have to obtain a template copy of this standardised script, fetch the token-specific components from the registry contract’s UTXOs, and build the whole script themselves on demand.
To ease computation load, it would be pertinent to put the onus to direct the wallet to check for token ownership on the user. This data can be stored locally on the user’s device. The user provides a list of policy IDs for tokens that they may own - subsequently the wallet will begin checking the UTXOs at the corresponding script addresses for the user’s funds.
Visibility of owners
The approach of storing the address that owns the token in the datum hash of the UTXO that holds the tokens is the simplest approach, but doesn’t allow for the mapping to be stored on chain, and as such the chain cannot be audited for ownership without access to the off-chain datum store. This is not ideal, and defeats the purpose of having tokens, even if non-native, on a public ledger.
This standard would be simplified greatly when metadata can be attached to script transactions - a simple mapping from address to token amount generated stored in the metadata of every transaction, one for every output. This is not yet possible, so a workaround is necessary.
In the absence of the ability of Plutus scripts to generate transactions with metadata, it becomes necessary to find another way of broadcasting the mapping of a particular token-bearing UTXO to its owner. This shouldn’t be too hard - there are plenty of potential solutions such as minting native utility tokens to be locked in the UTXOs that hold this information.
These are just my thoughts about the matter, and I’m sure they require a lot of modification. Please let me know your thoughts and improvements!