New Ethereum talks, every Monday. The week's conference uploads by event, in your inbox.

Loading player…

Vyper vs Solidity | Gas optimizations by Patrick Collins

Ethereum DenverMon, Oct 9, 2023, 12:00 AM

We take a look at vyper and solidity and real-time compare the languages to see which ones are more gas efficient, and why.

Transcript

hello hello how we doing everybody what's going on uh so I have some QR codes here if anybody wants to follow along we're going to be doing some pretty cool stuff here today before I get started here who here is a solidity developer raise your hand if you're a saluted developer okay a whole bunch of slitty developers not as many as I would expect from a hackathon what about Viper Developers almost no oh okay almost one all right excellent perfect this is exactly what I wanted Okay cool so today we're going to be talking about viper versus solidity in terms of gas optimizations we're going to learn a lot and I have 19 minutes to do this talk and I'm normally used to having uh 16 hours or more so for those who do not know my name is Patrick Collins I'm a smart contract engineer auditor educator uh some of my QR codes up there um I absolutely love web3 I live breathe sleep eat Smart contracts I have done a video on this before so if you want to grab that QR code as well uh watch the video on this uh you can head over there to there too but today for this presentation we're going to just focus on a single subset why is Viper oftentimes more gas efficient than solidity and I know crazy right how could that be possible Patrick you've done so many videos teaching solidity why are you now telling me that sometimes Viper is better but I'm giving the disclaimer that I both I still like both Viper and salute I think they're both great languages however as developers we should constantly be asking is this the best tool for what I'm doing that's what we need to be asking all the time is this the best tool how many people here ask themselves that when they're writing their code is this the best tool I see four Liars here excellent excellent all right cool so I'm considering myself more of a referee I'm playing I'm sure you do I'm considering myself more of a referee here but we're gonna explore why this is the case and the architectural trade-offs that go into this and get you thinking is this the best tool can I make this better right because as web3 that's what we should be constantly thinking here is our combatants here are two contracts that we will be doing gas battle against each other they do essentially the same thing um because at the end of the day that's what high level languages do both slitty and Viper compile down to evm op codes they just do it in their own unique ways so what does this code actually do what do these two contracts actually do very basically they have a storage variable named store number they have an external function that allows you to set stored number and a view function to read store number I'm doing solidity first however the Viper code is nearly exactly identical the syntax looks very similar Viper insulity are not so different after all yay it's a great world but they're very different under the hood and we're going to see that in a second so spoiler alert here are the results of deploying this code oh my goodness solidity is much more gas expensive than Viper when it comes to deploying these contracts what how could that be all I do is solidity okay well cool that's just deploying the contracts Patrick what about running the contracts what about reading that view that storage variable what about setting that storage variable how's the gas look there well I hate to break the news to you Viper is more gas efficient there as well so for all of you who did not raise your hand and say ah is this the best tool uh do not ask the question is this the best tool I should be working with it's time to start asking right but let's go deeper into this why is this the case why are we all using solidity if Viper is more gas effective here what's going on let's go under the hood and then yes I have some when I first did this I did some comparisons some benchmarks to Huff fuel solidity annual and some other stuff as well that's why you see other stuff but we will not be talking about those today so let's explore this why does this bar graph exist how is this possible let's talk about gas costs when it comes to contract creation when we first deploy these two contracts what is going on under the hood to make it such that Viper is cheaper to do so and to do that let's do a quick refresher on evm op codes and a little refresher on assembly if you're in remix and you have your your solidity code here when you compile it there's this little button called bytecode if you click that you get this disgusting output that you see on the screen here which is a whole bunch of op codes for the AVM right it's what makes all of our smart contract stuff work all right who is with me so far raise your hand say I who is not with me say what everybody's with me all right great excellent all right cool and so these op codes uh look something like this right um uh they're just all these op codes and most high-level languages break down these op codes into three different sections and solidity actually uh does a great job of breaking them down with this this invalid op code you can't really see it on the screen here but they break up these three sections by having this invalid code be kind of this this separator so uh usually the first chunk of code in your compiled contract is your contract creation code it's the code that is that gets executed when you deploy your contract and then in the middle there is what we have the called the runtime code this is actually the contract right this is all the code that you wrote for the contract and then we have some metadata and some other stuff we're going to be ignoring that uh for this talk here we're just going to focus on those first top two so contract creation that first lump of code runtime code that second Lumber code content creation is what we're looking at right now and if we look at these two for contract creation across Viper and solidity for these smart contracts that we showed we see they're very different what's the first thing that you see here what's the first difference you see like right away what do you see anybody what size thank you excellent we see sliding has got a bunch more stuff right and as gas optimizers we go okay well if there's a bunch more stuff that probably means it's doing a bunch more stuff and to gas optimize we want it to do less stuff so is that what's going on so that is just doing more stuff what is this more stuff that it's doing and if we look at Viper here this binary this this uh this uh bytecode gets put out to these op codes here which is relatively simple when it comes to opcodes there's this really important op code in there called code copy which basically is just saying hey take all that runtime code that comes after this contract creation code and stick that on the blockchain for people to do stuff with and that's all the Viper contract contract creation code is doing it's saying take that runtime code slap down on the blockchain and then we're done so what is solidity doing a lot more stuff there's a lot more op codes there what is solidity doing well if we look at this bottom section ignore the top section first that looks really similar to the Viper stuff right there's that important code copy op code there's a whole bunch of push dupe other stuff but that bottom op code stuff is basically doing the same thing hey take that runtime code slap that onto the blockchain but what about this top stuff what's all this so this this lump of code right here this is all the stuff at the top what's it doing well if we look at this bottom section we're gonna we're gonna ignore that top section for now that's called the free memory pointer don't worry we'll get back to that but if we look at this bottom section there's a call Value dupe is zero jump if push dupe revert basically what's that do what that is doing is it's saying grab any value any eth that is sent with this deployed contract and check if it's zero if it is not zero revert so when we're deploying our contracts solidity is actually checking to make sure we didn't accidentally send a whole bunch of eth with this contract that'll be unrecoverable wow thanks salinity compiler looking out for us 10 year old meme hype let's go I thought we were comparing the same contracts here Piper what the heck slitty is looking out for us you're not you're not doing the work to make sure I'm safe to which slitty would respond well if you specified a Constructor and that at external deaf init thing that's a Constructor in Viper if you did that then we would add that checker for you right so there's a big big difference in the Checker and based off of whether or not you have a Constructor or not in Viper so we'll say okay fine Viper you get off on the technicality here but this is one of the main things one of the main differences between a lot of the languages in the evm world and they all do some type of uh uh check to make sure we don't shoot ourselves in the foot to make sure we don't send a ton of ethereum when we deploy our smart contract right they we also will do checks on data links we'll do checks on function selectors most of these high-level languages will do checks to make sure us developers don't do dumb things because you know we often okay cool so solidity doing some extra checks it looks like Viper has those checks as well it wasn't in that comparison so great let's keep going let's talk about the runtime code now because we saw where a bunch of those OP code differences has come from has come from those checks we still haven't talked about that weird free memory pointer thing that I told you to ignore that we will definitely be coming back to and we're not going to go too deep into the runtime code here because there's a lot to talk about so this is the Viper runtime code this is the solidity runtime code it's even more but we are going to focus on that free memory pointer because if you know and if you down the presentation you can see these on the different op codes here the solidity runtime code also has this free memory pointer stuff going on the Viper runtime code does not free memory pointer stuff no free memory pointer stuff solidity has it both in contract creation and in runtime Viper doesn't have it anywhere so what's going on we found another bunch of op codes that solidity is using that Viper is not and obviously if solidity is doing them it's spending gas who's with me so far say I who is totally lost say I'm totally lost okay I heard a couple mumbles they're a little shy about being internally lost that's okay uh you can come back to this video later um I have more links to um to the to the actual code feel free to ask questions there and if I do the rest of this presentation really quick we'll have time for questions but glad most of you with me okay great what is this thing and actually most limited contracts will start with exactly this push Ox 80 push Shox 40 m store what does this do why do we have this to understand this we need to learn about memory and the stack to learn what this free memory pointer is what these op codes are doing here so a quick refresher in the evm we have memory and we have stack right these two wonderful things and when we push stuff we push it onto the stack and it's literally like a stack of pancakes we push values up up up up up up you keep going higher and higher you push stuff on until you do some type of op code that pulls them off so M store is an OP code that will pull things off the stack and we'll stick it into memory and in this example the M store command says okay grab the thing that's at the top of the stack and that's going to be the location of memory we're going to stick stuff and then what's underneath that we're going to stick that into that location of memory so we sticked we took ox80 stuck that in ox40 because mstore says Hey top of the stack location bottom of the stack data great and we need both a stack and a memory in the evm right stack is restricted in size memory is much bigger there's a lot more memory there's we don't have unlimited stack memory can sometimes be easier to deal with and variables and this is really important variables are returned in memory not from the stack so anytime you return any variable in solidity or Viper you need to return it in memory but how do we know where we can put this new stuff in memory in this array right let's say we have memory with a bunch of stuff in it already if I put more stuff in memory am I going to override what's already in there how do we know well let's see how they approach it because this is where the gas optimization stuff comes from let's see how solidity does it first so solidity uh looks like this right so this is memory you can imagine this is kind of solidity's memory here um the 0 x 0 and 0x20 those slots of memory are usually reserved for like hashing stuff but the rest of it is basically free for us to use and when we do this push push and store we're sticking this Ox 80 in there and what this is doing um is it's telling solidity hey there is free memory at the ox 80 spot so this position in memory ox40 or fake index 2 is telling us where the next lump of free memory is right this is this Ox 40 is a special spot in memory in solidity and if you change right if you change where that spot's uh pointing to you're changing where solidity is telling um you that there's free memory right and we could look at an example like this so if you see you went 256 2 equals two sorry no terrible naming there um we need to create this two variable in memory somewhere and those are the op codes associated with doing that we do a push push M load M store we load where the free memory pointer says there's free memory and then we store our un2562 data where the free memory pointer says there's stuff to do right so if this is memory um those OP codes get run the data gets stuck in there because that's where the Freeman reporter says there's free memory and then we update the free memory pointer to say Hey Now free memory is one block down right makes sense say I if it makes sense excellent okay cool but that's a lot of work every time I do anything with memory I gotta well first off I gotta create a free memory pointer then every right to memory I gotta read where free memory is first and then every time I write to memory I gotta update that free memory pointer um and that's a lot of work so let's talk about how Viper approaches this vipers sees all this and my emoji got messed up there but Viper sees this and says that's a lot of work so Viper Says let's take a different approach same thing this is Viper's memory uh first you know Xerox zero and Xerox 20 are usually reserved for like hashing stuff but this is that exact same function that we saw in solidity but in Viper it has the same un2562 variable that it needs to store somewhere in memory and Viper approaches this a little bit differently Viper Says wait a minute I have exactly two variables that I'm going to need to store in memory I need to store that un256 2 variable and then I'm going to need to store my return value in memory as well so I have two things gonna need to store memory both of those are size 32 bytes 2 times 32 is 64. all I need to do is just have 64 bytes of memory and I'm good to go I'll just have the first thing go in the you know 0 to 32 and the second thing go into 32 to 64. and I don't need a free memory pointer and that's exactly what Viper does Viper Says I'm just going to statically allocate this memory instead so whenever Viper sees this you want 256 two variable it's just going to stick it in that ox40 every single time it knows that a uint 256 is 32 bytes that fits exactly in our Ox 40 slot and it knows that our return value is also going to be you know of type unit 256 so we'll stick that in the ox60 and every single time this function runs that's exactly where I'm going to put them I don't need a free memory pointer because I'm just going to say first variable Ox 40 second variable ox60 that's it and this is where the main gas optimization differences come from is the way that they're doing this memory allocation this memory management Viper is doing memory allocation statically whereas solidity is doing it dynamically solidity has this free memory pointer that says okay I'm always going to keep track of where the next lump of free stuff is and Viper Says I'm not going to do that I know that I'm always going to have four variables that I need to stick in memory and I'm just going to stick them in the exact same four slots every single time that way I don't ever have to worry about overriding so you might be thinking Viper's better I'm just going to use Viper Patrick you've convinced me congratulations but remember what I said at the beginning of the presentation is this tool the best for the job constantly be asking this and when you ask that you should be thinking what are the downsides of doing this why does solidity not do this what's the issue here so let's talk about some downsides Viper needs to know how big everything is to put it in memory right if it doesn't know how big it is it can't say okay uh un256 goes in spot zero if the un256 could be you went 2 million because it would override right it needs it needs to know exactly how big each one of these lumps of data is so what it can't do is actually stick dynamically size objects in memory so for example in solidity I can have a function like this a function get array public returns a unit 256 memory array return my array and that's a dynamic array that you went to that my array that it's returning could be any size solidity can do that Viper cannot do that Viper has what's called a bounded Dynamic arrays it can't have these true kind of uncapped size of dynamic arrays now the caveat to this is in practice this doesn't really bar Viper from being able to do anything solidity can do um so I put it to you all to see what you like best to encourage you to get out of your comfort zone a little bit try to see what you like better and keep this in mind when you're writing solidity code or you're writing your next lump of Viper code and again the code that I did to test all these this presentation QR code and then ipfs to this presentation as well hopefully you all enjoyed I am 17 seconds over now thank you so much uh for listening to my talk hopefully you learned something and uh best of luck at eat Denver thank you any questions or no I can't take questions okay oh like oh okay good foreign [Music]

Automatic transcript — names and jargon may be misspelled.