A Complete Guide on Understanding and Implementing Upgradable Smart Contracts in Solidity using Libraries Versioning(Pseudo-Versioning) Smart Contracts Immutability is a feature that makes the Blockchain great. But like everything in this world, it also does have some cons. This article focuses on in today’s Blockchain platforms. We will mainly talk about Ethereum in this article, which is the most widely used smart contract platform today. Reusability and Upgradeability of Smart Contracts But first Go make a cup of coffee☕ first, it’s going to be a long one. We will start by seeing what are the reasons behind these restrictions/inabilities of current smart contract platforms. Then we will explore workarounds to model the Upgradeability(versioning) behavior(I call it ) which we enjoy today in almost all of the centralized platforms. Pseudo-Versioning P.S. . If you are really new to EVM(or want to learn about EVM in depth), then consider going through the below article _An Ultimate, In-depth Explanation of What EVM is and How EVM Works._hackernoon.com Getting Deep Into EVM: How Ethereum Works Backstage Overview Solidity(broadly speaking, EVM) has still a long way to go in terms of programmer productivity and language expressiveness. If you have worked with Ethereum, then by now you have probably realized that Solidity is a limited language. Especially, when you come from the lands of Swift and Javascript, developing in is definitely a step back in terms of what the language allows the programmer to do and the expressiveness of the language. Solidity This can sometimes, piss you off. Even the Panda got pissed off But Why it is Limited? Solidity, and in general languages that compile to bytecode intended to be executed in the EVM(which is a sandboxed), are limited because: When executed, your code will run on of the network. Once a node receives a new block, it will . In Ethereum this also means verifying that all the computations that happened on that block were performed correctly and the new state of contracts is correct. every node verify its integrity This causes that, even though the EVM is Turing-complete, heavy computations are (or directly not allowed by the current gas limit) because every node will need to perform it, therefore slowing the network. expensive A standard library hasn’t really been developed yet. Arrays and strings are especially painful, I have personally had to implement my own in order to do basic stuff, that we take for granted otherwise. string manipulation library You cannot get data from the outside world (out of the EVM) unless it gets in via a transaction (Oracle) and once a contract is deployed it is not upgradable (you can plan for migrations or pure storage contracts, though). Some of this limitations are needed for the existence of the Ethereum computing platform (you will never be able to store a backup of your Google Photos and perform image recognition purely on-chain, and that is just fine). Other limitations are here just because it is a really young technology (though evolving blazingly fast) and it will keep improving over time. Ok. But how the F**k do I solve this problem? While working on a project, which needed changes in the contracts in future, I came across “library”. This is a feature of Solidity which helps us to solve(indirectly) this problem. Before going into the Upgradable contract implementation, let’s see what is it and it’s limitations. What are libraries and Why do we Need them? In Solidity, a library is a different type of contract, that doesn’t have any storage and cannot hold ether. Sometimes it is helpful to think of a library as a in the EVM, a piece of code that can be called from any contract without the need to deploy it again. like: singleton This solves some big problems This has the obvious benefit of substantial amounts of , because the same code doesn’t have to be deployed over and over, and different contracts can just rely on the same already deployed library. : Deployment gas costs saving gas This is obvious from the above point. Code repetition in the blockchain: Earlier bug fixes and updates need to be deployed independently on each project (or, even worse, ). Now, it’s solved. Code Updates: Ethereum has to hard fork to fix a contract’s problems Libraries do sound awesome, right? Unfortunately, they also have some limitations. Below are : some important things to know about libraries Libraries . don’t have storage capabilities Libraries . can manipulate the storage of other contracts Libraries . cannot have payable functions Libraries . cannot have a fallback function Libraries . don’t have an event log Libraries . can be used to fire event logs for the contract which uses it Libraries . aren’t allowed to inherit Even though libraries cannot directly inherit, . they can be linked with other libraries and use them in the same way a contract would, but with the natural limitations of libraries These points can sound confusing at first. Don’t Panic. Here is a great resource to get your head around libraries. _A comprehensive review on how to develop more modular, reusable and elegant smart contract systems on top of the…_medium.com Library Driven Development in Solidity But for now, we will only cover the parts which we need to understand in order to understand/implement upgradable contracts. How does a Library work? A library is a type of contract that and ( ). A library is defined with the keyword library ( ) in the same way a contract is defined ( ). doesn’t allow payable functions cannot have a fallback function these limitations are enforced at compile time, therefore making it impossible for a library to hold funds library L{} contract C{} Calling a function of a library will use a special instruction ( ), that will cause the calling context to be passed to the library as if it was code running in the contract itself. I really like this angle from the Solidity documentation, DELEGATECALL “Libraries can be seen as implicit base contracts of the contracts that use them” In the above snippet, when function of contract C is called, the . This appears to be the same for all properties: , , , and . ( related to this indicates otherwise, but after doing some it looks like context is maintained). a() address of the contract will be returned and not the library's msg msg.sender msg.value msg.sig msg.data msg.gas Solidity documentation testing msg One thing we can notice here is that it is not clear how class C and library L are linked. So, let’s see that. How are libraries linked? Different from explicit base contract inheritance, ( ) in a contract that depends on a library, it is not that clear how a contract gets linked with a library. In the above case, contract C uses library L in its function , but there is no mention of what address of the library to use, and L won't get compiled inside C's bytecode. contract C is B {} a() . When contract C is compiled, it leaves a placeholder for the library address in this way ( is the for ). If we were to deploy contract C untouched, the deployment would fail as the bytecode is invalid. Library linking happens at the bytecode level 0073__L_____________________________________630dbe671f 0dbe671f function signature a() , Library linking is as simple as occurrences of the library placeholder in the contract bytecode of the deployed library in the blockchain. Once the contract is linked to the library, it can be deployed. In simple words replacing all with the address Now as we have covered the basics of the library, let’s see how we can use them to create upgradeable contracts. Library, themselves are not Upgradeable As stated in the previous section, They are not , in the same way, contracts aren’t either . the reference to the library is made at the bytecode level rather than at the storage level. Changing the bytecode of a contract is not allowed once deployed, therefore the reference to the library will live as long as the contract does . You must be asking that, then how does one introduce the “upgradable” feature that we have been talking about this whole time? Finally, How it Actually Works? Here is where a little trick comes in. Let’s see this in detail: Model of Updatable Contract . At compile and deploy time this is just fine because the Dispatcher doesn’t implement any of the methods of the library. This means that as the Dispatcher contract doesn’t use any library code in the contract itself, it’s(Dispatcher contract) bytecode(like the bytecode for contract C which we saw above) doesn’t have to include the library’s address in its bytecode. So, as we are not hardcoding any address on the bytecode level, we can swap the library any time with a different one. Instead of linking the main user-facing contract directly with the address of the deployed library, it is linked to a ‘Dispatcher’ contract But if we are not using any library code in the Dispatcher contract, then how do we execute the library functions? When a transaction comes in, the main contract(Token contract) thinks it is making a to the library(TokenLib1) it is linked with. But this will instead be made to the dispatcher(Dispatcher contract). delegatecall delegatecall Here is where things get interesting. Once the dispatcher catches the in its it figures out what the correct version of the library code is, and redirects the call once again with a . Once the library returns, the return will go all the way back to the main contract. delegatecall fallback function delegatecall This solution works great, but it has some minor limitations. Limitations The . Right now it is solved by having a mapping for function signatures to their return type size. This was intentionally kept out of the drawing for the sake of simplicity. dispatcher needs to know what the memory size for the return of that library call is Given the way ’s work on the EVM level, . As libraries have no storage, we kept Dispatcher with no storage. That’s why there is a separate DispatcherStorage to keep all the data it needs. Also, the . delegatecall you can only use it from one contract to another that has the same storage footprint address of the DispatcherStorage needs to be hardcoded in the Dispatcher contract’s bytecode Note that for the user-facing contract(Token contract) nothing special is needed, only that instead of being linked with the concrete version of the library, it has to be linked with the dispatcher. Here is the implementation of the solution: _Solidity implementation of a delegate proxy. Contribute to maraoz/solidity-proxy development by creating an account on…_github.com maraoz/solidity-proxy Happy Pseudo-Versioning! Sources: Jorge Izquierdo’s article on Library Driven Development Simon de la Rouviere’s article on ThrowProxy Thanks for reading ;) About the Author is a Co-Founder of Vaibhav Saini TowardsBlockchain , an MIT Cambridge Innovation Center incubated startup. He works as Senior blockchain developer and has worked on several blockchain platforms including Ethereum, Quorum, EOS, Nano, Hashgraph, IOTA etc. He is currently a sophomore at . IIT Delhi Learned something? Press and hold the 👏 to say “thanks!” and help others find this article. Hold down the clap button if you liked the content! It helps me gain exposure . Want to learn more? Checkout my previous articles. _A complete list of all consensus algorithms._hackernoon.com ConsensusPedia: An Encyclopedia of 30 Consensus Algorithms _A Complete List of all Smart Contract supportive Platforms_hackernoon.com ContractPedia: An Encyclopedia of 40 Smart Contract Platforms _A complete comparison of the two scaling methods._hackernoon.com Difference between SideChains and State Channels _The only blockchain which has blocktime of less than a second: 0.5 sec!_hackernoon.com EOS 101: Getting started with EOS, Part 1 Clap 50 times and follow me on Twitter: @vasa_develop