Am opening this conversation to talk about tokens and nfts using smart contracts rather than the base native asset system. Right now, all tokens on Ergo are using the native asset system. This system works well for almost all usecases, and ensures that unnecessary computation is not needed. However, I think that there is some interest in ERC-20 like systems, which require computation, but also allow for programmable assets.
Things that are not currently do-able on Ergo’s native asset system include:
- Enforcing NFT royalties outside of marketplaces (and other “on-spend” actions)
- Re-minting tokens with the same identifier (could be useful for options contracts, certain inflationary mechanics)
- Morphing on-chain data associated with a token over time.
- Unfortunately, certain entities such as those behind USDT and USDC may be unwilling to bridge onto Ergo if they lack the ability to freeze transfers between certain accounts.
ERC-20 Tokens are usually keeping some account state in their contracts, and providing functions that allow for asset transfers, etc. Obviously, Ergo’s programming model is much different, so let’s look at different designs for how to do this without requiring any forks to the current native asset system.
Design 1: NFT-UTXO
This design makes the most sense for NFTs. Simply have a singleton utxo under a contract which is holding the current owner of the NFT in R4 as a SigmaProp. Every transaction spending this box counts as an asset transfer, and must follow these rules:
- A new singleton with the same contract must exist in the outputs. It’s R4 may be different in order to signal an asset transfer.
- The current R4 of this box must be proven true in order for it to be spent.
Considering the number of NFTs that people make, this is probably bad in that tons of data must be kept on-chain for each NFT made this way.
Design 2: ERC-20 Like
This could work for NFT’s or Tokens. Each unique token id is represented by a unique contract + singleton box, which holds an account state within it. I would prefer to avoid using AVL Trees here to represent the state, the reason being that transfers would require synchronization with each unique token’s avl history to generate proofs. So in that case, we are either constrained to the 4096 bytes within the singleton utxo, or we can have some additional contract + set of utxos which is specifically storing the account state.
This is kind of a messy way to go about things. If we store address hash + a long, that is 40 bytes of data. Only ~100 balances can be stored within the singleton. Using an additional contract for state storage solves this problem, but feels like a dirty way handling things.
Design-3: Asset-Focused L2 / AVL Solution
This is probably the best option in terms of dataspace efficiency. AVL Trees can be used to store an account or even utxo state for holders of programmable tokens. At this level, it is best to have something relatively generalized, so that each token does not need it’s own tree to hold its state. This is probably the most complicated one to build, though it has scalability benefits over the others.
All of these designs probably break composability to some extent, though I’m not sure how to get around that. I think best option currently is design 2, because it is simplest and allows the utility of such assets to be extended to L1. I also would be interested in seeing variations of design 2 which are emulating utxo states instead of an account one.