Smart NFTs on Algorand
Let’s say you want to create a certificate of ownership on the blockchain, you mint a token, limit the supply and voilà an NFT has been created. Now you want to implement royalties to get a share in future sales to reward yourself for the original work. Only to be disappointed by the fact that royalties are not part of the standard tokens. For those people, I present to you the Smart NFT or rather a certificate of ownership in the form of a dapp.
In this article, I will describe how you can turn a dapp on Algorand into a certificate of ownership with built-in royalties and custom transfer logic. I will be explaining the general idea of the implementation. For the technical implementation, you can visit the Github page of Dartroom.
Features
What features do we need in our dapp? First, we would need to record the ownership of the dapp. On Algorand you would store this in the ‘Global State’. The global state can contain 64 key values pairs to store information within the contract. All these values are publicly available on the ledger. Anyone can see who the owner is. We will need to implement some logic in the contract to decide when this value should be allowed to change.
Secondly, we want royalties to be paid every time the certificate is sold. Now there is an inherent problem with enforcing royalties and that is back ally deals. Someone could simply sell it for a lower price or even transfer it for free to avoid royalties. And then transfer the money under the table. This could even be done with another smart contract to make sure both parties are holding up their end of the deal.
The closest we can get to locking this down is to only allow the certificate to be transferred through auction. If we assume that an auction will make sure the certificate is always sold for market value, then we can expect someone to intercept a back ally deal.
In this example, I willa also mention some smaller features to improve the dapp. The ability to set a reserve price that when met will start the auction timer. A custom auction duration when the timer starts. The ability to stop an auction if no one bids to allow the owner to change the reserve price.
Layout & execution flow
Our dapp will consist of two contracts, a stateless and stateful contract. On Algorand only stateless contracts can hold funds. If we want to temporarily store bids during the auction, we will need to couple a stateless smart contract to our stateful contract as an escrow. To couple the two we will need to store the app id of our stateful contract in the escrow. And add the escrow address in the stateful contract.
Besides the escrow address, we will need to store more information in the stateful contract:
- Info about the certificate to identify the coupled asset
- Addresses of royalties receivers
- Info about the auction (duration, end round, highest bidder, highest bid)
The royalty system
Algorand smart contracts are writing in TEAL, which is short for Transaction Execution Approval Language. The only thing the logic in our smart contracts can do is decide if transactions involving the contract should fail or succeed. A contract can not send transactions itself. To enforce royalties we will need to approve a set of transactions that includes payouts to the shareholders.
Enforcing royalties through checking single transactions is near impossible. Therefore we need to make use of another Algorand feature, Atomic Transfers. This is a group of transactions that all fail if one of the transactions in it fails. We can make use of this in the contract by checking the group for a certain set of transactions.
In our case, we will check if royalties are being paid to the right addresses. If they are not paid we will let the transaction fail. The atomic transfer for the royalties payout is illustrated in figure 2, if we assume the escrow holds the funds from the winning bid.
In this case, the owner, creator and manager have a share in the profits. Only at the first sale, the creator is the owner and therefore the split is not 85 /10 /5 but 85 / 15.
In the technical break down this is explained further, but it does not matter who the sender is in this transaction. Only the escrow is transferring funds in this case and there are no other payout options. Either the funds are split in a predefined way or the transaction fails. To preferent a stakeholder from not paying out the funds, the sender in the end auction transaction should not be locked down to a single address. Anyone should be allowed to perform this predefined payout transaction.
The auction system
To make sure the asset always sells for the market value, we only allow transfer through auction. The owner will need to send a transaction to the stateful contract with two arguments: the reserve price and the duration. Once that transaction is approved the contract starts to accept bids. As long as no one has bid the owner can still stop the auction by sending another transaction.
When the first bid is placed the timer will start with the duration set in the start auction transaction. All the bids are atomic transfers as illustrated in figure 3. By default, the highest bidder is set to the owner. When that is the case no bids have been placed yet and the escrow is empty. Funds then only need to be sent to the escrow.
If the highest bidder is no longer the owner then funds also need to be returned to the last highest bidder. This payback transaction needs to be sent by the new bidder.
Burning
Smart contracts can be burned or destroyed as it is called on Algorand. When and who is allowed to can be programmed in. When a stateful contract is destroyed the global state is deleted. The change history of the global state can still be seen in the app call transactions. The contract is no longer operational, all transactions to it will be rejected.
Current limitations
There are currently several limitations that hinder the use of smart contract-based NFTs. Most of these limitations have workarounds that make the smart NFT still useful. But only with better support for dapps can the full power of the smart NFT be harnessed.
One of these limitations is the app limit on Algorand. Currently, every address on Algorand is only allowed to create 10 stateful smart contracts. Any user will therefore only be able to create 10 certificates. You can work around this limitation by rekeying another address to your own. When you rekey, you remove all signing rights from one account and transfer them to another. That account is now able to send transactions for the new address with their own keys. Another 10 stateful smart contracts can now be deployed under the new address. This can be done many times, increasing the limit by 10 every time.
Another limitation is the discoverability of the smart contract. Because it is not a token, it can not be viewed in wallet apps at the moment. Those often do not support any form of contract viewing. Blockchain explorers also only allow you to search for the app id and not the asset reference in the global state.
This is logical since a stateful contract’s global state is fully configurable, making it more difficult to search. There will need to be more standardisation in the smart contract space before any wallet apps will start integrating contract support.
Conclusion
You now know the general idea and execution of the smart NFT. Al the transfer logic is integrated into the certificate to create what you could call a build-in marketplace. Technically the entire auction can be executed without any logic on a site or server besides sending the atomic transfers. For a better user experience, you would of course want to abstract the sending of transactions away and just have a bid button.