Introduction to Aztec Development I Ciara Nightingale
ETHGlobal·Tue, Dec 9, 2025, 12:00 AM
Join Ciara Nightingale for a workshop titled "Introduction to Aztec Development", featured at ETHGlobal Buenos Aires 2025! _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 🇦🇷 *ETHGlobal Buenos Aires* This workshop is specifically for ETHGlobal Buenos Aires, a 3-day hackathon held November 21-23 at the Centro de Convenciones Buenos Aires, bringing together the most skilled web3 developers, designers and product builders from all around the globe for a weekend-long adventure to advance the Ethereum ecosystem! Watch the full ETHGlobal New Delhi 2025 playlist here: https://www.youtube.com/playlist?list=PLXzKMXK2aHh76O7FfAHPJkZcqTIfYpoyf _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ✅ *Follow ETHGlobal* X: https://x.com/ETHGlobal Warpcast: https://warpcast.com/ethglobal Website: https://ethglobal.com YouTube: https://www.youtube.com/c/ETHGlobal _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _Are you interested in Ethereum development and entrepreneurship?_ 👉 Sign up for the next ETHGlobal event: https://ethglobal.com/events 🎁 Get exclusive access and perks with ETHGlobal Plus! https://ethglobal.com/plus 📣 Want us to throw an event in your city? Tell us where! https://ethglobal.com/city
Transcript
Hello everyone and welcome to this introduction to Aztec and programmably private smart contract development. If you're a Solidity developer, you're in exactly the right place because I am going to be assuming that that's who you are. So, I'll be assuming knowledge of the fundamentals of blockchains, why they're super cool, smart contracts and smart contract development. But don't worry, obviously, I'm not going to assume that you know Aztec smart contract development, what Merkel trees are, and how state works on Ethereum. Aztec is very different from other EVM chains because as well as having public state, it also has private state.
Therefore, to really understand Aztec, we're going to split this video into three parts. The first part is going to be convincing you about why you should develop on Aztec and why privacy is super important. The second part is going to be about how Aztec works from a high level. And this is a little bit conceptually difficult. So, I do recommend that after this video, you go back and read the documentation to really understand how things work because once you've got these key concepts nailed, your process of developing on Aztec is going to be so much simpler.
And then the third thing that we're going to do is set up our development environment so we can write, compile, test, deploy Aztec smart contracts ourselves. So, as with all of my videos, I'm going to do a lot of talking, but hopefully show you some fun visuals. So, get yourself a drink, get yourself a snack, and let's get into it. So, first of all, why do we need privacy? Now, if you haven't read Zach's privacy manifesto, I really recommend that you do so.
If you need convincing as to why we actually need privacy with blockchain technology, but the TLDDR is this. Blockchains are great for many reasons. They are, of course, decentralized, well, most of them are. They're credibly neutral, trust minimized, permissionless, but they are also transparent, which is a good thing because it means that no one can lie and everyone can see everything. And it also means that we can verify things like balances.
You can check whether someone has some minimum amount of balance to be able to participate in your protocol. However, there are instances and lots of them where we need and want our data to be private. Particularly big institutions, they don't particularly want to be sharing all of their data to everyone in the whole world. And also for you the individuals, you also want your data to be private. I don't particularly want everyone to be able to see what I invest in, how much money I have, and everything about my onchain activity.
Not very good for offset. So what if we can combine worlds where we have state that is both private, so you own your own data and no one else can see it, but also verifiable. For example, I can prove that I do have enough money to buy those tokens. I can prove that I do have that access pass NFT without actually revealing my balance or any other information. I want to be able to buy those tokens, decrement my balance, verify all of the state transitions without revealing anything about any of the execution or any of my data.
And this is exactly what Aztec achieves. Programmable privacy. So you the developers have the ability to choose what state is public and private. What functions are executed in public and what functions are executed in private. This of course means that developing on Aztec is pretty different from developing on Ethereum.
And this is because of that addition of private state and private functions. Let's go into a little bit more about public and private state as they work quite differently from each other. The first call out I want to make to avoid some confusion is a big mistake that solidity developers make at the start of their journey and that I personally also made which is that assuming that Ethereum already has public and private state. We obviously have those visibility specifiers public and private that we can prepend to our state variables. But we now know this does not mean that private state variables cannot be read by blockchain observers.
Private just means that other smart contracts cannot read that state variable, including inheriting contracts. Public means that you automatically get that get a function that other contracts can call. These specifiers control the visibility between smart contracts, not between the blockchain and end users. Anyone can of course come along and analyze the contract storage to obtain all of the values even if they're private. Aztec however has of course private state and this is private with respect to the end users.
The private estate is cryptographically hidden from everyone except the owner and of course anyone they choose to share their data with. Whilst public state is visible to everyone. It's transparent and these two types of state so public and private state are managed using two different state models. Public state is accountbased so it can be directly updated and read by anyone. So public state works pretty much exactly the same as it does on Ethereum.
Whenever data, for example, a balance is stored, a key value pair is created. For example, some owner's address and their corresponding balance. When the data is modified, the value corresponding to the key is updated. And this accountbased state is updated directly when the transaction is executed on chain. Public state is stored on Aztec in the public state Merkel tree.
Private state is not account-based, and it's where things get a little bit wacky. If you do get confused in this section, please please please visit the documentation and do some reading around the subject. It does take a little bit of time for you to really understand what's going on here and to get a mental model of how private state works and then how it connects to the blockchain etc. So firstly to keep things private private functions cannot be executed on chain and private state cannot be stored directly on chain because otherwise of course everyone would be able to see it and know what happened. Instead, private functions are executed locally and private state is stored locally on the user's device and then a zero knowledge proof of the execution is sent to the sequences and verified onchain.
Private state is not accountbased. To understand why and really see the problem, let's assume for a second that it is. Let's say we have an account-based state model for private state and instead we're just encrypting the data. So we have some encrypted address that maps to some encrypted balance and maybe only the user can decrypt it. When we send a transaction, this value in this storage slot will be modified directly.
So even if the key and the value are encrypted, the data location is leaked. Using correlation techniques, this can of course expose information. For example, we could link a user to their balance location and this breaks privacy assumptions. So instead, private state uses a UTXO based model, a little bit like Bitcoin, and uses something called notes. We're going to dive into notes very shortly, but let's have a look at UTXOs.
The UTXO based model is very similar to physical cash. When you have cash in your wallet, you never actually store a total balance. Instead, you have individual bills, maybe a $10 bill and a $20 bill. If you wanted to pay someone $15, you can't split your $20 bill in half or update the amount. Instead, you have to hand over both bills and then the person receiving it would have to give you $5 back as your change.
And Aztec notes work a little bit similarly. Instead of having a total balance of 30 tokens, instead you might have one note containing 20 tokens and another note containing 10 tokens. So, what are these pesky little notes? Notes are just private data. They're not particularly complicated actually.
They are just a strct containing some data, eg some note owner and maybe the value of that note and then some methods to do things like create a commitment and create a nullifier which we're going to come back to shortly. For example, this is one of Aztec's notes called the uint note. So you can see here that you have the strruct and then down here we have some methods on this note. So notes are literally just private data and they are stored locally on the owner of that note's device. So the user's device and they are never stored on chain in their raw form.
Instead we create a commitment of this data. So a hash of the data with some randomness to prevent brute force attacks is stored in something called the note hash Merkel tree. The key thing is that notes cannot be modified. So the note hash tree is append only. We cannot delete notes from the tree and we cannot change them.
In the same way that you can't edit the value of a $10 bill. It's just $10. Notes are either spent or what we call consumed or unspent. Let's say Alice has a note with a value of 10 tokens and another note with a value of 20 tokens. Let's say she wants to send Bob 25 tokens.
She would have to mark her two notes as spent or consumed and then create two new notes. One note for Bob with a value of 25 tokens, the amount she wanted to send, and then another new note for herself with five tokens representing her remainder. But what does it mean to consume a note? How do we mark it as spent? We can't remove it from the note hash tree because it's append only.
How do we know if notes in the tree are spent or unspent? This is where nullifiers come in. A nullifier is a deterministic piece of data derived from the note that it corresponds to and it can only be calculated by the note owner. And presence of this nullifier marks a note as spent. And these nullifiers prevent double spending because if the nullifier is present, it means the note is spent, therefore it cannot be spent again.
and nullifiers are stored in yet another Merkel tree called of course the nullifier Merkel tree. So let's go back to Alice and Bob. So Alice wants to send Bob 25 tokens. She consumes her two notes, her 20 token note and her 10 token note by first proving that she has a valid commitment in the note hash tree by proving knowledge of the pre-image which when hashed creates a valid commitment in the note hash tree. And then she creates two nullifiers, one for each note, which are then added to the nullifier tree to mark these notes as spent.
She then of course creates two new notes, one for Bob and one for herself as the remainder, which she can then spend at a later date. But how does she share this 25 token note with Bob without posting the raw data on chain? He needs access to that raw data to be able to spend his note at a later date. This data can be shared in a number of different ways. She could share the raw note data offchain with Bob maybe by email or WhatsApp QR code carrier pigeon or she can use something called note discovery.
This is out of scope of this video as it's a little bit complicated but basically it's a way for Alice to let Bob know about his note onchain without revealing the raw note data with anyone else. Please visit the Aztec documentation if you'd like to understand more about note discovery. And that is pretty much it. So public state is account-based and works pretty much the same as Ethereum. Public functions are executed onchain and public state is stored onchain.
Private state is UTXO based and uses the concept of notes. Raw notes are stored offchain locally. Note commitments are stored onchain in the note hash tree which is an appendon Merkel tree. If a note is spent or consumed, a nullifier corresponding to that note is stored in the nullifier tree. private functions are executed offchain and then ZK proofs of the execution are verified onchain to make sure that all state transitions are correct.
So it's great understanding all of the theory about the Aztec protocol, but what about Aztec smart contracts? Aztec smart contracts have to deal of course with private state, public state, private functions, public functions. They have to be able to create zk proofs of the execution and so many more other complexities. Therefore, of course, they cannot be written using Solidity. Instead, they are written in noir and using a framework called Aztec Noir.
Aztec Noir just provides some helpful functions and wrappers to be able to make it easier to handle notes, private state, creating nullifiers, creating commitments, and so much more. I'm not going to be going through noir or Aztec noir in this video as that would just make this video way too long. Instead, let's jump into setting up your development environment and have a little look at an Aztec Noir smart contract and then I will leave you guys to be able to scour the documentation to understand how to write these smart contracts. Let's get into it now. Okie dokie, artichokei.
Let's get our development environment set up so that we can become awesome Aztec smart contract developers and build smart contracts with programmable privacy. So the first thing I'm going to say to you is that you will need to have Docker installed and running. Otherwise, this whole demo is not going to work. I'm also going to assume that you have the Noir LSP installed. Next, next.
Next. We need to pull up our terminal. And then we are going to install the Aztec tools. To do that, head to the Aztec docs and make sure that the version you're on is DevNet and then click on setting up the DevNet. To be honest, any getting started guide is going to show you this.
And then scroll down and it'll have the getting started steps. And then we're going to copy this bash command. We're going to paste that into our terminal. Hit enter. Yes to continue to allow it to install the following tools and then update our path.
So Aztec, Aztec Nargo, Aztec postprocess contract, Aztec up, and Aztec wallet. If you'd like to know what each of these tools are, please visit the documentation. And then once that is done, let's run Aztec- version to check that it is all installed. And then you'll see here it says 2.1.
4 or whatever version you've installed. But instead, we want to have the DevNet version. So we're going to run this command aztec up, which installs the latest version if you don't specify a version, and then the version that we want to install. Now, if we run Aztec- version again, you'll see that we do in fact have 3.0.
0-devet.4. The repository that I'm going to be using for this demo, just to show you some of the commands that you can use to compile your smart contracts, test them, etc., is going to be this Aztec starter repo. Now, this is a really good repository for you to read through to understand how to write smart contracts.
And then in the readme, it has all of the instructions for how to use the repo. It has a little config which allows you to specify whether you are working on DevNet or Sandbox. Sandbox is currently being renamed to local network. So don't worry if that's a little bit confusing but this is your local network a little bit like anvil for you foundry developers and then devet you can consider from a developer perspective to be test net. Let's have a little look around this repo.
So if we head inside of source this is where all of your smart contracts are defined. Main.nr is where our smart contract lives and you'll see here we have an example smart contract which is a voting contract. I'm not going to go through all of this syntax, but the high level is you have a strct for all of your storage variables. So, we have an admin, tally, vote, ended, an active at block, and you'll also see this one's public.
We've got a map of fields to some public mutable variables, another public mutable, and then a public immutable. So, we don't have any private variables. We have a constructor, which is very similar to solidity except it can be called after deployment, and then we have some functions. So we have a function called cast vote which is a private function as you can see here in this macro add to tally public which is a public function of course end vote which is again public and then something called a utility function that allows us to get the vote for a certain candidate. Again I'm not going to go into this in detail but I do recommend that you read through if you'd like to understand a little bit more about smart contracts on Aztec.
We then also have a test folder which includes some Aztec noir tests. So this is akin to your solidity test that you write with foundry. These are going to be your unit tests. So you've got things like test check vote status test end vote. You'll also have a utils file which allows you to set up the environment.
So you don't have to do this setup every single time you run a test. Instead we just run this setup from utils in every single function. And then we also have endtoend tests which are written in Typescript. And this uses AztecJS which allows us to do things like get test wallets, create account, get the gas fees, and so much more. So we can now go ahead and clone this repo.
So I'm going to copy the URL and then I'm going to get clone the repo and then I'm going to navigate into it and then open it up in my code editor. So then I can have another proper look around maybe at all the different files etc. So let's say we have written our smart contracts and we've written some tests. Because we are using JavaScript for our end to end tests. So testing things like our scripts.
Let's install our dependencies by running yarn install. And then let's compile our smart contracts. We can do this by running Aztec- nargo which is the Aztec flavor of Nargo. If you want to see more about Nargo, then visit the Noir documentation. If you want to know more about Aztec Nargo, then visit the Aztec documentation.
Anyway, this allows us to do things like compile. The other compile. The other command you need to run as well is going to be Aztec postprocess contract. And this will just process all of the contract artifacts that compile creates. In the future, these commands might be combined together, but as of right now, this is the process.
And then hopefully inside a target folder, you will now have your compiled contract. We can then generate the contract artifact JSON and TypeScript interface so that we can interact with the the contract from our TypeScript files. We can do this by running Aztec code gen target-out directory src/artifacts and then you'll have this artifacts folder which inside will have a TypeScript file which will create our private contract class for us to be able to interact with with all of the functions on the contract in here. And then if we look in our endto-end tests, you'll see that we do in fact use this artifacts private voting.js.
Then we can see where that's used. We use it here to deploy the contract. And then this contract is used to call the functions on the contract. Okay. So now let's say we're happy with our tests.
Let's first run our Aztec noir tests. So our unit tests. We can do that by running simply Aztec test. Amazing. Our seven tests pass.
Note that if you do change your smart contracts, as of right now, you have to manually recompile them. The test command is not going to do that for you. Then let's also say we want to run our integration tests. So our end to-end tests and we want to do that on DevNet. So we want to test all of our scripts, all our deployment scripts and everything.
So as I said, these are written with Aztec.js. So to do that we have helpfully created a little command using the config to set up all the things like RPC and blah blah blah. If you want to have a look please look into the code to see how this works. But I'm going to just run yarn test colon colon devnet and then this will set up everything for me.
So you can see the command that was actually run here. So our first end to end test passed and now we're waiting for our second one. And all of our tests passed. The final thing that we'd want to do is learn how to be able to deploy smart contracts. So we actually have a deployment script.
So if we head to deploy contract, then in here you will learn how to do just that. So I recommend that you read through this if you want to understand how to deploy them. I'm not going to walk through this code right now, but you can feel free to of course read through this to understand how to deploy your smart contract using Aztec.js. To run this script, we can literally just run deploy yon deploy colon colon devnet to deploy this to devnet.
Hit enter. It will then run that script deploy contract. It will then create us a wallet. We scroll down. It created an account.
And here you can see the secret key that was generated, the signing key that was generated, the salt and the address. Now because Aztec has native account abstraction, your account is itself a contract which is pretty awesome. Now of course if this was even a test net to be honest because you know test net funds can be pretty hard to come by. You don't want to be sharing these bad boys and you need to make sure you save them. I really am not keen on using an EMV for your secrets and stuff but because we're on DevNet and test net I'll allow it.
But of course use a key store if you can. Anyway, so that has now done. So we have successfully deployed, well, first we deployed an account contract and then we have deployed a smart contract for our voting contract. We could then interact with that by running this interaction script, but I'm not going to do that right now because it'll just be another yarn command. So not particularly interesting to you guys.
Anyway, so that was it. That's the demo. I hope you understood a little bit about Aztec. If you don't, please head to the docs. There's lots of information there.
Harsh has also created some awesome projects such as an OTC desk on Aztec that I recommend that you go and look at the code for because that would be really useful for you guys to understand how private smart contracts work and it also uses something called partial notes which are really really cool by the way and thank you so much for watching this video and learning a little bit about Aztec and private smart contracts. You are in the right place if you want to be on the front of blockchain technology and keeping up with things. I'm super excited to see what you build and what you get up to. Make sure you also join the Aztec Discord. If you'd like to connect with like-minded Aztec people or if you have any questions, then that is the place to ask them.
Aztec support is absolutely amazing. Whenever I have had problems, I have dropped them in the Discord and they've been answered very, very promptly. It's pretty impressive to be honest. Good luck.
Automatic transcript — names and jargon may be misspelled.