Is It Still Immutable in the Context of CREATE2?

ETHCC 3 · March 2020 · 25:03

Alex Murashkin examines smart-contract immutability in the context of the EVM’s CREATE2 instruction.

Speakers

Topics

From ETHCC 3, hosted by Ethereum France.

Transcript

all right okay all right so let's start then hi everyone I'm Alex Moroccan a senior software engineer with quantum and I am presenting create - and its implications on imitability I'm presenting on behalf of Martinelli who created the content for presentation in this talk will describe what create 2 is and how it works we enumerate properties of create 2 will demonstrate how create two effects our understanding of immutability and discuss a few security related topics around grade - so Crito is a contract creation IBM up

code that was introduced by vitalik in EAP 1014 and included in the constantinople heart fork its behavior is similar to the regular contract creation of code create but contracts can be deployed to an address that does not depend on the blockchain state yeah if a sender wants to deploy a smart contract using the conventional way conventional create here's how it works the sender submits a contact creation transaction that includes init code in it code is basically an executable code

derived from the contracts constructor with parameters values being substituted in it this code is executed by the EVM and it results in the runtime byte code which is stored on chain as well as with side-effects of this contract Constructors execution an important point here is that the contact address is derived from the sender's address as well as the nonce the centers at the center addresses nonce which is incremented upon each transaction this basically means that no two contract

creation transactions may result in the same contract address create to work similarly in terms of how init code is handled in it code is also executed by the EVM it's the result in runtime byte code is also produced and stored but in this case contract address the longer depends on the nonce it depends on the Senators Elvis salt and init code and this leads to a few important properties the first one is that says that contracted address can be

predetermined before deployment which might be useful if you want some predictability and some other use cases and yeah of course to get the same address you have to keep the init code and the salt fixed yeah then another thing is if the contract is self destructed it can actually be redeployed again at the same address but it's worth noting that in it code sometimes can be written in such a way or like the constructor of contract can be written in such a way

that it produces a different runtime byte code upon multiple executions when this happens we end up with the following situation so a contract can be actually redeployed at the same address but end up having a different runtime byte code so what does it imply it actually implies that create two changes our understanding of immutability and we'll present two cases cow so imagine the first scenario when you want to interact with a contract you check its

source on either scan everything looks fine the contract took save then the control gets self destructed and an unsafe version of this contract gets redeployed at the same address and contact code no longer appears to be safe and if we look at this two example the deployment contract it was verified on either scan it says exact maturity is fine then note that this contract has destroy method at the very end it's basically called self-destruct operation on a contract which means that

somebody can destroy them you can destroy the contract you can assume that it's access protected it's not really relevant for this use case yeah the point is that this contact can be self destructed then yeah you keep interacting with the contract then you reload the page at some point and you see a different picture infra scan tells you that the content has been initialized using this really neat label at the top and it also explicitly says that the contract self-destructed but was later realized with a different red code and how how did the contacts heart got

changed here yeah imagine we have an evil factory that does the deployment initially it uses initially deploys the innocent version of the contract of course in each code here has to be the same in both cases we just assume that need code is somehow implicitly parameterized so that multiple executions can actually lead to produce production of different byte codes yeah initially deployment of innocent contract has exceeded someone at the user layer checks the source code

everything is fine then starts interaction with it deposit maybe some tokens daya tokens and the evil factory then destroys the contract using this method that we just saw oh it's another one then later it deploys the contract at this address again and the bytecode now is different and the evil contact can actually withdraw funds and we should note that because the innocent contract and evil contract share the same address any token balances that you're held by the innocent contract are now held by

the evil contract and all this token balances can be withdrawn and the takeaway here is Napoleon to ensure safe operation do not interact with contracts that are both deployed using create - and have a self-destruct capability the following scenario is a bit more convoluted so imagine we have a contract that is not deployed using create - and does not have my self-destruct option so what does it mean initially yeah at first glance it

may seem like a status quo before introduction of create to somebody you can think oh okay well that's that's fine this contract is safe however this will not always be the case so imagine a situation when one address has privileged access to this contract and upon a closer look you'll see that this address really just helps initialize the contract and then get self destroyed at the end and let's look at this case in a bit more detail so imagine we have this privileged contract which is basically which basically acts as an initializer or the sensitive type contract the

British contract was deployed using create - after the initialization of the dubbed contract it gets self-destructed this is when any user observes it on it'll scan and confirms that okay so this con work has been self destructed it's no longer of my interest I should stop pay attention to what's happening at privileged contract address however this might be a mistake as we see later the owner uses create - to revive this privilege contract basically just use the same white code but basically just redeploy the contract to this location

and then maybe this privilege contract has some vulnerability or maybe somebody stole the keys and can now perform half harmful operation on the sensitive that contract and we should know that the storage of the privileged contract was basically wiped out when it was revived actually was wiped out even earlier as stage when it was self destructed and now maybe this opens up additional attack vectors like for example somebody can claim ownership of revived privileged contract by unintentionally initializing

the takeaway here is that even if the contract stays the same and is not deployed using create to the introduction of the create to up code still exposed some attack vectors and when the target contract has a sensitive relationship with other contexts such as village taxes delegate call or anything we should also make sure that all these contracts are not both deployed with create tool and have a service type capability and the same holds for each of these contracts individually so basically one has to check recursively and confirm that everything is safe how do we protect ourselves from the

situation well one option is to use XG code hash which yeah basically retrieve the value at the beginning and then get it again and compare it however this will not work for this revived contract situation we described on the last slide because the bytecode is pretty much the same so the hash will be the same also so in this case storage becomes important and somebody has to check and confirm that the storage was not empty initialized and in general it's it's actually more reliable to rely on

historic data on transaction data between this contract and other contacts and if yes we basically have to check recursively and if no then we potentially yet if no then no vulnerable create to enabled exploits would be impossible in this case but the general this the cases generally very interesting because base fear an attack could could be basically a layer of 30 contracts and each of them may have sensitive relationships with each other and one of them may get redeployed at the end

and of course users should be warned in the UI when they are interaction with great - deployed contracts that's yeah so one option is considered story in XT called hash locally in the dab or maybe that's how it's asked and asset and then one users if it was changed and of course consider monitoring the historic data and detect such three deployments but all of the above is still only the preliminary check because you pretty much have to use recursion to determine the entire relationship tree and here check check all the contacts one

important aspect is that introduction of k2 actually changed our perception of imitability initially when we heard about ethereum it was restated widely that no there is no code imitability everything that gets deployed on chain is fixed cannot be changed and later later people found workarounds and started deploy and upgradable smart contracts in this case technically the byte code at a given point stays the same but you'll get to replace the

implementation contract and in a way you achieve some it ability on J what create two takes it one step further when you actually can have a different byte code now at the same address yeah in summary we presented create su and its properties we described some attack vectors and suggested defend defense mechanisms against them demonstrated how our understanding of small product imitability has evolved over time and I highly recommend checking out the authors medium page and github examples for create tool so it's

marginally it's the same same name for medium and github examples and there is the repo code create two snippets which will be useful here and just some thoughts on why we talked about create two now of course all these there were lots of discussions last year when it was first introduced and they were valuable articles by zero age Jason Carver and Rick mo and we basically yeah there was some other information or there already but as an auditing firm we basically found out that now developers

are starting to pick it up and they actually saw some projects that he was create to now and that's why we thought that it's another important basically moment in time so try to show and demonstrate which risks paid to me it goes yeah and you can check out some references as well yeah and yeah thanks a lot for joining us this presentation was a collaborative effort by Martinelli Jay Harrell and myself yeah thanks a lot

[Applause] well is it enough to say that I mean the only way how we can interact or get in I mean be impacted by a create - is that we use a contract yes which is created by create - which means that we somehow link it or we know it's part of the smart contract State or parameters yes and we somehow have to remember it in anyway is like if it's a parameter yes and if there is an ability to to change

it to change the address on the story as it's basically the same vector at a correct so what we were saying is that that creates - only adds the same amount of checks not when even though and there is no interface in a smart contract - to change the address of some dependency yeah I mean certainly some of these attack vectors might have existed in some form except that here it's more it's more like a perception right so you know that the contract can be redeployed with a different bytecode now and acknowledging has to kind of change the

implementation or grade the smart contract right so in this case you know this yeah that this attack is done in a slightly different way so we've been using Zeppelin Zeppelin OS upgradability pattern before and I always felt it's a cool idea but it's kind of a heck right like how we're doing it the proxy thing and stuff with create - it sounds like it's actually

the way how to do upgradability right maybe I'm and but I don't want to know push it but how do you propose like we should treat the smart contracts created with create - right now if I'm the if I'm the user I'm the app for example like should I take the like with the a bij so on should I take also a signature of of the of the smart contract or something like that so I'm sure that I'm interacting what I'm into what I wanted to interact with or what is what is your yeah so I think it's related to this slide

yeah so pretty much you may have to run a check on the hash of the white code of the other untime white code but at the same time he also need to check the transaction history for that address and see if there is any content creation transaction that's present but of course the first step I think the easiest step is just to look at the contact source and see if there is any way to do self destruct on it because generally it's not really a good sign if if this method exists in the first place so I think that's something that you can detect very easily and then like once yeah if

you're convinced that this service track there is for a good reason and then you can also check the which operation was used for deploying the contract and if it's create - then basically you have as a diagram that you can follow yeah that's pretty much it cool so I'm obviously in huge favor of using this to upgrade contracts it's just way more gas performant you're not paying that extra call for every anyways that's aside I was actually curious it I've not tried this either scan does it tell you if a contract is a result of a result a result the create - like does it have the hole does it tell you any contract the deployed its entire chain was it great - which makes you susceptible to

that second method you're talking about mm-hmm I mean mostly your question is whether you have this it shows you the dependencies yeah like if it create two contract which is now gone from the network created a contract which then is a thing because I mean I could always like you said destroy that create contract and then start them to create - all the way back does they tell you like the kind of the provenance all the way up yeah that I am not sure exactly I didn't check it but certainly it's something that will be interesting to check out yeah sure any more question guys all right thanks thanks a lot again

[Applause] you