🏗 SolQL: a new way to access on-chain data - Shayan Shafiei
ETHGlobal·Sun, Oct 9, 2022, 12:00 AM
Join Shayan Shafiei of SolQL for a workshop titled " SolQL: a new way to access on-chain data". ETHGlobal hosted ETHMexico in Mexico City 🇲🇽 - our first IRL hackathon in LATAM in over four years. This year hackers had the chance to build the future of web3 with a chance to win over $150k+ in prizes from teams like WalletConnect, dYdX, AAVE Grants DAO, as well as experience talks from guest like Vitalik Buterin and Aya Miyaguchi! Thank you to the 580+ attendees from 27 countries who joined us for this unforgettable weekend of learning and hacking. For Mexico, 65% of hackers were from LATAM, and 46% were new to web3! Thank you for being a part of it! ❤️ After ETHMexico, we are heading straight into a full month of learning & building 🏗 Get ready for ETHOnline, our largest online event of the year! --------------------------------------------------- Follow us: https://twitter.com/ETHGlobal Check us out: https://ethglobal.com Email us at: hello@ethglobal.com
Transcript
[Applause] [Music] okay are we ready yes let's begin hello everyone my name is cheyenne i'm here to present seoul kyo before i do that formalities first a big thank you to the eth global team for obviously organizing this event and in particular this workshop onto business what is soul ql i'm going to say what it is in first it isn't a querying language so why is ql in the name the same reason java is in javascript it sounds cool i've told you what it isn't i'm going to show you what it is now um the most brief description would be it is a tool that mimics hardhat forking but is much quicker than hardhat forking i'll show you in a moment so here i've got a standard hard hat environment set up i've got a config file with the compiler version provider url forking standard setup if you if you have used hard hat this will be pretty familiar to you obviously so the smart contract i'm going to be testing today is called the query contract and in order for this to work we need to impose some restrictions on this query contract so one of those research restrictions is it has to have a function with this signature right here so it has to have a function named query which returns bytes memory so what is going on here basically what we're doing is we're taking the uni swap v2 factory contract on gurley test net and we are calling the all pairs function to get the eighth pair and then once we have the ice pair call the token zero function to get its first token now there is a specific reason why this example was chosen i'll explain that later but let's get into the comparison first so this uh benchmark repo is available on our website over here so you can try running the benchmark yourself see if you get some similar results um without further ado let's test soul ql first and then i'll test hot hat forking afterwards okay 7.9 seconds to do what to get 10 pair contracts from the uni swap v2 factory and then get the first token cool now 7 seconds does sound slow but we are offering this as an alternative to hardhat forking which gives us the following results wait a while okay 13 seconds now that doesn't seem like much of a difference even though it is almost a 2x gain but what ends up happening is as we increase the number of token addresses we are fetching uh the difference goes up quite quickly an example would be uh assuming that hard hat forking grows linearly with the number of tokens that we query whereas soul ql would grow logarithmically so much slower now before i explain how this performance game comes to life i'm gonna go through some caveats there's two main ones firstly we do not have hard hats console.log functionality yet although it's possible just will take a while and two we don't have the functionality to be able to pass constructor parameters to contracts yet again that can be implemented so here you'll notice that there is no constructor every piece of information that we need has been declared inside as a literal and that is because as of right now there is no support for being able to pass data into a constructor okay so this is what i was talking about earlier this is a graph representing on the x-axis we have the number of pair contracts we're querying and on the y-axis we have the number of milliseconds taken to get a result so as you can see sulcio the blue dots here stays pretty constant whereas hard hat grows pretty quickly so at this point right here at 2 000 pairs we're looking at about a 30 x gain in performance so that would be comparing around six seconds to 1 800 seconds so just to put things into perspective that's six seconds compared to 30 minutes which is a pretty big difference okay and at the very far end so here we have 9507 pairs at that point hard hat doesn't even work you will probably get a timeout or some other form of networking error so again for this demonstration just because it takes a while uh we're not going to demonstrate these data points right here because they would quite literally take the rest of the workshop to show but yes so that shows the speed gain that you would have from using sol qr now we do have examples you could follow along with so if i open here go to the docs obviously we have this warning here this is still in alpha so braking changes will happen but installation you go to a directory and you run this command right here it basically what it does is it clones the repo that we have set up and it installs the dependencies um i'll actually show you so right here if i do npx soul ql at 0.012 i'm going to call this test 2. so we get this test2 directory we've already run npm install so all of your dependencies are already installed so here what you have is the exact same smart contract i just showed you but we also have this main script which shows the usage of the soul ql api so basically the way this works is uh you import the soul qr class from the package obviously you instantiate an ethers provider with your provider link you would have a contract name this name would be this name right here so if i turn this into query 2 i'd also have to turn this right here into query 2 for this to work we are passing the chain id and we instantiate a source soul ql interface like so the reason you pass the chain id and your provider at the same time is because if you already know what chain id your provider has obviously we don't need to uh make an asynchronous call to figure out your chain id for you that would take an extra couple hundred milliseconds don't want that you also have to pass the hardhat runtime environment uh to this soul cure class reason being hardhat does quite a bit behind the scenes so rather than reinventing the wheel ourselves we just decided to rely on hard hat so that is quite essential over there and then to get the results all you have to do is run the following line this gives you a [Music] encoded string of bytes like this but we can obviously use the default api coder of ethers.
js to decode our result and have it in a nicer format reason this is address 100 is because over here this is what we are this address 100 array is what we are packing and returning as bytes memory so just to show you where was it if i go here that is by the way if you oh there you go that was quicker than before anyway so this is your uh encoded result basically which you use the ethers the js decoder to turn into this right here okay now with that out of the way where were my slides this is diving a bit into the nitty-gritty of how this thing works and why it gives us the performance gain it does give us so firstly i'll explain what seoul keol is doing and then i'll go through what hot hat is doing and why hard hat is slower than soul qr so basically what selkiel does is it takes your contract it uses the built-in hard hat compiler to compile it down to evm bytecode it then sends that byte code to the provider you give the soul qr api and it gives you the results back now there is one step in the middle here so the way this actually works is we also have these oracle contracts these are contracts that we deploy so these are actually depolared right now just ungurley but we are on the verge of deploying it to other chains as well so what is happening here is basically we call this function here when we want to simulate our smart contract which takes in the barcode of that smart contract and then deploys that contract using this assembly block here runs the query method on it and returns the result now in real life this would cost gas however we're not actually signing this transaction we're simulating it so if you've used call static before that's what we're doing here so we don't actually pay any gas for this so that's how that works now it would be more helpful to see all of this happen on the provider's dashboard so that you can see the type of json rpc requests you get for hard hat forking as opposed to soul care so i'm gonna run the hot hat forking script again and we don't need to wait for it to finish we can just come here don't steal my api keys thank you okay this is what hard hat does recall that smart contracts have a storage address on the global ethereum state so what hard hat does is it has a local evm instance but it doesn't obviously have access to the entire ethereum straight states because if it did it would be a full node but it isn't so what it does is to get the data it needs to do its computation it sends your provider eth get storage at requests so this parameter here is actually a smart contract address so if you look this up this could be the v2 factory or it could be a pair actually we can probably do that yep there we go so this address here is the uni swap v2 factory deployed on gurley so obviously we're getting data from the smart contract but we don't have the data locally so we send json rpc requests to our provider to get the data so basically the bottom line is when you're using hard hat you are sending a lot of json rpc requests and hard hat deliberately slows this down just so you don't get rate limited which is actually a fair call but then let's see the alternative approach of sole qr again we didn't really need for it to finish right this is all we get a single heath coal reason being we are passing the byte code of our smart contract that's what this mysterious looking string here is to the provider and the provider simulates deploying a smart contract using this bytecode using the oracle smart contract that we genuinely have applied deployed so this is the result that you then get so essentially the performance gain we get from using sol ql comes from making fewer json rpc requests we make exactly one request so obviously that has a lot less networking overhead which is what results and where is it this graph right here so as you increase the number of pairs that you're occurring obviously you get proportionately more eth get storage at json rpc requests whereas with sol ql if you increase uh the number of iterations you're doing in your loop you're really just changing the jump i byte code so the length of the byte code of the smart contract doesn't change that much as you increase the number of pairs so what ends up happening is firstly the data you have to send to the provider to be able to simulate this smart contract doesn't increase linearly as the number of reads from storage you do increases and secondly because the provider is doing all of the reads from state locally they can obviously do it much much quicker than the hard hat evm on your machine having to make a separate json rpc request each time it needs to read a contract's storage so yes that's what seoul qr does any questions no questions all right i believe we are early 10 minutes early cool well that's it for me thank you for listening
Automatic transcript — names and jargon may be misspelled.