DAPPCON 2018: Solidity 0.5.0 - Dr. Christian Reitwiessner (Ethereum Foundation)

DappCon 2018 · July 2018 · 20:27

Christian Reitwiessner, creator of the Solidity programming language and a developer at the Ethereum Foundation, walks through Solidity 0.5.0 at DappCon 2018. The talk covers the release's breaking changes and safety improvements, explaining how stricter compiler checks aim to catch common smart contract bugs before code reaches deployment on Ethereum.

Speakers

Topics

From DappCon 2018, hosted by Dappcon Berlin.

Transcript

some of you might have seen the top by Alex in the morning where he already hinted that I will talk about more details of solidity zero five zero zero [Music] five zero is a breaking release and it's I would say it's the first big breaking release we had for a solidity where we hopefully fix many of the weird at caged edge cases of solidity and our yeah design girls for solid solidity is zero five zero were we want to make it safer so we don't add too many features in

this braking release but we mostly restrict the ways in which the language can be used and we require the user the programmer to be much more explicit in in many more areas and we also try to remove dis ambiguities and weird behavior and yeah some runtime checks runtime checks are always yeah are good and bad so they are good because they prevent bad things from happening but they are also bad because they are usually more costly so they they need code to be run so the deployment cost is

higher but also the runtime cost is higher and they might even lead to yeah security incidents because a runtime checks are the only the only sensible thing you can do with a runtime check is to revert the transaction and this might lead to a contract getting stuck and in some cases that might even be worse than just going through with the error okay so yeah and because of that it's it's much it's even more important that all of the users of solidity are aware of these runtime checks that happen and in some situations okay so let's start with some code examples yeah this is a solidity contract written

for solidity 0 for 0 or 0 for whatever and it's a yeah very simple contract that just sets an owner and then allows you to withdraw money and this contract has at least one buck and this one buck also happened in the wild and the the problem is that I think the the previous talk also quickly touched on that the problem is that there is an initialized function which is called the constructor but it doesn't have a visibility specifier and because of that it's publicly visible by default and this means that anyone can reset the owner

even after deployment and we make this easier by forcing the user to explicitly specify the visibility of all functions and then you yeah you have to think about do I want to make this public or not and if you make it public it explained it's explicitly visible and yeah now you create this contract and you wrote the contract and at some point you decide yeah my contract is perhaps a weird name so let's let's change the name and then you might forget to also change the name of the constructor because the the constructor of a smart contract in solidity is identified by

having the same name as the contract and this also happened in the wild and because of that we change the constructor to be written with a special keyword here and now you can rename the contre the contract without change in the nature of the constructor and the third thing yeah so here at the bottom there is a function call for a function called withdrawn at least it might seem so in in reality it's just a call to the event here and to make them more visible we force users to use the omit keyword in front of every event call yeah then we yeah that's another example that also happened in

the wild Alex already talked about this example in the morning we have a very simple for loop here that just sums all the elements of of an array and if you take a closer look you might spot it back there and the the annoying thing about this bug is that all your unit tests might be perfectly fine because it only happens as soon as you supply an array that is longer than 256 elements if you do that this loop will be an infinite loop because yeah the the compiler infers the type for I here and this type depends only on the first value that is assigned to the type and the type of this first value is you a

date and if the length is longer than or its larger than 250 255 then this will result in an infinite loop so we disallow var so type inference is completely completely removed from the compiler you always explicitly have to specify the type of everything yeah and another thing is that solidity has the concept of data location which can be either memory storage or call data and this is quite confusing for I mean rightfully so quite confusing especially because the default values depend on

where you declare the variable and we decided to scrap all that and just require the data location to be specified explicitly for all reference types so you always have to specify memory for function parameters now and yeah the same for local variables then another park that is always named as some prominent example of bugs and solidity is the failure to initialize storage pointers so here we can see an example of that data P you might think that this is a temporary variable that is just created but it actually is a pointer to storage and if

you do not initialize it it's set to zero which yeah kind of reference is the length of this array which is not at all what it should be this has caused a warning earlier so people should already be aware of that but with zero five zero we forced this to be not possible at all anymore so and the thing that is not possible as all listed to declare P without assigning it from somewhere so this problem is fixed and but the fix yeah you can do it like this so you have to assign P from somewhere so you first have to create a new element in this

array by increasing its length and then you take the last element in that array assign it to your storage pointer and then you can set the elements this looks very weird so we do not plan so we have a fix for that but we it won't be part of 0 5 0 but hopefully of 0 5 1 or 2 or whatever and the fixed looks like that so storage arrays will have a member function called push new which creates a new so which creates a new element at the end of the array and returns a reference to that so if you assign it to a variable and you assign these members

of the variable you will assign you will yeah these values will be put in the last element of the array you can also directly use participants that push new dot name equals something good then yeah another thing that was or yes something that was inherited from JavaScript and was quite annoying for some time Alex also talked about that shortly is the function scoping of variables and especially the variable hoisting this code is valid solidity code so a function declare sorry a variable

declared anywhere inside a function is visible in the whole function and from the start of the function so assigning I assigning 3 to I works here because it's declared somewhere here yeah so we decided to just take I mean solidity is a curly braces language so we just decided to use the scoping rules from C 99 or C++ and this is basically block scoped variables with the single exception that if you declare variable in this initializer part of a for loop it is only visible inside the for loop and not outside so this is probably the

usual rules you would expect from a curly braces language this is now this is valid solidity is 0 5 0 because the eye that is declared here is not visible outside of the for loop so you can declare another independent variable I for the second for loop in 0 for 0 this would at least cause a warning or even error I think another good thing about that is so in in 0 for 0 you would have either declared I only once and use it for both loops or the second option would be to just declare a different

variable for the second loop but if you ticular different variable for the second loop this takes another stack slot and you might run into the yeah stick to deep error and we implemented the block scope variables in a way that the stacks love is actually freed at the point where the variable runs out of scope so this might save you so the or this this might allow you to increase your yeah kind of stack size or number of local variables available to your function okay then I have some more changes without examples the push new I showed to you earlier has an equivalent for

removing the last element from the a array that is called pop and probably in zero six zero we might even disallow assignment to the length property of an array altogether because that causes problems with unpredictable gas costs then yeah two other features are access to the a bi encoder and decoder this is probably quite useful for proxy contracts or just yeah passing data around in smart contracts yeah deep so the Inc code there are there's a whole

family of encode functions because we have yeah at least the the proper ABI encoding and the packed ABI encoding and then there are two more encoding functions that also take a functional signature signature so you can take the byte array and directly pass it on to a a call function and the decode function is is written in a way where you pass a tuple of type names here so that this might look a little weird on first side but I hope that it's quite practical to use yeah then another feature that was often

requested or enums and structs and interfaces so I think this will be quite useful to define yeah more more readable interfaces and yeah make interface is actually useful I hope then we still have some yeah minor save changes so the actually the the change lock that we currently have is three pages long so I can't explain every single feature but I hope all of them will be useful yeah call had some very very weird edge cases and if you don't know all of them that it's kind of not predictable what it will do so we try to remove all that and

change calls so that it only takes a single bytes parameter and just uses that as the call payload and you can then use the ABI encode functions to generate this this payload ya tuple assignments had some so in zero for zero or in zero for it was possible to to assign tuples to variables without specifying all the components so that the last component was some kind of catch-all thing so you could take a function that returns five elements and then assign that to only two variables

and the compiler wouldn't complain now the number of components have to match exactly yeah interface functions have to be external this is quite quite an easy change because interfaces are meant as external interfaces and not interfaces to be inherited from and yeah this this conversion thing is also an interesting change it was prompted by some competition some world that says yeah here look at the solidity code guess what it does and the problem here is that if you have so bytes one is a kind of byte array with eight bits and U and

eight is an integer of eight bits and apart from the allowed operators the only difference with them is the alignment integers are always right aligned so low-order aligned and by trains are always left aligned so right padded with zeros and of course you can I mean it's kind of logical that you can't convert between those but it gets interesting when you yeah and also the the the yeah the expected value is obvious I hope and it gets interesting if you convert between such byte arrays intentions of different sizes so for example you have a un 16 and you are sorry au into 8 it's an 8 bit editor and

convert it to a bytes - so a 2 byte byte array another question is on which side does it pad so where how does the shifting work and to make to make it clear how the shifting works we basically disallowed these conversions when the sizes are different and the reason is that so if you want to convert you into 8 2 bytes - now you can either go through you in 16 which Pat's on the left or you can go through so convert a given date to a bytes one and then her bytes - and that pads on the

right ok good I mean I I think it's at least a little bit clearer I'm not sure if it's all clear but I think it improves the situation at least now um yeah so another change right shift unsigned integers actually shift so this was a buck I would say because we implemented right shift on signed editors by scientific which is wrong I think nobody actually used it so it's not too bad and yeah another change is non pure constant state variable so this allowed the previous talk also spent some time on constants and the reason

why they are disallowed is because constants are not actually constants but more like macros so the value of the constant is put in every place where the constant is used and now we force these values to be pure which means they do not depend on anything and this allows us to make them actual compile time constants and put the value there this is not what we do already but at least we can do that change without changing semantics and then for major safety things view and pure functions when you call view and view part of view and pure functions in zero-five-zero it actually uses the static call up code this causes

some problems on test nets because that e call is only available starting from Byzantium and if you run a local test net it usually defaults to the frontier EVM and then people get reverted transactions and don't know where that comes from so this is usually call set your set your test nets to Byzantium and yeah similar change you have to be aware of is that the ABI decoder now reverts if the call data is too short so if you expect a UN date if you expect a you end parameter but you don't give any data then in zero for zero it would have just used zero now it reverts so this is all something you have to take care

especially when you write proxy contracts and and one very or one special case is that most people do not know that the ABI specification says that byte arrays have to be padded to multiples of 32 bytes and this might cause a problem here so even if you only have three bytes of value you still have to add enough zeros so that it's better to 32 bytes you actually under sure it might be that we don't revert in these cases but yeah better be aware of that then in line assembly we will enforce strict mode which means you we do not

allow for example jumps anymore so jumps and labels are gone and the reason behind that is that we want to make the transition to you'll as an intermediate language and you will does not have jumps because we want to target different virtual different backends and jumps are not always possible there so for example in webassembly it's very hard to make yet jumps to labels and when we know that there's no way to generate such code not even with inline assembly then we're free to compile the web assembly and one tag last thing the the continued operation in a do-while loop

had a bug because it directly jumped to the next loop iteration without checking the condition this is something that was only noticed I think one and a half years after its implementation which kind of also hints that nobody used that so it's fine to do that breaking change yeah so