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

Loading player…

Optimism 🛠 Deploying to Optimism in 1 min and spending 29 mins looking at cool Solidity/EVM tricks

ETHGlobalSun, Oct 9, 2022, 12:00 AM

Join Kelvin Fichter of Optimism for a workshop titled, "Deploying to Optimism in 1 min and spending 29 mins looking at cool Solidity/EVM tricks." This workshop is part of ETHNewYork 2022, a three-day in person hackathon that will feature hackers, mentors, enthusiasts, sponsors and speakers who are all gathering in New York June 24-26, 2022 to talk about the future of money, finance, the web, ownership, the way software works and the way power is distributed. We're excited about a new frontier. ---------------------------------------------------- Follow us: https://twitter.com/ETHGlobal​ Check us out: https://ethglobal.co​m Email us at: hello@ethglobal.com

Transcript

[Applause] [Music] all right hello hello my name is kelvin um i work on optimism which if you don't know is a layer two on ethereum uh one of the cool ones and uh i'm gonna spend this is gonna be kind of a different talk than normal i'm gonna spend one minute showing you how to deploy to optimism and then 29 minutes looking at cool solidity slash ebm tricks this is not all of the evm tricks because there are so many of them but these are the cool ones so here we go all right so back last year optimism was really hard to deploy too it was really annoying you used to have used this thing called the ovm and you had to compile your contracts with a special ovm compiler and it was a whole mess so we rebuilt the thing and made it easy so you don't have to do that now it's just like deploying to any other network so i'm not going to actually deploy but i will show you how to do it um if you want to do it by re through remix if you really want to do this through remix i guess you can um use some tool just to get connected to the optimism network in your whatever your wallet is i i built this simple website called chain id.link that you can use to connect to a bunch of different networks so you can try that or chainlist.org blah blah right get connected to optimism change your network go there write a contract deploy that's it you don't have to do anything special it's just like deploying to ethereum or you pick a different network right easy um same deal with hard hat right all you do is you set up a hard hat project and you add optimism to your hard hat config and then you write a contract and you deploy with dash dash network optimism how do you add optimism to your hard hat config well here's the details of if you go to community.optimism.io it'll tell you how to do all of that it'll tell you how to what endpoints you can use these it it's just like adding any other network to your hard hat config it's really really really easy and if you go to dev docs where are we using your favorite tools there's a whole page on how to do this let me let me zoom in a little bit there he goes here's an example of how you can add it to your hard hat config just just add the url it's just like ethereum great fantastic okay same deal with truffle so that same page community.

optimism.io it just tells you how to add it to your truffle config it's really easy you just write a contract then deploy with dash network optimism just like you would do if you were deploying to polygon or if you're deploying a test net or whatever you just you just specify a new network and that's because we did a lot of work to make sure that it was fully what we call evm equivalent so it just runs geth under the hood and that's pretty cool same deal with brownie except you don't even have to add optimism to your config for brownie you just do dash dash network optimism and it's built into brownie which is very cool thank you brownie that's basically it that was longer than a minute so too bad all right now the fun part of the workshop evm tips and tricks um a lot of them you will not want to use in production but it's still fun all right so invalid let's start there number 10 we'll do a top 10. invalid invalid is a really cool opcode because it just reverts sort of it does not actually revert it triggers what we call a non-evm error non-revert evm error and what this means is that there's a class of errors that are not reverts that will cause your call to end and you will lose all of the available gas so an example of this is like a stack underflow let's say you try to pop a variable off the stack and there's nothing there you're going to get an error like this invalid is really cool because originally it people just started using this opcode they just picked it and they started using it and it wasn't defined as an eip it was kind of defined by social consensus and then in eip141 they set it aside as an official opcode called invalid and it is the most efficient way to burn all of the gas that's available in a given call frame so if you ever need to burn gas really quickly without actually doing work you just trigger this opcode and all of your gas will disappear immediately very efficient okay call code call code i want to see someone actually find a use for call code call code is basically really useless it's like the original version of delegate call except they got it wrong delegate call if you aren't familiar is really useful for proxies and what it does is it allows you to run the code of another contract but you still maintain the message sender and the value and all that stuff so it allows you it allows you to do a proxy call code was really useless because it would call the code of another contract but it would also change the message sender to be the new to be the the address of the contract doing the calling and so it never actually worked as a proxy i don't know if anyone actually uses call code but if you do tell me because i don't understand why you would use it so that's just out there the id yes why would you want to burn all the gas in the call that's a really interesting well optimism actually has one use case for this i don't know if it's the only use case but it is one where uh as a trick because message.value is really annoying and if you mark something as payable in solidity and then you want to call another function you want to pass along value that other function has to be marked payable too and so you know one example of why you might want to do this is that what optimism does is when you send a message from ethereum to optimism you have to pay for that message somehow and if you may you could make it payable but now app developers whenever they want to pay for a message have to make this whole chain of functions payable it just looks really weird and your users have to send value with a transaction which they're not used to doing and so the trick was well why don't we just burn a bunch of gas on l1 and we wanted to do this in a way that wouldn't actually put put a pressure on nodes because if you're actually doing work you know you're putting pressure on nodes um so we can just burn the gas really efficiently by just starting a new we do a call and then we just trigger the invalid op code and then all the gas is gone and it's sort of your how you pay for it is by burning gas if that makes sense all right the identity pre-compile um ethereum has a bunch of pre-compiles they're pretty cool uh the identity precompile is probably the weirdest one it's located at zero x zero zero zero blah blah four and all it does is it returns whatever you give it so if you give it some call data it's going to return that call data to you uh which sounds really useless and mostly is really useless but it is useful in certain cases if you want to gas golf for copying lots of memory at a certain threshold just doing straight up memory copying by taking a you know reading a a word of memory and then rewriting it gets to be expensive so it's easier to just do a call and insert all of this call data and then say i want it to be returned over here instead and it's cheaper so fun if you want a gas golf generally not that useful otherwise although it is also the source of various guest bugs so risky risky pre-compile okay solidity tricks these are kind of mixed evm and solidity tricks i feel like i'm going a bit fast here so i got to slow it down a little bit solidity exposes contract type information if you aren't aware of this you can use this type and then my contract and it gives you meta information so it gives you stuff like the name of the contract the creation code the runtime code and the interface id all these things are pretty useful the name maybe not so much although i could see use cases for it where let's say you want to do like a you know you want let's let's see what's a good example you could do something like i don't know what you do you know do some version string return some version string and it involves the name of the contract i don't know whatever the creation code though is really useful if you want to let's say make instances of a contract you can you know basically get access to the creation code you instead of running you know new con oops sorry new contract you can do like a low level create and there's sort of useful cases for why you might want to do that yes yes so oops sorry so i will actually talk about this a little bit later but in in ethereum when you create a contract you have two sort of types of code there's the creation code and the runtime code and what happens is or what happened was that's ethereum really wanted constructors and so what they decided for to be able to have constructors was you would run when you call the create op code you pass it some evm byte code and that evm byte code actually executes and whatever that evm byte code returns becomes the code of the contract that you have created so every contract has these two pieces the creation code and the runtime code and so the creation code runs when the contract is being created and it's expected to return the runtime code and this is of course really useful for constructors because it means that in the creation code you can do stuff like set a bunch of storage to initialize the contract and then once you're done you can return the code and the contract has done some work in the initialization step and then the interface id is really useful if you've ever used eip165 which is this you know supports interface thing where it'll you can query a function and the function will tell you what interfaces a certain contract supports you can just really simply return my you know type my contract dot interface id and that's a very easy way instead of having to do this like whole exor of different stuff it does this for you so very useful saves you a couple lines of code all right another one that not a lot of people know about but it's pretty cool solidity has function types so you can actually pass references of functions into other functions which allows you to do things like map right so this is one of the examples from the solidity docs where you can let's say you want to define a map function and it takes an array as the first parameter an array of of unions and it takes a function that takes a uint and returns a uint and what map is going to do here you can see it's going to create a results array and then it's going to loop over the input array and then you can see here it's applying the function to each input value to generate the outputs so this is pretty cool you can do this for a lot of you know a lot of interesting things we just want to save some code or save some lines of code by just passing functions around it can be a little finicky sometimes with with typings and like external and public don't always i don't know if this has been fixed in more recent versions of solidity but when this first came out it was a little finicky but should mostly work and a cool way to do do a little bit of this meta programming okay related to this solidity recently introduced this thing called abi encode call so if you have been writing solidity for a while you probably know yes yes i believe so yeah probably try it should work um yeah probably i mean if it doesn't work we'll find out um solidity okay so so people are probably familiar with the the classic uh abi encode and abi encode pact but solidity also has these cool things abi encode with signature and abi encode with selector which is really good for encoding function calls to other contracts and relatively recently the problem with these with encode with selector and encode with signature was that it wasn't type checked so you didn't actually know if you were properly encoding the call to the target contract until you started testing when as presumably you write tests that show you whether you're properly encoding this or not and and you get some sort of error when you run your tests but recently solidity introduced abi in code call where you pass you know mycontract.myfunction.

selector as the first parameter and you pass the params here and solidity will actually compile this type check it make sure that you are properly encoding your calls to the other contracts so this is a great way to make sure that you are encoding things correctly and save yourself the headache of having to write a bunch of tests and only finding out later that you mess something up cool and that takes advantage of course of the fact that you can pass in function references and well in this case i guess it's using the selector but whatever same idea all right this one is something that not a lot of people know you cannot deploy contracts that have byte codes starting with zero x ef 0 0 so or actually just 0x ef which implies 0x ef 0 0 but really it's just ux ef you're not allowed to do this try it try deploying a smart contract to ethereum where the byte code of the smart contract is 0x ef you can't do it and that's because of this thing called the ethereum object format which was starting to be introduced which is i'll talk about when it was introduced and the ethereum object format was initially trying to solve this problem of right now code and data in smart contracts are the same thing and this is how you get these weird things like you know technically the constructor is something that you can jump to and execute or technically the the hash at the end of the smart contract that's you know that solidity appends is code that you can jump to and you can run that code and you can use it to do cool uh you know capture the flag things or whatever puzzles but this actually creates problems in the evm because the evm has to look for every single every time you do a jump in the evm it has to figure out is this somewhere i'm legally allowed to jump to in your code and in order to do that you have to check is the thing that i'm jumping to a jump desk opcode and there's all these different things but basically we can eliminate a lot of this analysis by explicitly separating code and data but you can use this ethereum object format to do a lot more interesting things but of course we don't have this right now so how do we make sure that we will have it in the future we define some prefix and uh we block people from deploying contracts with that prefix and then in the future we'll allow people to deploy that con contracts with that prefix again with the assumption that the evm reads that prefix prefix and it says okay i know that if it starts with ef00 something this is an ethereum object format compatible smart contract and i know that it's going to have this the following format and i'll talk a little bit about what you can do with that how is this possible so what happened was in the london hard fork eip3541 it was announced that all contracts starting with 0xef would be blocked so of course people started deploying contracts that started with 0xef and uh and then what people did was they just looked on chain and they figured out well sure they deployed something that started with 0x ef but they didn't deploy anything that started with 0xef00 so we'll just pick that instead and you can't deploy any new ones so good enough it has the potential to be really cool so the the eof ethereum object format contracts would start with 0xef and then a version byte and that version byte tells the ef how it's supposed to parse the contract so one example here is it says let's say this is a version zero contract we'll say that there's a specific area here defined as the length of the to tell to tell you the length of the code then you have the code and then you have the length of the data and then you have the data or something like that and you can also use the same trick to deprecate opcodes so you can say let's say that nobody is allowed to deploy any more version zero contracts and in version one you are not allowed to deploy a contract that includes some op code that we don't want people using anymore because we hate it so we can we can do this really interesting stuff so not technically out yet but will be and will be really cool create two okay so this is uh this is something that you might already know uh create two is really useful if you don't know it you should be using it more often i'd create if you do know this great if you don't you should the original create op code as it says here generates addresses based on the creator address and the creator's nons but create two generates addresses based on the creator's address the contract code and the salt which means that they're basically deterministic and it doesn't depend what chain you're on you can deploy the same contract to every single chain which is really important especially in the multi-chain world you don't want a situation where two contracts can exist on different networks at the same address but have different code that can be damaging so use it generally more secure be a little careful whatever fine i'm going to skip that self-destruct is extremely sus but it has some cool stuff so self-destruct will delete a contract from the state try and it will transfer its balance to the beneficiary very cool uh very cool opcode a lot of people hate it and it's created a lot of bugs for people but whatever so a contract is susp or self-destruct as us because a contract that uses self-destruct can delete itself and then it can be recreated at the same address with completely different code which is kind of a cool way to do upgradeable smart contracts and i think some people have done this before it's not amazing i mean it's a little terrifying and uh there's definitely been situations where like block explorers don't work or you end up with like a like a parody situation where somebody just hits the kill button or whatever and you can't do anything about it so be very careful with that and then self-destruct is the only way to send eth to another address without triggering its code which can be very useful if let's say a contract has code in it that says when i receive eth revert immediately so if you want to forcibly send each to somebody and they can't do anything about it just use self-destruct and so remember that if you're auditing a contract make sure that you don't make assumptions about a contract not being able to receive eth because you will be able to receive eth no matter what and it's also the only way to permanently delete eth from the supply so yes of course you can send eth to a burn address like the zero address but it's still technically in the supply even though it's not accessible self-destruct is the only way if you self-destruct to yourself it's the only way to delete each from the supply permanently it just gets poof it's gone right all right we're yeah um self-destructors does it in the in the code for self-destruct it basically when you trigger the op code it will just increase the balance of the recipient and it won't actually trigger a call to the recipient so it's the only way to do it i'll have to i'll have to run through these because i'm actually getting quite tight here block hash is the ultimate oracle that nobody uses i wish more people did it's really really cool block hash obviously contains information about the entire ethereum blockchain it's a blockchain so the block hash contains information about the current block but it also contains the previous block hash which means you have a chain all the way back to block zero and using merkle patricia tri proofs you can access literally anything in the ethereum try not enough people do this it's really cool optimism has built a library for verifying merkle patricia try proof so you can do this on chain and you can read the storage of other accounts you can read event logs you can do whatever right everyone says like well contracts can't access event events no they totally can access events you just need to do a miracle try proof it's expensive but you can um and it's you know this is there's a lot of reasons why people didn't want people to access this stuff but anyway you can access it it's the ultimate oracle and no one uses it and i bet you could build a really sick hackathon project by just doing some unexpected thing by reading information from the ethereum state like you can literally just go and read the storage of any other contract you normally cannot do that block hash only goes back 256 blocks but you can always walk backwards by doing proofs so you say well the pre you know i'll prove about the current block and then i'll show you the contents of the previous block hash and i'll just repeat this because the previous block hash contains the block hash before that and you just go on this chain backwards and optimism really wants to build a block hash oracle so we would kind of have a chain of block hashes into eternity um so if you're interested in working on that as a hackathon project would be really cool kind of like a collaborative way for the entire theorem community to store every block hash so that we have access to it not just for the last 256 blocks but for every single block requires a lot of proofs but i'm sure as a community we can do it together and great so create oh this is number one this is probably the coolest one that people don't really think about when i talked earlier about contract creation i said that create executes a knit code this initialization code creation code and the code whatever that code returns becomes the contract code and the secret thing in here is that create executes the init code so create executes arbitrary evm byte code you can literally just pass whatever you want right i can i don't actually have to create a contract i can pass uh you know push one push one add as the instructions to you know there's the as the init code and what it's going to do is it's going to push one to the stack it's going to push one to the sac it's going to add the two and then it's going to have you know two the value two on the stack and then i don't know then it just stops and it doesn't do anything um but what you can do is you can execute arbitrary byte code you can do whatever you want you don't actually have to create a contract you can do you can do math or whatever you can uh you can basically have like user provided scripts that you run and you can you can kind of do whatever you want so you can make a simple scripting language where um let's see what did i yeah okay so here's an example right you could put let's say you want to do like a scripting language that doesn't actually change state you can do something like put all the inputs in call data run create with the user script as init code so it just runs these evm op codes then the user script reads the call data so it reads the inputs and then the user script is going to revert so it doesn't actually change anything and you read the result from the return data the other reason to revert here is that like i said this is still a contract contract creation and if you return then it actually goes and creates a contract with it with whatever's in the return data but the evm has a quirk where if you revert then then whatever you return instead of being created as a contract just gets put into the return data buffer so you can read it so optimism almost did this i was too scared to put it into production but i built it where we had this whole system of uh of these contracts that would drip eth to other contracts and originally i wrote this whole system where we would uh i wrote this whole system where we could provide these small evm bytecode scripts and the evm bytecode scripts would have to they would get you know created and they would have to do a bunch of work and they would have to either return or i guess revert with a zero or a one and if it was a one that meant that i could go ahead and do whatever i wanted to do if it was a zero that meant don't do this it didn't work revert whatever right so yeah you could i think there's a lot of fun stuff you can do with this and nobody really does it which means that i think you would look cool if you did it was that 29 minutes just about interesting okay this uh i was not expecting to get this far okay nope that was 29 minutes so no oh one bonus trick one bonus trick you can actually in solidity if you drop into assembly in the constructor you can use the return instruction in the constructor to return whatever you want and that returned by code becomes the code of the contract so if you wanted to i don't know return i don't know what you could return you can return whatever you want and that becomes the code of the constructor and so you can do some really deranged things like in the constructor read the code replace the code with other stuff to be able to use opcodes that solidity won't let you use and then return and you do just all this hacky stuff that you should never do in production great okay that's exactly 30 minutes perfect optimism is hiring as always optimism op labs or just come hack i'll be downstairs hacking on some deranged solidity so cool if you have more questions we can talk afterwards all right you

Automatic transcript — names and jargon may be misspelled.