I often get asked this question:
WELL-MEANING FRIEND OR RELATIVE: Oh, Evan, you work in the cryptocurrencies industry? Oh-ho, are you making your own coin, when is EvanCoin coming, oh-ho?
ME: Ha-ha, oh, it’s not like that [blah blah blah]
Eventually I got fed up, now I answer:
ME: (suddenly intense) It will be coming very shortly and it will be built on Algorand.
This surprises people, but it really is that easy to build your own layer two application on Algorand! (A layer two application on Algorand will typically consist of an application that manipulates data using Algorand transaction’s note fields. This is as opposed to layer one code, the code that lives in the protocol itself.)
Today, I will show you a demo I made using the Algorand
examplecoin demo lets you build your own personal coin on top of Algorand! In this demo I will initialize EvanCoin on the Algorand blockchain, and transfer some EvanCoin from one account to another. Checking out the Algorand developer documentation might help you follow along, too.
You can find
examplecoin on my GitHub. It allows a developer to initialize an example coin on the Algorand blockchain, and tabulate the current balances of any example coin on that chain, so long as the coin’s master key is known.
To do this, the
examplecoin application uses the
Note field of Algorand transactions. It places base64 encoded data in the note field, and uses Algorand’s account management to make sure the notes come from the correct accounts. The initialization of an
examplecoin is a base64 blob placed in a transaction, as is the transfer of an
examplecoin. Maybe it’s easier to explain with an example. Here are the
examplecoin structs, which are barely more than “who’s sending to whom, and how much?”.
You can then take these structs and convert them into
byte arrays, suitable for a transaction’s note field:
You can see more on the full GitHub repo. The idea is that you can then read in these byte arrays and get the
NoteField structs back using
Algorand layer two is very flexible, so I want to rephrase and restate what we are doing here: we are taking arbitrary data structures and posting them to the Algorand blockchain, reading back these data structures later, and using that to inform new data operations. This means that you, as an app developer, can build any application you like on top of Algorand. The blockchain is providing you with verifiable secure storage. This also means that, if this application were handling sensitive or private data, we would have to handle the fact that the data is being posted to the public chain.
But we don’t have to care, because this is my own personal
examplecoin, EvanCoin. Let’s go make some coin and move it around.
Below is a snippet that produces the blob for initializing an
examplecoin and transferring
examplecoin to another account. The
coinKey variable is the address determining the master of the
examplecoin: you could sort of consider it analogous to an
ERC20 contract address. The
receiverKey is the account receiving the
examplecoin. Since this demonstration is just for me, and I intend to keep all EvanCoin to myself (everyone keeps asking me for EvanCoin, too bad, they can’t have any), I’ll just create
uint64(100) coins, and transfer half to another account I control. Here’s the snippet for that:
Running the above code, I get the following output blobs:
initNote looks like gqFpgaZzdXBwbHlkpHR5cGWhaQ==
transferNote looks like gqF0g6ZBbW91bnQyq2Rlc3RpbmF0aW9u2TozUTdKWDNUWVNNRjJNQlBZWjJHTTRHRjNQWFdMNFozNDIzNURHVExRQ1BVUFAzSTY0RldWTFozWTM0pnNvdXJjZdk6NUFRVTNTU05MVEVOTzQ0UFBLQ0ZHRUREVFNCUE5FQURLNFVFWEZEVFFMUVJPUjM3Q0JZN1ZDRktEVaR0eXBloXQ=
Now that we have these notes, we can post them to the chain. The SDK lets you transact easily. The
go doc documentation for the SDK can explain more about transacting. Here, we’re going to focus on the
Note field, where we can place our data. We will place the
initNotesBytes64 blob in the
Note field. (It’s important to know that the
examplecoin demo will only inspect transactions that are
from the master
coinKey address. So, here both
from are set to the
coinKey address. Just one of the two matching would be sufficient when reading data back later, though.)
Nice! The initialization blob has been posted. Now let’s transfer some EvanCoin. To do so, we do exactly the same as above, but this time using the
transferNotesBytes64 blob, building it into a transaction and sending it to the network.
(We could have also used the
goal commandline utility to post these notes: something like
goal clerk send --amount 1 --noteb64 gqFpgaZzdXBwbHlkpHR5cGWhaQ== --from 5AQU3SSNLTENO44PPKCFGEDDTSBPNEADK4UEXFDTQLQROR37CBY7VCFKDU --to 5AQU3SSNLTENO44PPKCFGEDDTSBPNEADK4UEXFDTQLQROR37CBY7VCFKDU. For this article, though, we’ll stay within
Success! Our transactions have been submitted. (I’m running this against my own private test network, created using
goal, so I don’t have to worry about the fee market, or wait for transaction confirmation: I know my transactions will be included in the next ~5 second block. If I wanted to explicitly wait for transaction confirmation, I could use the SDK to query whether the transaction is pending or confirmed.)
I’ll run the
examplecoin utility to tabulate the results. (I have omitted this step, but I also noted which the round range in which the transactions were confirmed, using
Status() call, so I know both transactions got posted between rounds 500 and 550. To make things run faster,
examplecoin uses this info to inform the utility which blocks to look at.)
$ algorand-l2-examplecoin -verbose=false -coinkey=5AQU3SSNLTENO44PPKCFGEDDTSBPNEADK4UEXFDTQLQROR37CBY7VCFKDU -firstround=500 lastround=550
Wrote results into results.csv$ cat results.csv
Success! I have 50 EvanCoin in one account and 50 EvanCoin in another account. 😎
GOTCHAS AND BRAINSTORMING
- In this demo I assume the
examplecoinutility will be used by very few users (just me) to manage very few accounts, so there’s a few scalability issues: using a
csvrather than a database, for example, or trying to hold everyone’s running balance in memory as the results are tabulated.
- Currently the utility starts from scratch every time you run it, and overwrites the output file entirely. One could change it to use a preexisting output, and just scan along the chain from where it left off.
- Since the utility needs to read every single block in a potentially large range of blocks, it needs to be run on a machine with an Algorand archival node or relay, so that the blocks that the utility needs are never pruned.
- I have not audited any of this code for correctness or security, as it’s a quick toy demonstration. I wonder if someone can steal my precious EvanCoin? 😱
- I mentioned briefly that this functionality is sort of analogous to named fungible tokens, similar (kind of) to
ERC-20. With some changes, one could probably tweak things to work like nonfungible tokens (NFTs).
- Code and data can be one and the same thing, can’t it? Can you picture a system that puts code on the chain as encoded data, executes it, and puts new code on the chain in response? A self-amending program? 🤔
Thanks, everyone, I hope this little demo helped or educated you in some way. We’re all in this together! 🎉