This is a workshop for building compliant and privacy-preserving tokens on the Aleo blockchain.
By the end of the workshop, developers should learn:
-
Why Aleo is uniquely positioned to enable compliant private payments and transactions
-
How to create a basic token in Leo
-
How to implement public/private
transferandmintfunctions for that token
Head into the private-token-workshop-token-template/ submodule of this repository. Create your own fork of that submodule.
If you're new to developing or just want to try out the Leo language, check out the Leo Playground. It's a web-based IDE that's designed to allow developers to build, deploy, and execute programs, all in the browser! It comes with an editor, Github integrations, and a number of utilities to manage programs and interface with the network.
You can load the project directly into the Leo Playground by connecting your Github account and loading the private-token-workshop-token-template/ submodule fork you just made.
Head over to the command line section of the Leo Playground and run the following command:
leo account new
This will generate a new Aleo account with the corresponding private key, view key, and address. The output should appear something like this:
Private Key APrivateKey1zkp...
View Key AViewKey1..
Address aleo1...
Keep track of all of these, as you'll need them later.
You'll need some Testnet tokens to deploy and interact with programs onchain. If you're partcipiating in an in-person workshop, ask one of the leads to send you some. Otherwise, head over to the official faucet. For the faucet, you'll need to load your account into one of the official wallet providers. Follow instructions on the page for more information.
Once you've funded your account, return back to the Leo Playground with the project loaded in and open the .env file. This file is where you can specify the network and endpoint to broadcast to, as well as the private key to sign transactions with. Fill in the PRIVATE_KEY field with the private key you just generated.
This is the Leo project where you will be doing all of your coding. Some basic features have been included, including a record type for private balances and a mapping to keep track of public balances
In addition, the function signatures/headers have already been provided for you, as well as a list of features you will need to fill in for each function.
The ofac_check_demo.aleo program is designed to mimic an onchain compliance check. It contains a simple mapping of mock "OFAC-sanctioned addresses" and a transition function to validate addresses against that mapping.
This program is already deployed on Testnet, and is added as a remote network dependency in the private-token-workshop-token-template Leo project. It is here purely for reference. You should NOT need to edit/use anything in ofac_check_demo/ or edit your private-token-workshop-token-template/ dependencies.
First, we're going to build a token program in Leo by filling in the provided template code. The program will include:
-
mint_public&mint_privatefunctions -
transfer_public&transfer_privatefunctions -
Compliance checks against the
sanctionedmapping inofac_check_demo.aleo
Choose what your token program will be named! This should be longer than 10 characters to avoid additional network fees. It should also not conflict with any existing program on the network.
Once you've decided on a name, change the name of the program at the top of main.leo. Additionally, change the "program" field in the program.json file to match the name of your new program. These two fields MUST match or your program will not compile correctly.
This feature mints new tokens by updating the public mapping value for the recipient. In line with Aleo's async model, it is split into two separate functions:
This is an async transition that is executed offchain and has its corresponding zero-knowledge proof verified onchain.
-
First, you should call the
address_check()function fromofac_check_demo.aleo. This has already been done for you in the template. -
You should then pass the returned
Futureto themint_public_onchainfunction alongside the other appropriate fields.
This is an async function that is executed onchain.
-
First, await the
address_check : Future. This has already been done for you in the template. -
Set the value for
recipientin thebalancesmapping to the current value plusamount.
This feature mints new tokens by initializing a new private record with the specified amount of tokens for the recipient. In line with Aleo's async model, it is split into two separate functions:
This is an async transition that is executed offchain and has its corresponding zero-knowledge proof verified onchain.
-
First, you should call the
address_check()function fromofac_check_demo.aleo. -
Next, initialize a
Tokenrecord with therecipientas the owner and theamountas the amount. -
Return the
Tokenrecord and pass theFutureto themint_private_onchainfunction.
This is an async function that is executed onchain.
- Await the
address_check : Future
This feature publicly transfers tokens between two users by deducting the transfer amount from the sender's balance in the public mapping and adding the same value to the recipient's balance
This is an async transition that is executed offchain and has its corresponding zero-knowledge proof verified onchain.
-
First, you should call the
address_check()function fromofac_check_demo.aleo. -
You should then pass the returned
Futureto thetransfer_public_onchainfunction alongside the other appropriate fields.- For the
senderfield, you can useself.signerto specify the address that initialized the function call
- For the
This is an async function that is executed onchain.
-
First, await the
address_check : Future. -
Next, set the value for
senderin thebalancesmapping to the sender's current value minusamount -
Finally, set the value for
recipientin thebalancesmapping to the recipient's current value plusamount
This feature privately transfers tokens between two users by consuming the sender's Token record and producing two
new Token records. The first is owned by the recipient with the amount sent, and the second is owned by the sender with any leftover amount.
This is an async transition that is executed offchain and has its corresponding zero-knowledge proof verified onchain.
-
First, you should call the
address_check()function fromofac_check_demo.aleo. -
Next, initialize a
Tokenrecord with therecipientas the owner and theamountas the amount -
Initialize another
Tokenrecord with thesenderas the owner and the remaining balance as the amount -
Return both
Tokenrecords and pass theFutureto themint_private_onchainfunction
This is an async function that is executed onchain.
- Await the
address_check : Future.
Now that you've built and tested your program, you're ready to deploy your program to Testnet. This is where you'll need the Testnet credits mentioned earlier.
After deploying, you should now be able to interact with your deployed program onchain.
-
Publicly mint 100 tokens to your address
-
Publicly transfer those tokens to
<SUBMISSION_ADDRESS> -
Privately mint an additional 100 tokens to your address
-
Privately transfer those tokens to
<SUBMISSION_ADDRESS>
Submission Address: aleo16ee2zncu2t6ftcpnnnmyd3c6pf8eu2xfyksh23amwqgvapp6mg8q8hy7e0
Submission Link: https://forms.gle/gWG11bzgWCkALwyb9
