zkSync 🛠In-Memory Mode & local testing of zkSync Era
ETHGlobal·Wed, Oct 9, 2024, 12:00 AM
Join us for a zkSync workshop! From November 17-19 2023, ETHGlobal welcomed developers from around the globe to take part in shaping the future of Ethereum at ETHGlobal Istanbul. Over $600,000 USD in prizes were given away at the prestige Istanbul Congress Center... thanks for an amazing weekend hackers! ----------------- Follow us: https://x.com/ETHGlobal?s=20 Check us out: https://ethglobal.com/ Email us at: hello@ethglobal.com
Transcript
[Music] hi everybody my name is Nick I am here from uh ZK sync and I'm going to be talking about the inmemory node for uh testing and local debugging whenever you're deploying your apps to uh ZK sync we'll go through uh quickly an agenda today of you know what it is but some background about myself I've been a software engineer for 12 plus years uh recently joined the matter Labs company came from SpaceX and uh yeah let's get into it so uh before I go into era test node I do want to cover what it is uh we could be using for testing today sorry if it's like a dark background a little difficult to see I'll I'll just read it out loud sometimes um the first option is we have a public test net right it has uh gly as the L1 and you know the the downside of of this test net is it's difficult to find funds from a faucet uh the second setup is having a full uh local dockerized network using three Docker containers and we have that available in this GitHub repo that I have listed below at local dash setup so uh it is uh just a local network from a layer two down to the layer one with a postest database uh takes a few minutes to get set up and you know these are two great resources to get tested uh your smart contract locally but let's talk talk about erit test node so we wanted to build something that improves a lot of the problems and frustrations that people were having whenever they were developing for ZK sync so one it needed to start up fast so for era test node it starts up in less than half a second the ability to Fork the Upstream uh main net and test net networks at any given height we want to be able to replay transactions from these networks we want to give you these pre configured Rich accounts so that if you were to start it up locally you don't have to worry about finding a faucet somewhere so that you could you know start just deploying and using your smart contracts uh support for getting the console logs for hard hat or Foundry um the call stack should just be easily available to you for debugging purposes and if you're having any issues with uh gas utilization or just questions about why is it so expensive for your smart contract we wanted to make it really easy to dig into that those gas details so what is it uh look like to run the era test node so first and foremost it's a binary uh the one way you can uh run it is download the binary from our GitHub release and the command would just be era test node run and it'll be up and running on Port 811 the second way is you could actually just use npx so this npm uh uh tool we have a ZK sync CLI tool where you can just say Dev start and you don't have to download the the binary manually it will just take care of that for you and get it running finally the last way to do it is to have it embedded in your hard hat configuration so if you add this yarn package or this npm package of matter laabs hard hat ZK sync node uh then in your hard hat config you add the import statement that I have at the bottom of that exact package whenever you do things like uh you know npm hard hat test it will just run against that local node spin it up for you download it for you and uh stop it whenever you're done running your tests we'll go into some examples about that later but you know why did I give you that background uh and how do these three different approaches compare so just a quick High overview you have a comparison between the test net those Docker containers and finally the era test node so so running locally the testnet does not do that it is not running on the public uh servers that we have and uh this could be a downside if you are running uh your tests in cicd sometimes you don't want to rely on a bad internet connection if you want to develop fully offline you're on an airplane you want to be able to develop everything locally uh Rich accounts so testnet right the downside is you have to find goly eth you have to find a faucet that you trust uh to get some you know tokens so you can actually use your smart contracts in terms of fast setup the testet is live you don't have to do anything it just works right now um however the downside for something like Docker is it takes five to 10 minutes sometimes to get running for the first time uh and then debugging you don't get debugging with any of the other approaches like you do with ear a test node so in terms of configuration for some of these the chain IDs are different 280 270 260 obviously the end points are different but the major difference is layer one ear test node does not have that layer one component it is just a layer two in memory node similar to like the hard hat network node or uh uh W or you know there Anvil is another example um and it it doesn't you know require uh or doesn't have that uh capability to communicate to an L1 at the moment so if you need to test that functionality uh go with one of the other options I've been talking about it a lot but let's go into a quick demo of how would we deploy a greeter contract um let's talk about what you would need to add to your hard hat config and really it's just a network with the URL pointed to Local Host Port 811 so let's take a look at that I have created a uh template project uh based off of Z ging CLI template or create sorry um and what I was talking about with the greeter contract is right here we have a string that we are setting in the Constructor and we have two methods where we get this greeting message and we set the greeting message so what we can do is go ahead and you know start up the era test node era test node run and there you go it's already running so what we can do is actually start using it and it will be here let me toggle presentation mode real quick that way you can see a little better all right so npm run deploy and for the network I'm going to say in memory node so you'll see the first thing it's saying is ites doesn't have a private key you need a wallet to be able to deploy but the nice thing about running the era test node is it spits out that information for you right at the beginning it tells you what the chain ID is it tells you what port it's running on and it tells you what those 10 rich wallets are that you could use locally so in the EnV file I'm just going to paste that in run it again and let me scroll down so you can see it so it deployed and you can see if I scroll up that here is a summary of the transaction that happened uh in the lower command line you will see that this is the contract addressed for the new greeter contract uh here were the Constructor arguments and in inmemory node you see this was the transaction it was successful you can see who initiated it uh who the payer was what you know gas was used what gas was refunded um what some of the events were and it will still keep running ready for the next command so let's get into that next command which is we have the ability to interact with this new deployed contract and what this script does is points to this uh greeter contract that we just deployed it gets the greeter message it sets the greeting message to uh hello I'm just going to say Dev connect and then gets it one last time so let's do instead of deploy interact and you'll see if I scroll up over here that there was a call there was a transaction and that's to set the message and then there's another call to get it one last time and and in this project we also have hard hat tests right so uh that whole workflow that I just showed you of deploying the contract setting it getting it um updating its value and it can all just be wrapped up into a single test and it will work now let's run this [Music] um sorry one second all right let's skip that for right now I don't know what the error is it looks like it's hitting an API rate limiting for an unknown reason that's probably because the internet connection for me is really not great down here but uh you can easily point to the hard hat node but you'll notice that it won't actually uh be outputting the content to the node that is running in this console and the reason is because whenever you are just doing hard hat tests it is using the hard hat Network um and this was that third example of how you could run it locally whenever you're running tests where we say Okay import this node and so whenever you do hard hat tests it will just start up a note in the background run against it and uh spin it down whenever you're done so it's great for CI and you don't really have to take care of uh or worry about too much so uh just as a small recap I showed you how to start this inmemory node deploy a contract you know use some rich accounts execute the contract and uh hopefully run some automated tests now I have shown you like just a basic node like a hard hat node but what we really wanted to do is make sure that you could actually debug some of your transactions and what do we need to support whenever we want to have that capability for developers uh the first two things are we want to show you the call Stacks and we want to show you the console logs so the whenever we're looking at a bunch of tests or debugging it's just console log everywhere it's console log for hard hat is console log for Foundry so uh let's look at showing that exact value so over here what we're going to do is update the greeter contract so when I say console log that is this console log that is the hard hat console and I have two new console log statements at the beginning of set greting so set greeting is called and then the value that was passed in I also added a check right underneath that says hey make sure that the greeting value that you're trying to set it to is not equal to the string test if it is you know go ahead and revert and say received a test value we don't want that so we're going to compile the cont contracts again and then we'll redeploy going to take the new address update the interact contract and this time when we interact let's take a look over here at the IR test node so as that ran if we look up right here in the transaction we can see the console logs are being spit out uh right inside of the transaction summary the call traces are here it says there are 20 of them but you don't see them uh we hide them by default but we can easily show them so while this node is running we've added a bunch of apis so that you can update the settings about it you can update the log levels you can update uh information about how much uh uh you show call information you want to see Etc so we're going to call config unor set show calls while the node is running and we're going to set it to all so let's do the interact script one more time and this time you'll see a lot more information all of the stack Trac is showing up here and you'll see it is indexed uh based off of the the tree index uh for the entire call stack so if you go in here you'll start seeing things like uh the the console log statements the two that are right here the two kak statements that you are using to compare that your string does not equal test Etc but you know you can't really necessarily read all of the information easily so we have another method to do that and if we scroll down a little bit set resolve hashes so what we're going to do if we run this one more time is you should notice that these values on the right uh are no longer just hashes we reach out to openchain API turn these values into human readable functions so that as you're going through the code and you look through you see oh whenever I called set greeting before that it did execute transaction set transaction origin get raw code hash all of these methods through the entire system are available to you so uh oh I need to show you what an error looks like so I had added that check that says hey the value shouldn't be uh test so what happens if we do set it to test can you easily tell what's going on and boom right here in bright red it already tells you look uh execution reverted received a test value um this is insanely useful whenever you are trying to debug a set of transactions inside of a batch it just highlights exactly what the problem is and you don't have to dig any further to to resolve the issue so in terms of console log call Stacks uh readable events and AI functions uh easily spotting errors in reverts that is just like first class citizen for the in memory node now the other nice thing about debugging is we want to be able to give you the ability to Fork main net Fork test net in a few seconds and also replay transactions so why would you want to replay a transaction well let's talk about about a scenario where a customer says Hey within our tests everything worked but ZK Sync has an issue when some transactions fail with an error message uh it's this is a long bunch of texts uh here's the contract address I tested it myself with the same result if you need anything uh please let us know and we we don't have access to their console we don't see what they're seeing we're just hope like hoping that they give us the information they need but we don't have to do that we know exactly what the transaction is so if we were to click on this and open it in the block Explorer we can see the first hash like yes it failed right but we can take this transaction hash and if we go back here we can actually use a new method called replay underscore TX replay the transaction uh against test net and we give it the hash of the transaction you'll notice that I already showed you show calls resolve hashes but I added a third one in here which is show gas details we they want to be able to see what was happening with the gas cost why is this thing using up so much gas or we thought that was the problem so uh we took a closer look and if we take this and make this as large as possible I'll stop the node so I run the command of replaying this exact uh transaction inside of here you'll see that there were two transactions in the batch so it gets each transaction so it's already forked uh test net by the way it it happened that fast um but what it's doing is it's taking those two transactions and it's replaying them uh one after another uh locally now uh it's also reaching out for every single one of these methods and getting the human readable uh function names that you see on the right so the uh events are also being translated so you can see the transfer events Etc right here you see the big bright red ER which is whenever they were calling set latest answer it threw a panic uh if we scroll up a little further there is a new section inside of the transaction summary there is a massive gas detail section and let's take a look at what it does well one it breaks down your your gas usage by transaction setup you'll see 25% of it went to transaction setup 64% went to account validation 9% was spent on op codes and if you break down the transaction setup even further you see 93% was spent on operator costs if you keep digging you know there are these overheads that we give you insight into so all of this gives you the right tools to be able to dig down even further and you can like literally just replay transactions that are giving you problems in test net and Main net and if you notice if I scroll all the way down this Noe is still running you can still execute transactions against this you can still use this because it's still running running and it's forked at that exact moment in time with the error that you just saw so if you want to dig in further you can it's still live now forking you don't just have to Fork you know uh at the latest block you can Fork at an exact block height right you can Fork uh test net you can Fork main net uh whatever you need to do for your local testing it should just work so I talked about forking Main neet test net forking at a specific height replaying transactions and digging deeper into some of those gas details to figure out like why something is so expensive in terms of cicd we wanted to make it easy so that this in memory node yes just a question yes yeah so uh in terms of integrating it with your cicd uh you know one way is just the GitHub action if you just need a node running that you want to point something to it it's this bottom part right here you just say you know dat but SL test node action at V1 and it's running it starts up on you know Port 811 you can give it the extra parameters if you always want it to Fork from a very specific Block in test net for your for your cicd whatever the case may be um the in terms of of like what's happening next and what do we want to see with a tool like this so One support for Foundry we want to have things like Forge Anvil rivet all these things just sort of work um in a very quick and fast environment that you can manipulates a lot of the underlying information um when it comes to uh the node itself uh you should be able to do what you need to to to test uh all of your smart contract from beginning to end the project itself was was open source from the beginning so if anyone wants to contribute to it we are encouraging you know the the growth of that open source uh contributions for the project um adding the ability to connect to a to an L1 like right now it's just an L2 on its own but there's nothing there's just you know some work involved that's necessary to get it connected to an L1 so that you can test the full beginning to end um support for more apis and then you know what else you you can think of so you could this is all written in Rust if you want to take this uh in memory node compile it down in wasm now it's JavaScript you could have an inmemory node running in your browser you could have theoretically an inmemory node that is right next to the transaction that fails in your block Explorer in ether scan and you say oh why did it fail and then it just replays it based off of forking at that exact place re uh tells you exactly all the details that you need to see and you can just you know investigate right in the browser so that's one idea that you could do uh yeah we have uh GitHub uh discussions um and I'll make sure to circulate the slides uh through eth Global but uh one other project that we did this week I know it's over but ZK Quest was something that you know we had published this week where uh we basically built a little you know Capture the Flag video game for this week and all of the development was against local ear uh in memory node um so it was a true battle test of like this thing works um we've used it for uh doing a bunch of experiments in the company where we can manipulate and change the underlying system contracts for the ZK sync era node um and validate that oh future changes are going to work we're changing the prover uh the underlying prover and we know it's going to work because it works for the inmemory node we know that that we can make some drastic changes uh to the underlying system before pushing it out uh for the public to use because we have this in memory node um so yeah any uh questions I know I kind of sped through it a little fast just because I'm nor yes no so we have to basically the way Foundry is built is around Anvil right um that is there like in memory node um the thing is you know it's built specifically you know just for evm similar to like the hard hat network node but what we want is because ZK Sync has the ZK evm uh which is evm compliance we actually need to uh tie it into this inmemory node that we've built we need to have a wrapper around it if we build this wrapper so that these tools think that it is Anvil then everything will just work from uh Forge to rivet um to other just like Foundry tools that they're building around having an anvil like sort of uh in memory node so uh same thing for hard hat right hard hat has a network node that it starts up whenever it runs tests if we just wrap the in memory node that we have uh to look like and have you know the interfaces uh of of that network node then it'll just be plug-and playay and it should just work um and so that's sort of the idea here hopefully that answers your question a little bit uh for ZK sync not at the moment that's something we're working on right now where uh yeah we're working on ZK Forge and then uh also slight it's it's evm compliance and then also the ZK EV underlying evm um yeah there are just differences that are not exactly uh supported from from Foundry they haven't had to um same like there's a lot of Foundry that we're working with them so that we can actually build a standard so that it can support different types of EVMS cool uh anything else I know I wanted to leave some time for questions so nope yay
Automatic transcript — names and jargon may be misspelled.