Just like with every new material, understanding smart contract upgradeability requires to spent quality time on it. Let’s try to shorten this learning curve :) Lately great articles and resources have been published on the topic and the team ( and ) really pushed forward the concept of upgradeable smart contracts. Zeppelin OpenZeppelin zeppelinOS However I am feeling that a dead simple example is missing in those discussions and this is what I would like to share with you. I am not going to summarizes or give you an overview about upgradeability patterns here. As I said I think there is already enough amazing ressources on the internet and ( ). Nevertheless I would like to provide you with an easy start instead. A dummy dead simple upgradeable smart contract. you will need to spend time learning and researching anyway this is a great starting post But before that let’s recapitulate some key points: relies on the . upgradeability solidity method delegatecall The most basic solution relies on 2 contracts. A (for storage) that delegates calls to a (logic contract can be upgraded. Not the proxy). proxy contract logic contract will load code from the contract receiving the call. . Again, storage is done on the calling contract ! Therefore the proxy contract will hold the state of our upgradeable contract. delegatecall Storage is done on the calling contract Calling a smart contract function that does not exist will trigger its (if the fallback function is implemented of course). This mechanism is used by the proxy contract. fallback function : I used the inherited storage pattern from zeppelinos for this example. Code was adapted from their . note repo 1. Overview let’s consider the following smart contracts and this scenario: is deployed but suddenly you realize that it contains a bug… too bad. The bug is in the function. TokenVersion1 mint pragma solidity ^0.4.21; contract TokenVersion1 {mapping (address => uint) balances; event Transfer(address \_from, address \_to, uint256 \_value); function balanceOf(address \_address) public view returns (uint) { return balances\[\_address\]; } function transfer(address \_to, uint256 \_value) public { require(balances\[msg.sender\] >= \_value); balances\[msg.sender\] -= \_value; balances\[\_to\] += \_value; emit Transfer(msg.sender, \_to, \_value); } // there is a bug in this function: value should not // be multiplied by 2 function mint(address \_to, uint256 \_value) public { balances\[\_to\] += \_value \* 2; emit Transfer(0x0, \_to, \_value); } } contract TokenVersion2 is TokenVersion1 { // bug corrected here: multiplication by 2 removed function mint(address \_to, uint256 \_value) public { balances\[\_to\] += \_value; emit Transfer(0x0, \_to, \_value); } } You do not want to mint double right ? (or maybe you do ^^). If your system is designed to support upgradeable smart contracts the bugged contract can be fixed by deploying the contract . But for this to work you need what is call a proxy contract for delegating calls to your Token contracts: TokenVersion1 TokenVersion2 pragma solidity ^0.4.21; /*** @title Proxy* @dev Gives the possibility to delegate any call to a foreign implementation.*/contract Proxy { address public implementation; function upgradeTo(address \_address) public { implementation = \_address; } /\*\* \* @dev Fallback function allowing to perform a delegatecall to the given implementation. \* This function will return whatever the implementation call returns \*/ function () payable public { address \_impl = implementation; require(\_impl != address(0)); assembly { let ptr := mload(0x40) calldatacopy(ptr, 0, calldatasize) let result := delegatecall(gas, \_impl, ptr, calldatasize, 0, 0) let size := returndatasize returndatacopy(ptr, 0, size) switch result case 0 { revert(ptr, size) } default { return(ptr, size) } } } } The transaction flow is the following: transaction flow 2. Hands-On Let’s walk through the transaction flow (figure just above) and how upgradeability is used: You start by deploying your proxy contract . Proxy Then deploy your logic contract. Here it is TokenVersion1 You tell your proxy contract to point to the by calling its function TokenVersion1 upgradeTo(address of TokenVersion1) Here comes the tricky part: let’s try to mint some tokens. But we are not going to call the function on contract directly (we would be bypassing the proxy by doing that, and breaking the upgradeability pattern). Instead we are going the call directly on the proxy and because this function does not exist, it will trigger the fallback function, firing a to the address of the contract saved in the variable. mint TokenVersion1 mint(address, value) deletagecall TokenVersion1 implementation The proxy contract of the function (thanks to ) and execute it. The mapping and event of the function are executed and stored in the proxy contract. ! Proxy contract does. And this is exactly why you can upgrade this contract :) will load the code mint delegatecall from tokenVersion1 balances Transfer mint TokenVersion1 WILL NOT store any data and WILL NOT fire any event If the function was successfully executed, calling through the proxy will return you the correct balance (well multiplied by two). However, calling directly to the contract will return you 0 (yes zero). Remember, contract did not executed any code… mint balanceOf(luckyAddress) balanceOf(luckyAddress) TokenVersion1 token At this point you noticed that your function has a bug :( got twice the amount you intended to mint. So you create a contract that inherits ( ) from and you correct the function. mint luckyAddress TokenVersion2 inherited storage TokenVersion1 mint Then you deploy your awesome and bug free contract. TokenVersion2 You tell the proxy to point to this new contract by calling upgradeTo(address of TokenVersion2) Et voilà! :) Your proxy is now delegating calls to the new version of your Token contract. And because the state is stored in the proxy contract, no data was lost ! (yes still has double the coins from the bug in — state is persistance across your updates, and that’s the point.) luckyAddress tokenVersion1 3. Code You’ll find a complete working example in my github repo: _ethereum_contract_upgradeablitiy_simple_example - dead simple example of smart contract upgradeability mechanism…_github.com salanfe/ethereum_contract_upgradeablitiy_simple_example There is a standalone script in folder. See the file header on how to run it. In a nut shell start ganache and run it :). python /python If you prefer , you’ll find a test file in . Same, instructions are in its header. javascript /test 4. Ressources Don’t stop here :) This “dummy” example is just to get you started. Inherited storage is one pattern among a few. The community has come up with at least 2 other patterns: and . Here are great ressources (kind of sorted): eternal storage unstructured storage https://blog.zeppelinos.org/proxy-patterns/ https://github.com/zeppelinos/labs https://blog.zeppelin.solutions/proxy-libraries-in-solidity-79fbe4b970fd https://blog.colony.io/writing-upgradeable-contracts-in-solidity-6743f0eecc88 https://vomtom.at/upgrade-smart-contracts-on-chain/ https://medium.com/aigang-network/upgradable-smart-contracts-what-weve-learned-at-aigang-b181d3d4b668 https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c