Author a Simple Private Contract

NoirCon 3 at Devconnect Argentina 2025 · 20 Nov 2025 · 50:40

Zorzal, Team Lead at DeFi Wonderland, builds a simple private Aztec contract: a counter that lets whitelisted users privately increment a public value. The session covers notes, private and public execution and note nullification, then adds unit tests in Noir and end-to-end tests in JavaScript before deploying to devnet. It was held at NoirCon 3 during Devconnect 2025.

Speakers

Topics

From NoirCon 3 at Devconnect Argentina 2025, hosted by Aztec Network.

Transcript

Good morning GMGM. Thank you everybody here for taking choosing [music] to spend your time at our third inaugural noon. >> Hi everyone. Uh in this workshop we are going to be building a really simple simple private smart contract on Aztec. Um first thing who has been like to the previous workshops like explaining what's like the theorical stuff about Aztec who knows about like private versus public space who has set up Aztec once on their computer. Oh Okay. So on that QR code there are some like uh small instructions into setting everything up.

Uh you will need to set up Docker and like install Aztec and download a repo. Um, if you want to follow along in the workshop, you can do that. If you don't want to follow along and just want to see me code, that's fine, too. Um, so yeah, uh, my name is Shyto. I'm from Wonderland. I'm partner lead with our partnership with Aztec. We are building a couple of things. Um we are building a lot of developer tooling with for example the Aztec boilerplate uh that allows you to start projects really easily or the AEC benchmark which allows you to like benchmark two different versions of a contract and see how much uh the DA cost or L2 gas you are using um compared to that and then we are also building the standards uh we have a

repository that is called Aztec standards that has a token an NFT and other standards that we will start building over time. Um, okay. I'll take out the QR code. So, if you want to scan, it's now. So, if you follow along, you should have Wait, I need to remove There we go. You should have something like this. And if you run yarn and run compile and yarn test, it'll run the tests. I'll show you the contract in a minute.

>> So, yes. there. >> Good. The internet does not help. Okay. In the meantime, while this compiles, um we are going to be using the counter contract. uh is a it's a really really small contract that basically has uh a public variable that is called a counter which is a public motable and it allows anyone to call a private function that is called increment and the increment function what it does is that it calls itself calling the function increment internal and it ences

it to public that I will explain in a minute. Um when that call happens it calls this function the increment internal which reads the counter and then increases its value by one. That's literally the contract. That's it. Um the interest part the interesting part about this is the mix between private and public space because you are calling a private function. Um you cannot access public variables. In this case, you have the counter which is just a number that is public and you wouldn't be able to access that from private state private state and the only way for everyone to know what the value of counter is if if it was public. Um, so what you do is ignore that.

Come on. There we go. So what you do is you use this keyword or this call which is in Q. And what this basically does is that um this will execute this this will start the pi the execution pipeline for your function in private. It'll do everything and then it will uh call the public state in the end to execute that. Uh so this is a way for you to interact between private and public. You can interact from private to private from private to public but you can never never interact from public to private because private execution always happens in the user device. So if you wanted to do public to private and public execution happens on an RPC, you wouldn't be able to execute anything on

private space. So those are the interactions that are valid. Um first thing like let's say that I don't want everyone to be able to um execute the increment. So what I will do for that is let's say that I only want the other variable that we have which is admin to be able to call that function. That is really really easy. What you basically do is you can um grab the sender. Well, it literally like is completing my my code but you can check that the sender is equal to the value that we have in storage which is uh owner sorry and then you can revert in case it's not

equal not owner. Okay, so this call here basically like grabs the sender of the function of the transaction sorry and then it compares it to the owner of the contract. Just adding this um will guarantee everyone that the private call that is being executed is being done by the admin. No one else will be able to um to call this. And just as an example, if we go to uh let's go to increment.nr, N R this is a test. And then let's say that we want to set up another account which is not the admin.

Uh yeah, let's call let's create another account and let's call it not admin. And if we execute the call from not admin now we shouldn't be able to uh on compile and test this should revert just because we don't really have uh we are not really calling from the admin uh it's actually oh it's admin sorry confused the takes a little bit of time but yeah uh

it's compelling everything and now one test fails because we are calling it from another um user basically let's add a little bit more functionality um let's say that the owner doesn't really want to be present all of the time to call increment. Like let's say that you need to call increment like multiple times a day and it's a hassle for the like for the owner of the contract to be there all the time and he basically wants to set up multiple people that are able to call this function. Um one way to do this would be introducing notes. Um and a note explained in the like previous workshops is basically an a small unit of information. It's basically abstract literally that contains a little bit of

information. Uh for that let's call let's create the folder types and let's call it incrementor note. Uh let's think that we will I'll copy this just so we don't take that much time. Cool. [snorts] And now we have set up our first note. This is the incremental node. It only has two like really really small pieces of data. It has the owner the owner which is the owner of the node who will be the one that will be able to call increment and it has some randomness. Um why the randomness? Because if you only allow if you only have the owner in a node uh it's it would be really really easy to brought force checking different

addresses to see if they are incrementors. If you use this randomness, it will be like literally impossible for you or really really difficult, let's say, to try to brute force and see if his address is in the incremental nodes. Um, a couple of things that we uh implement here. Let me remove that. Uh, we use the trait equals uh which basically allows you to equate a node to another. And then we set up this which is um a way that you can give some functionality to your nodes. Uh in here we we should like we we are able to add any functionality that we want. And the only functionality that we added now is a function that is called new that

receives an owner and it creates the randomness inside and returns the note. This is just for us to be like for us to be like really simple to initialize nodes. We don't even need to generate the randomness in the contract. And just a quick thing to like explain here, the randomness is generated inside an unsafe keyword. Um that is because randomness is generated with a call to an oracle that is executed in the user pixie. The interesting part about this is that because this runs in my computer, I am able to change these things. So there is no way like for you to be 100% certain that I'm using a random variable. I could run this seven trillion times even

using the same like way of generating randomness and run it a million times until I get a number that I actually like. Um so that's why we call it unsafe uh in this case because the one that will be generated the incrementor notes is the owner of the contract. He has like no gain into using a randomness that is like not correct. Like there is no way like he he doesn't win anything by doing that. Cool. Let me to use this mod increment note.

Cool. This is just importing everything. And then on main we will remove this. Cool. And um there are multiple ways to use nodes. In this case we will use a data structure that is just um it's a private set. So we will call it incrementors. I'll call it private set increment or not. Cool. Uh now we have set up our first private set. And one thing that I forgot to mention is that um I mentioned before that private and public state is like completely separate. But one thing that I did not mention which is interesting is that um in here this is a private function and

we are reading the variable admin. Not the variable but the the parameter admin and admin is public. Um, Aztec does some magic things here and it allows you to use public immutable variables, public immutable um, values in private just because they are initialized at the start with the contract. This like gets uh, indexed or whatever and it allows you to access them in private. But everything that is mutable, you won't be able to access. Like if I try to call the counter, it will say that it does not exist in my storage. um just because it's mutable and there is no way for you to prove that this is the latest value of counter in your computer. [snorts] Cool. Now that we uh implemented the

incrementors notes, we'll add a new function for the admin. Let's call it let's say it's external. Let's call it let's say it's private and let's call it okay add incrementor. Let's do that. Okay. Um, let's grab the sender of the transaction and let's check if the sender of the transaction is the owner because we only want the owner to uh call this function. So, this grabs the sender. It compares it to the admin that is in the contract and if not it throws not owner. That's it. And then what we can do is insert and not let me create

it separately actually. I think it will be easier to kind of follow. I should disable autocomplete actually. Cool. In here, we initialize our note and we use the function like this helper function that we created that is new. So that's why it only needs uh the increment as a parameter. It doesn't need the randomness because it generates it inside. And then afterwards we can insert it into the private set.

Cool. Now our note is in our private set. The interesting part about that is that in inserting a note into a private set doesn't really help us in any way because no one has access to this node. No one has it. For a note to actually make sense, you need to either share it offchain as it was uh explained before in other workshops or you can uh share it onchain. And this is via the uh emit um function. So every time you insert a note, it returns a note emission.

And here I there we go. Um and then afterwards you can decide who will get this note, who will be able to read it. And to emit that note, you basically call note emission emit. And in here we send first the first parameter will be um the address in this case we want the incrementor to get this note and the second parameter is really interesting it's the type of message delivery okay the type of message delivery can be unconstrained or constrained um the difference between this is that if you emit a note in an unconstrained in a constrained way sorry there are uh more checks into validating

that whatever you are doing is correctly being done. So for example in this case we can call it constrained on chain or we could call it unconstrained. In this case we will call it constraint just because of like simplicity and it's the safest way but we should be able to use it unconstrained here. Why? Because again like because only the admin can call this function. he has absolutely no gain into emitting this note in an incorrect way. Like if I encrypt it in a different way that you know how to decrypt, you just won't be able to access the note and why am I doing this if I'm not

actually giving you the right to uh increment. Um, so I could do it unconstrained, but anything that can be done by users at and could um kind of up someone else if they did it in a bad way, you have to do you have to do constraint 100%. Let's say that in the token contract in the transfer, I allow for the creation of notes of balance notes without them being constrained. I can send you a note that is encrypted in a way that you don't know how to decrypt and there is no checks on chain to actually validate that the message delivery is is being correct and you wouldn't be able to access the funds. So in that sense like I would be able to

pay you you would be able to see that there is like something that you received or that I sent something but you wouldn't be able to decrypt the note. Um again in this case we'll only use constraint just because of simplicity but basically when you are building something you will need 100% to think about the different types of delivery. Yes. >> So this is putting the uh the note on James encrypted. This is the uh this is not the commitment that's separate and that's >> the commitment is separate and that will always go. Okay. Got it.

>> Like the commitment always happens. >> Okay. The commitment always happens but then like you can decide if the node gets shared on chain and then published to L1 of course encrypted like there is no way for anyone else to read it. Um but the commitment always needs to be like shared on chain because if not like you would be able to duplicate notes. >> Yep. Thanks. >> Cool. Now um we finished with the node. Do you want to send it in the hackmd? So if if anyone is like still following in the hackmd we will be uh sharing when we complete a function you can just copy it and paste it. Uh we also have a branch that is called fit/solution.

So if you want to see it after the talk you are also welcome to do that. Um okay so in this case now we sorry now we added an incrementor and the owner of the contract is able to call this and create a note that basically gives the right to someone else to call increment. Now we need to actually uh implement that logic. The logic that only allows the incrementors to call this function. Um for that we'll need to remove this assert. Let's um let's create a new function that is

called is a new variable that is called is admin. And for this [snorts] it will check that sender uh is equal now let's call it actually let me call it admin storage that owner that read cool in here we read the owner and then um if the admin is different that the sender so only in the case that basically the admin is not calling this function we'll do this check and in this check. What we will do is use let me copy it actually will be easier.

[snorts] Cool. So because a private set like is basically an array in some sense um we need to filter those notes and we need to check if the person that is calling this function has in their own private state they have the note and they are able to decrypt it. can prove that they can decrypt it. Um, in this case, what we'll use is this note getter options that allows you to select like different filters to find the notes that you actually need. Um, in this case, the only thing that we need to check is that the owner, which is a a property of the incremental node, equals the sender of the function. That's it. Um, and then we set the limit to one so that because we

know that it will always return at most one note. Afterwards we can call storage incrementors get notes and we send these options options so that it returns the array of nodes the final array of nodes and in this case if the person that is calling this has um one or let's say or more more than zero notes we know that they are an incrementor. So we only need to add an assert and check that the notes array is greater than zero. That's it. And if

it's not greater at zero, let's say not incrementor or admin. Let's remove this time. Cool. So now we added that. Um now the function increment can only be called by either the owner of the contract which is uh the admin or someone that has received um an incremental note basically and then uh let's add one last piece of functionality and then um we will go over to some tests and see if we can uh deploy into uh DevNet and deploy into the local uh sandbox. We'll add

another function and let's call it um remove incrementor. This basically will allow the owner of the contract to remove any incremental node. Okay. So to explain something that I added before in here we added two note emissions. This second one wouldn't be necessary if we weren't going to do this step. Uh like if we only wanted the incrementor to access that note, that's fine. We can only emit it to the incrementor. But because in the future we want to allow

the admin to be able to nullify that note, we also need to share that note with the admin. If not, the admin wouldn't be able to call uh or to nullify that note ever again because they they will lose that information unless they keep it off chain and they add it later. But this is like the simplest way. Um, so that's why we added the second emit there. Cool. And let's say let's actually copy it from here. Cool. And the remove admin, the remove incrementor, sorry, will basically do the same. I'll check that uh the caller is the admin of the contract and then it will uh remove the note from there. And

the removal of the note is really similar to getting the note. It's just using another function. That's why I will just copy it. And we will do the same filtering basically checking that the owner does not equal the sender but it equals the incrementor. So what this will do is that when the owner when the admin of the contract calls this function, it will see the incremental private set, it will have all of the nodes that the owner has created ever and it will find one note at least uh that has the incremental that they want to remove as the owner of that note. And then

afterwards because um you have the pre-image of the note and we allow the admin to call this you will be able to call instead of get notes which literally like returns the note you can call pop nodes and the difference between get notes and pop nodes is that uh get notes returns you the note and that's it and pop pop nodes it takes the note out of the set. How it basically nullifies the note. So now that note is not usable anymore. Yep.

>> You would have to do this for every hypothetically if you did it twice for one user. >> That's a that's a fantastic question. Yeah. Yeah. Like if you did it twice for one user because let's say that you made a mistake, you would need to do this like uh multiple times. One thing that we could do is like we could remove this set limit to one and you would be able to pop multiple nodes at the same time. Um, ideally, and we didn't do this uh just because it was uh like really short workshop, but you should be able to find a way to kind of stop the owner from creating multiple nodes to the same person in the ad incrementor. Um, at the start when we were planning this workshop, we ended up like trying that

out, but it didn't make a lot of sense. I'll explain why. Um basically what we did is we use this to kind of find the note if there and if there were more than zero nodes we reverted. Um that works right like it basically like checks if there are there is a note and if not it will revert. So if the admin doesn't have any malicious intent, let's say, which of course makes sense that the admin won't have any malicious intent, that would work, but because getting notes depends on the cooperation of the pixie. If the admin had something to earn by not providing the note, they could do it. Like basically, this doesn't force you to present all of the notes that actually um kind of match

this criteria. So you could have the note and you could be like nope I don't have that because it depends on your private storage. Um so for this you would maybe have to do something like more magical related to nullifiers and something like that and nullifiers you cannot uh kind of skip because those are always posted on chain in the nullifier tree. So, let's say that every time, and I'm just getting this out of my head, um, every time you add someone as an increment, you publish a nullifier, and then if you go to add [music] the same incremental a second time, it will try to publish that nullifier, and the notifier will already

be there. So, the transaction will revert. The problem with doing doing it this naive way is that if you do it this way, I add you, I then remove you, I post the nullifier, and let's say that a week after that I want to add you again. Uh then I'm So yeah, I won't be able to add you anymore. So you would need to like find another magical way using nonsis or I think at some point we kind of um played with that, but it's it's complex if you want to do it that way. Yeah. Uh but yeah, you could like just the admin doesn't have any malicious intent. You could add this and revert in case there are more than zero nodes just to avoid the admin from making mistakes. But that's it. Yep.

Okay, cool. Now um in the removing creator um we check that the sender is the admin. We try to find the note and if it finds um more than zero, it pops the note. uh in case there are zero notes like there won't be any issue. Uh so that's fine. Cool. And now let's go see if we can uh write some tests for this. Let's find it's actually called yeah increment.nr. [snorts] Okay.

Cool. There are a couple of tests that uh we could write for this. First, let me remove this test. Actually, let me copy it and have a second one that actually does what it needs to do because now we have a failing test. Let's say that we call this tests um reverts if caller is not admin. And to be able to revert what you basically do is really easy in the test.

You call should fail with and you add the error there. Uh in this case because it's increment it should be let me check. Yeah not incrementor or admin. Cool. And now if we run the tests. And I think my issue is that I keep calling owner when it has to be admin.

>> Okay, this this is actually my mistake. Cool. I up with the variable. That's it. There we go. And let me write it here. And let's try again. I haven't compiled what we have been um coding. So yeah. >> No, it's still I hope it works now. Cool. Uh, we forgot the previous test and it had the admin

there. So, yeah, that's it. Or that should be it. So, now we should have uh I think three tests and the three should be good. One is failing and it's expected. So, it uh should be marked as green. Cool. Now we have three tests. Awesome. Um, let's see what else we could write. Let's uh try to write a test where the admin sets up an incrementor. It's called unconstrained function incrementor can increment.

So we will set up an incrementor and um then the incrementtor will call increment. Let me copy the setup here just for simplicity. Actually, let me copy it fully. [snorts] Cool. We will create a second light account that is called incrementor and we'll check that if uh increment is called by the incrementor, this should revert.

While that is happening, we'll call called by the admin and the admin will call the function to add an increment. It reverted. Cool. And then add incrementor. And we add the incrementor. It cool for test pass. Um what this is

basically doing is uh creating the contract initializing it and then the admin is adding an increment and the incrementor is calling increment and now we can see that the counter value is one instead of zero. Uh like we could just to like be completely safe in our test. We can check we could check that our counter is zero before um so that we know actually let me do it here. Yeah, there we go. >> [snorts] >> So that should pass too. And I forgot to read it. Sorry.

[clears throat] Let's call the counter unmutable variable. And let's assign it again here. Do you know how to >> Ah, that's fine. Yeah, should be quick. Cool. Now for test pass. Um let's also

write on our test which other let me see what which other test we can check uh add incrementor remove incrementor let's um try with a test constraint where the where yeah another reverts if not owner calls remove incrementor. That's a really long name.

Let's add this one and then uh we'll go ahead and run our sandbox and deploy everything into our sandbox and deploy everything uh into DevNet 2. Uh by the way, this is if I'm not mistaken, this is all running on uh DevNet.5. Um it should be compatible with everything that is related to DevNet. But uh remember that if you use the I'm pretty sure that the default instructions in the Aztec website um don't tell you to actually use DevNet. Uh they only use like the installer from Aztec. So it will install the test net version. So you need to be like really explicit there. And when you

do a you need to send the version like basically uh 3.0.0 uh devet.5. So yeah, just a small reminder there. Cool. Uh for this function, let's call it not owner. And the not owner is going to be calling remove incrementor. And this should revert Uh sorry should fail with there we go and

it's not owner. Okay. There are multiple tests that we can like still write about this but I think like basically this is like enough. Yeah. >> So I'm trying to wrap my head around what's public and what's private. the if we remove the getter the get counter getter would that become private? >> Oh no no no no uh it's just a matter let me show you >> it's just a matter of the type of variable that you use >> like if you check here um you have the counter that is a public mutable okay >> and then in here the incrementors are private set so it's the type of data that divides like public and private space. So if we made counter a private mutable y then could we still access it

with a public? >> That's a good question. Um okay so in that case what you would do is let's say that um only the people in this room know about this contract. Okay. And then what we do is we create a note that is called counter note that tracks this number. The bad thing about that is that I would need to share this note with everyone here so that you would be able to access it. If you want to do this with people that are like completely outside this room, they would need to like contact me or I should like build a website that kind of shares the pre-image of the note or whatever uh for you to actually find it. And it will be really difficult because um notes are append only let's say they are not like mutable itself. So if we create one note

and I share with everyone here and then you call increment and you increment that note you are nullifying the previous node. So you would need to share the new note with everyone here like one after the other. That would be like insanely costly in terms of uh uh like Yeah. Um >> okay. >> Storage. Yeah. >> Okay. Thanks. >> So yeah, that's um that's a really good question. Like basically the thing that AE has is that contract design works really really differently than doing it in solidity and you have to like it took us um quite some time like quite a couple of weeks to actually

like wrap our hands around it. Um because it's completely different a completely different like programming paradigm. Um because it's not like at at first like you basically go into Aztec and the first thing that you like kind of think is that I can create a private note and everyone can just like I don't know like access and increment that value and no one knows the value and that can happen like because things are executed in my computer my computer needs to know like all of the values. So I cannot have something that no one knows but I use. So for example um if you were doing a contract that is like much more complex than this. Let's say

that you are doing unis swap 2 or something like that. So like a dex um like the simplest dex that you can imagine. A dex is basically like a pool that holds two different tokens and the ratio between token A and token B determines the price. So the interesting part about this is that if you want to build a DEX on Aztec at least you will need to have the balances be public because if not how can you like how how would you know how much you will get by executing the transaction. So every time you are developing an app for Aztec, you need to think like you basically start thinking okay let's start with everything private all of the variables everything and then things start coming to your head and you're

like okay if I do this private how the will this person access like this piece of data like they literally need to execute this in their computer and they need to do like math equations and you need to know the values of everything if not like you cannot do it. Um so yeah uh at least like how I interpret it is that we start with everything private and then slowly we start only putting public the things that 100% need to be public like there is no other way to execute it and usually things that need to be public I understand them as things that anyone should be able to read like because you could think about it and be like oh

let's put it in private but if someone wants it, we share it. And it's like that's public. Like just do it publicly and that's it. That will be like much more simpler for users because yeah, you could make it so that everything is private and then you go inside the website and the website shares stuff with you. But what are you like winning by that, you know? Um, so yeah, private and public like execution and interactions are like massive there. It's it's really important. And yeah and you can see it here like basically the the counter is public and the good thing about that is that there is only one value for counter. So if we were sharing a note like all of us together let's say

that we wanted to do this with the counter node that we all share between each other and we all want to increment that counter and he sends the transaction and I send the transaction. one transaction will come first and the first transaction that comes will nullify the node that was in um that was in storage and my transaction will fail because that I will try to nullify a note that does not exist anymore so yeah cool and um let's see a tech we'll start the testing environment the sandbox Let's wait for it to start.

Cool. And in another terminal, we'll do yarn deploy counter, I think. Let's check it here. Cool. uh yard deploy counter sandbox sandbox and then it was wait I forgot how it was deploy >> deployer secret okay I forgot cool uh what we will be doing now is deploying our counter into sandbox using like this secret please don't copy it but uh yeah you can use any secret of

course like if you are doing something that is more productive. Uh you would like save it in an environment or whatever. But yeah, let's see if it works. Cool. So, uh we have the contract address here for the counter and then let's see if we can also find it here. I think it will be a little bit annoying with all of the This is the fee payment contract. Yeah, here. So you can see like in our local environment we successfully like deployed our counter and if we had some scripts some JS files that want to interact with this we like we should be able to do like any end to end tests. Um

I won't go into end to end tests here but they are like pretty simple. I'll show you only the test that comes uh with this which bas with the yeah with the repo. it deploys the counter and you just basically call counter methods and you have all of the methods that you can access. Um yeah, you check the admin, check that it's SQL, get the counter, check that it's zero when you start and then you call increment from the owner and afterwards it should be one. It's really simple.

And lastly, let's see if this works. Let me stop the sandbox. Cool. Let me just run the same as before. What's happening? There we go. But let's call the other one and deploy to DevNet. My computer going insane.

Cool. Devet. Cool. And this is not working. Um, basically this will use the same thing that uh Sh Yosh showed before. Um, oh, I think I have no internet actually. [laughter] Um, this is using the same thing that uh Shed before uh which is basically the sponsor of F FPC. um fuse or gas is a really interesting thing in Aztec and um it's still not completely polished let's say um but for now for DevNet for every like developer use case you have what they call a

sponsor FPC which basically like receives any transaction and anything that comes in they just pay for the transaction that's it in the future the idea would be that you will be able to pay for fees in any token And there will be like different uh FPCs basically like let's say that uh someone runs an FPC that accepts USDC as payment or whatever. Um and this is really interesting. Cool. We send the transaction and let's see if it actually deploys.

Yeah, you can see that here it's registering the contract for the sponsored FPC and the account that we are deploying with here. How long does a transaction take in a stick? >> 30 seconds. >> 30 seconds. Let's see if it's accurate. >> It depends. >> It depends on the state of the network. >> Cool.

Now it deployed and you can access. Let's see what I can do with that. Why is it so grainy? And we go into Azexcan. There is like um just for you to know Azexan has its DevNet. Aastexcan.xyc instance that allows you to see everything that is happening on uh DevNet. Yep. Here is the call. there's not much to see as deployments are private. So yeah, in the future the idea would be that you would be able to use um the contract type which is the class ID like this is published and if you um have a mapping from this class ID to the code of the

contract, you are able to publish this and to show this. But if you don't publish the code, there is no way for you to see it actually. So yeah, that is basically it. Anyone has any specific questions or whatever that you would like to discuss? We have 10 more minutes. 14 more minutes. >> Cool. Yeah. uh I mean if you you mean like for example the variables that we are publishing or or a bite code >> if you don't have the the code for the

contract no like that's uh you won't see it like same as solidity right like you would need to basically like decode stuff and kind of >> yes I know I mean let's imagine that I have the code of the contract. When I check it, I will I will check the public variables, but I could not uh get the the private. Is that right? >> Yeah, correct. Like you will see like garbage there. Yeah. >> Okay. Okay. Awesome. >> Yeah. Yeah. Oh, you would only be able to access like the public state there. >> So, yeah. >> Yeah. >> Is there a concept of like verifying the contract? Uh there >> verifying the contract like on the on the scan >> on the explorer?

>> Oh, yeah. Yeah. Yeah. So like right now I think it's not uh something that is like completely public or easy to do but the guys at Aztec Aztec scan are working on that like they have this part here that is called standard contract type and some of the contracts are registered like for example uh we have our own token standard and if you deploy that it'll show you like the data for the token standard and a link to our repository but they just need to expand that registry but yeah uh in the future you will be able to verify your contracts in the scans. for sure.

>> Yep. >> Like your own note. Someone send you a note, can you decrypt it and see what it actually is? >> Um, >> yeah. Yeah, of course. Like there are basically like two ways to find your notes. Um, the most naive way would be basically like to brute force. like you can literally go and try to brute force decrypt every note in existent for Aztec. Um I mean if you don't know and you want to check if someone sent you a specific note you would need to register the contract. Oh actually like let me give you a little bit more context.

Notes are siloed into each contract like there is no like just a notes registry that is there and all of the nodes are like swimming around. Um each node is like tied to a particular contract. So you register that contract and then you read the notes for that contract. >> But is there like a snippet of code where if we added someone as an increment here they could what does it look like? >> Oh the pixie grabs it and decrypts it immediately like they know how to do it like yeah uh in the case for example let's say that I do a token transfer. Um and again like I'm repeating things from the previous workshop but I'll repeat it anyways. I think it's fun. Um there are multiple ways for you to know that I

send you money. One would be for me to show to share everything offchain. Like basically I send you the money. I publish the nullifier for my notes and then I show you a a QR code that you can scan and it adds them to your pixie. This is like locally share like everything offchain whatever. Um then you can try to brute force like you basically add the contract try to brute force any note in existent for existence for that particular contract and if you like get a hit fantastic you know the note and the third one is no discovery. Um basically Aztec noticed that it's literally or kind of impossible for people to really try to decrypt all of the notes in the system. That would be insane and it would take a lot of time.

uh I don't know if it happened to you for example if you use Monero or Ccash and you try to start uh your account from like block zero it would take like hours for you to actually like sync the whole chain. So they came up with a like scheme that is really interesting that is called note sharing or note tagging. And [snorts] what that basically do does is that it indexes the note based on the sender and the receiver address in a way that the the RPC cannot actually know that value. So if we know each other, we can privately like offchain share that I sent you money. Like let's say that you send me money. I add you as a as a sender on my wallet and it will pick up

all of the transactions that are indexed for our payer. That is you as a sender and me as a receiver and that will be like really quick. >> Wouldn't they have to have the contract to be able to understand the structure? >> Oh yeah. Yeah. They add the contract for sure. Yeah. They add the like basically they they add the artifact for the contract and they have to register in their pixie. >> Yep. For sure. Cool. Anyone else? Awesome. Thank you everyone. If you want, we'll be [applause] around.

If you see anyone with a t-shirt, feel free to talk to us. Thank you.