How to Write Upgradable Smart Contracts (Smart Contract Versioning)
Tags: ethereum, smartcontract, javascript, node
Published: 2020-02-26 21:37:36

This article was first published on our open-source platform, [SimpleAsWater.com](https://simpleaswater.com/upgradable-smart-contracts/?ref=dev_to). If you are interested in IPFS, Libp2p, Ethereum, Zero-knowledge Proofs, Defi, CryptoEconomics, IPLD, Multi formats, and other Web 3.0 projects, concepts and interactive tutorials, then be sure to check out [SimpleAsWater.com](https://simpleaswater.com/upgradable-smart-contracts/?ref=dev_to).

---

Smart contracts are [immutable](https://en.wikipedia.org/wiki/Immutable_object), by design. On the other hand, software quality heavily depends on the ability to upgrade and patch source code to produce iterative releases. Even though blockchain-based software profits significantly from the technology’s immutability, still a certain degree of mutability is needed for bug fixing and potential product improvements.

In this post, we are going to learn:

1.  Why do we need to upgrade smart contracts?
2.  Understanding how upgrades work under the hood?
3.  Using [OpenZeppelin CLI](https://www.npmjs.com/package/@openzeppelin/cli) to easily write/manage "upgradable" smart contracts.
4.  Upgrading Contracts Programmatically using the [OpenZeppelin Upgrades](https://www.npmjs.com/package/@openzeppelin/upgrades) library.
5.  A few Limitations & Workarounds of Upgradable Contracts

If you are just looking for a way to write upgradable contracts and don't want to go through "how this all works", then just head over to the [3rd section](#openZeppelin-upgrades).

> In case you get stuck somewhere or have any doubts, let us know [here](https://discord.gg/x2kmUXW).

Why do we need to upgrade?
--------------------------

Smart contracts in Ethereum are [immutable](https://en.wikipedia.org/wiki/Immutable_object) by default. Once you create them there is no way to alter them, effectively acting as an unbreakable contract among participants.

However, there are several scenarios where we wish if there was a way to upgrade the contracts. There are a lot of examples in which [millions of dollars worth of Ether were stolen/hacked](https://medium.com/firmonetwork/3-famous-smart-contract-hacks-you-should-know-dffa6b934750), which could be saved if we could update the smart contracts.

How do upgrades work under the hood?
------------------------------------

There can be several ways we can upgrade our contracts.

The most obvious way will be something like this:

*   Create & deploy a new version of the contract.
*   Manually migrate all states from the old contract to the new contract.

This seems to work, but has several problems.

1.  Migrating the contract state can be expensive.
2.  As we create & deploy a new contract, the _contract address_ will change. So you would need to update all contracts that interacted with the old contract to use the address of the new version.
3.  You would also have to reach out to all your users and convince them to start using the new contract and handle both contracts being used simultaneously, as users are slow to migrate.

A better way is to use a _proxy_ contract with an [interface](https://www.tutorialspoint.com/solidity/solidity_interfaces.htm) where each method _delegates_ to the _implementation_ contract (which contains all the logic).

![](https://simpleaswater.com/content/images/2020/02/upgrading-contracts-2-2.png)

A _[delegate call](https://medium.com/coinmonks/delegatecall-calling-another-contract-function-in-solidity-b579f804178c)_ is similar to a regular call, except that all code is executed in the context of the caller (_proxy_), **not** of the callee (_implementation_). Because of this, a `transfer` in the implementation contract’s code will transfer the proxy’s balance, and any reads or writes to the contract storage will read or write from the proxy’s storage.

This approach is better because the users only interact with the _proxy_ contract and we can change the _implementation_ contract while keeping the same _proxy_ contract.

![](https://simpleaswater.com/content/images/2020/02/upgrading-contracts-3.png)

This seems better than the previous approach, but if we need to make any changes to the _implementation_ contract methods, we would need to update the _proxy_ contract's methods too (as the proxy contract has interface methods). Hence, users will need to change the proxy address.

To solve this problem, we can use a [fallback](https://www.tutorialspoint.com/solidity/solidity_fallback_function.htm) function in the proxy contract. The [fallback](https://www.tutorialspoint.com/solidity/solidity_fallback_function.htm) function will execute on any request, redirecting the request to the _implementation_ and returning the resulting value (using [opcodes](https://medium.com/@blockchain101/solidity-bytecode-and-opcode-basics-672e9b1a88c2)). This is similar to the previous approach, but here the proxy contract doesn’t have interface methods, only a fallback function, so there is no need to change the proxy address if contract methods are changed.

This was a basic explanation which is enough for us to work with upgradable contracts. In case, you want to dig deep into proxy contract code and different proxy patterns, then check out this post.

[How Upgradable Smart Contracts Work Under the Hood](https://simpleaswater.com/how-upgradable-smart-contracts-work-under-the-hood)


OpenZeppelin Upgrades
---------------------

As we saw above, there are a lot of things you need to manage while writing upgradeable contracts.

Fortunately, projects like [OpenZeppelin](https://openzeppelin.com/) have built [CLI tools & libraries](https://docs.openzeppelin.com/upgrades/2.7/), which provide an easy to use, simple, robust, and opt-in upgrade mechanism for smart contracts that **can be controlled by any type of governance, be it a multi-sig wallet, a simple address or a complex DAO.**

Let's first build a basic upgradeable contract using the OpenZeppelin CLI tool. You can find the **code for the below implementation** [**here**](https://github.com/simpleaswater/upgradable-smart-contracts).

> In case you get stuck somewhere or have any doubts, let us know [here](https://discord.gg/x2kmUXW).

OpenZeppelin Upgrades CLI
-------------------------

Working with OpenZeppelin CLI requires [Node.js](https://nodejs.org/) for development. If you don't have it already, install node using whatever package manager you prefer or [using the official installer](https://nodejs.org/en/download/).

### Project Setup

Create a folder named `upgradable-smart-contracts` and go inside the folder.

```
$ mkdir upgradable-smart-contracts && cd upgradable-smart-contracts 
```

> Throughout this tutorial, we use the ****$**** character to indicate your terminal’s shell prompt. When following along, don’t type the ****$**** character, or you’ll get some weird errors.

We will use a local blockchain for this tutorial. The most popular local blockchain is [Ganache](https://github.com/trufflesuite/ganache-cli). To install and run it on your project, run:

```
$ npm install --save-dev ganache-cli && npx ganache-cli --deterministic
```

Now, start a new shell/terminal in the same folder run the following command to install the CLI tool:

```
$ npm install --save-dev @openzeppelin/cli
```

To manage your deployed contracts, you need to create a new CLI project. Run the following command, and provide it with a name and version number for your project when prompted:

```
$ npx openzeppelin init
```

Two things will happen during initialization. First, an `.openzeppelin` directory will be created, holding project-specific information. This directory will be managed by the CLI: you won’t need to manually edit anything. You should, however, commit [some of these files](https://docs.openzeppelin.com/cli/2.7/configuration#configuration-files-in-version-control) to Git.

Second, the CLI will store network configuration in a file called `networks.js`. For convenience, it is already populated with an entry called `development`, with configuration matching [Ganache](https://docs.openzeppelin.com/learn/deploying-and-interacting#local-blockchain)'s default.

You can see all the unlocked accounts by running the following command:

```
$ npx openzeppelin accounts
```

![](https://simpleaswater.com/content/images/2020/02/ganache-accounts-1.png)

List of unlocked accounts

### Writing & deploying contracts

Now, let's create a contract named `TodoList` in the `contracts` folder.

```
// contracts/TodoList.sol
pragma solidity ^0.6.3;

contract TodoList {
    string[] private list;

    // Emitted when the storeda new item is added to the list
    event ItemAdded(string item);

    // Adds a new item in the list
    function addItem(string memory newItem) public {
        list.push(newItem);
        emit ItemAdded(newItem);
    }

    // Gets the item from the list according to index
    function getListItem(uint256 index)
        public
        view
        returns (string memory item)
    {
        return list[index];
    }
}
```

Now, let's deploy this contract on the local blockchain.

```
$ npx openzeppelin create
```

![](https://simpleaswater.com/content/images/2020/02/deploy-contract-1.png)

As we can see our contract is deployed at `0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb`.

Let's add an item ("responding to emails") to the `list` array using the `addItem()` function by running `npx openzeppelin send-tx`.

![](https://simpleaswater.com/content/images/2020/02/send-trx.png)

Now, let's suppose we need to add a new function named `getListSize()` to get the size of the list. Just add a new function inside the `TodoList` contract.

```
// contracts/TodoList.sol
pragma solidity ^0.6.3;

contract TodoList {
	// ...


    // Gets the size of the list
    function getListSize() public view returns (uint256 size) {
        return list.length;
    }
}
```

After changing the Solidity file, we can now just upgrade the instance we had deployed earlier by running the `openzeppelin upgrade` command.

![](https://simpleaswater.com/content/images/2020/02/upgrading-contract.png)

Done! Our `TodoList` instance has been upgraded to the latest version of the code ****while keeping its state and the same address as before****. We didn’t need to create & deploy the _proxy_ contract or link the _proxy_ to the `TodoList`. All that is done under the hood!

Let’s try it out by invoking the new `getListSize()` function, and checking the size of the list in the new contract:

![](https://simpleaswater.com/content/images/2020/02/call.png)

That’s it! Notice how the `size` of the `list` was preserved throughout the upgrade, as well as its address. And this process is the same regardless of whether you are working on a local blockchain, a testnet, or the main network.

Upgrading Contracts Programmatically
------------------------------------

If you want to create and upgrade contracts from your JavaScript code instead of via the command line, you can use the ****[OpenZeppelin Upgrades](https://www.npmjs.com/package/@openzeppelin/upgrades)**** library instead of the CLI.

> The CLI does not just manage contract upgrades, but also compilation, interaction, and source code verification. The Upgrades library **only** takes care of creating and upgrading. The library also does **not** keep track of the contracts you have already deployed, nor runs any initializer or storage layout validations, as the CLI does. Nevertheless, these capabilities may be added to the Upgrades library in the near future.

You can find the **code for the below implementation [here](https://github.com/simpleaswater/upgradable-smart-contracts/blob/master/index.js)**.

> In case you get stuck somewhere or have any doubts, let us know [here](https://discord.gg/x2kmUXW).

In case you have not followed the above OpenZeppelin CLI part, you need to [install NodeJs & Ganache as instructed here](#openZeppelin-upgrades-cli).

Your first step will be to install the library in your project, and you will also probably want to install `web3` to interact with our contracts using JavaScript, and `@openzeppelin/contract-loader` to load the contracts from the JSON artifacts.

```
$ npm install web3 @openzeppelin/upgrades @openzeppelin/contract-loader
```

Now, create a file `index.js` inside `upgradable-smart-contracts` folder and paste this boilerplate code.

```
// index.js
const Web3 = require("web3");
const {
  ZWeb3,
  Contracts,
  ProxyAdminProject
} = require("@openzeppelin/upgrades");

async function main() {
  // Set up web3 object, connected to the local development network, initialize the Upgrades library
  const web3 = new Web3("http://localhost:8545");
  ZWeb3.initialize(web3.currentProvider);
  const loader = setupLoader({ provider: web3 }).web3;
}

main();

```

Here we set up `web3` object, connected to the local development network, initialize the `Upgrades` library via `ZWeb3.initialize`, and initialize the contract `loader`.

Now, add this following snippet in the `main()` to create a new `project`, to manage our upgradeable contracts.

```
async function main() {
  // ...
    
  //Fetch the default account
  const from = await ZWeb3.defaultAccount();

  //creating a new project, to manage our upgradeable contracts.
  const project = new ProxyAdminProject("MyProject", null, null, {
    from,
    gas: 1e6,
    gasPrice: 1e9
  });
}
```

Now, using this `project`, we can create an instance of any contract. The `project` will take care of deploying it in such a way it can be upgraded later.

Let's create 2 contracts, `TodoList1` and its updated version `TodoList2` inside `upgradable-smart-contracts/contracts` folder.

```
// contracts/TodoList1.sol
pragma solidity ^0.6.3;

contract TodoList1 {
    string[] private list;

    // Emitted when the storeda new item is added to the list
    event ItemAdded(string item);

    // Adds a new item in the list
    function addItem(string memory newItem) public {
        list.push(newItem);
        emit ItemAdded(newItem);
    }

    // Gets the item from the list according to index
    function getListItem(uint256 index)
        public
        view
        returns (string memory item)
    {
        return list[index];
    }
}
```

To create `TodoList2`, just add a new `getListSize()` function in the above contract.

```
// contracts/TodoList2.sol
pragma solidity ^0.6.3;

contract TodoList2 {
    string[] private list;

    // Emitted when the storeda new item is added to the list
    event ItemAdded(string item);

    // Adds a new item in the list
    function addItem(string memory newItem) public {
        list.push(newItem);
        emit ItemAdded(newItem);
    }

    // Gets the item from the list according to index
    function getListItem(uint256 index)
        public
        view
        returns (string memory item)
    {
        return list[index];
    }

    // Gets the size of the list
    function getListSize() public view returns (uint256 size) {
        return list.length;
    }
}
```

Now, we need to compile these 2 contracts using:

```
$ npx openzeppelin compile
```

This will create JSON contract artifacts in the `build/contracts` folder. These artifacts files contain all the information about the contracts that we would need to deploy and interact with the contracts.

Now, let's create an instance of `TodoList1` using the `project` we created above.

```
async function main() {
//...
    
    
//Using this project, we can now create an instance of any contract.
  //The project will take care of deploying it in such a way it can be upgraded later.
  const TodoList1 = Contracts.getFromLocal("TodoList1");
  const instance = await project.createProxy(TodoList1);
  const address = instance.options.address;
  console.log("Proxy Contract Address 1: ", address);
}
```

Here we get the `TodoList1` contract details from the contract artifacts we created above using `Contracts.getFromLocal`. Then we create & deploy a pair of _proxy_ & _implementation_ (`TodoList1`)  contracts and link the proxy contract to the `TodoList1` via `project.createProxy` method. Finally, we print out the address of our proxy contract.

Now, let's add an item to the `list` using `addItem()` method and then fetch the added item using `getListItem()`.

```
async function main() {
//...
    
  // Send a transaction to add a new item in the TodoList1
  await todoList1.methods
    .addItem("go to class")
    .send({ from: from, gas: 100000, gasPrice: 1e6 });

  // Call the getListItem() function to fetch the added item from TodoList1
  var item = await todoList1.methods.getListItem(0).call();
  console.log("TodoList1: List Item 0: ", item);
}
```

Now, let's update our `TodoList1` contract to `TodoList2`.

```
async function main() {
//...
    
    
//After deploying the contract, you can upgrade it to a new version of
  //the code using the upgradeProxy method, and providing the instance address.
  const TodoList2 = Contracts.getFromLocal("TodoList2");
  const updatedInstance = await project.upgradeProxy(address, TodoList2);
  console.log("Proxy Contract Address 2: ", updatedInstance.options.address);
}
```

Here we get the `TodoList2` contract details from the contract artifacts. Then we update our contract via `project.upgradeProxy` method which takes 2 parameters, the `address` of the proxy contract that we deployed in the previous step, and the `TodoList2` contract object. We then print out the address of the proxy contract after the update.

Now, let's add a new item to the `TodoList2` and fetch the items.

```
async function main() {
//...
    
    
  // Send a transaction to add a new item in the TodoList2
  await todoList2.methods
    .addItem("code")
    .send({ from: from, gas: 100000, gasPrice: 1e6 });

  // Call the getListItem() function to fetch the added items from TodoList2
  var item0 = await todoList2.methods.getListItem(0).call();
  var item1 = await todoList2.methods.getListItem(1).call();
  console.log("TodoList2: List Item 0: ", item0);
  console.log("TodoList2: List Item 1: ", item1);
}
```

Now, let's run the `index.js` using `node index.js`.

![](https://simpleaswater.com/content/images/2020/02/terminal.png)

Here we can observe 2 things:

*   The address of the _proxy_ contract did not change even after we updated `TodoList1` to `TodoList2`.
*   As we got 2 items from the `TodoList2`, this shows that the state was preserved throughout the update.

Hence we can say that `TodoList1` instance has been upgraded to the latest version of the code (`TodoList2`), ****while keeping its state and the same address as before****.

> In case you get stuck somewhere or have any doubts, let us know [here](https://discord.gg/x2kmUXW).

Now, as we have seen how to upgrade contracts, let's see a few limitations & workarounds that you need to know about when writing more complex contracts.

A few things to keep in mind: limitations & workarounds
-------------------------------------------------------

When working with upgradeable contracts using OpenZeppelin Upgrades, there are a few minor caveats to keep in mind when writing your Solidity code.

It’s worth mentioning that these restrictions have their roots in how the [Ethereum VM](https://www.bitrates.com/guides/ethereum/what-is-the-unstoppable-world-computer) works, and apply to all projects that work with upgradeable contracts, not just OpenZeppelin Upgrades.

> If your contract is not compatible for upgrades, the CLI will warn you when you try to upgrade. This feature is not there yet in the OpenZeppelin Upgrades libraries.

In order to understand the limitations & workarounds, let's take an `Example` contract, explore the limitations in the contract and add some workarounds to make the contract upgradable.

```
// contracts/Example.sol

pragma solidity ^0.6.0;

import "github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20Capped.sol";

contract Example {
    uint256 private _cap = 1000000000000000000;
    ERC20Capped public token;

    constructor(uint8 cap) public {
        _cap = cap;
        token = new ERC20Capped(_cap);
    }
}
```

### Limitation 1: No Constructors

Due to a requirement of the proxy-based upgradeability system, no constructors can be used in upgradeable contracts. To learn about the reasons behind this restriction, head to this [post](https://simpleaswater.com/how-upgradable-smart-contracts-work-under-the-hood/).

### Workaround: Initializer

A workaround is to replace the constructor with a function, typically named `initialize`, where you run constructor logic.

```
// contracts/Example.sol
pragma solidity ^0.6.0;

import "github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20Capped.sol";

contract Example {
    uint256 private _cap = 1000000000000000000;
    ERC20Capped public token;

    function initialize(uint8 cap) public {
        _cap = cap;
        token = new ERC20Capped(_cap);
    }
}
```

Now, as the `constructor` is called only once when the contract is initialized, we need to add a check to ensure that the `initialize` function gets called only once.

```
// contracts/Example.sol
pragma solidity ^0.6.0;

import "github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20Capped.sol";

contract Example {
    uint256 private _cap = 1000000000000000000;
    ERC20Capped public token;
    
    bool private _initialized = false;

    function initialize(uint8 cap) public {
        require(!_initialized);
        _initialized = true;
        _cap = cap;
        token = new ERC20Capped(_cap);
    }
}
```

Since this will be a common thing to do when writing upgradeable contracts, OpenZeppelin Upgrades provides an `Initializable` base contract that has an `initializer` modifier that takes care of this:

```
// contracts/Example.sol
pragma solidity ^0.6.0;

import "github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20Capped.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";

contract Example is Initializable {
    uint256 private _cap = 1000000000000000000;
    ERC20Capped public token;
    
    function initialize(uint8 cap) public initializer {
        _cap = cap;
        token = new ERC20Capped(_cap);
    }
}
```

Another difference between a `constructor` and a regular function is that Solidity takes care of automatically invoking the constructors of all ancestors of a contract. When writing an initializer, you need to take special care to manually call the initializers of all parent contracts:

```
// contracts/Example.sol
pragma solidity ^0.6.0;

import "github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20Capped.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";


contract BaseExample is Initializable {
    uint256 public createdAt;
    
    function initialize() initializer public {
        createdAt = block.timestamp;
    }
    
}

contract Example is BaseExample {
    uint256 private _cap = 1000000000000000000;
    ERC20Capped public token;

    function initialize(uint8 cap) initializer public {
        _cap = cap;
        token = new ERC20Capped(_cap);
    }
}
```

Keep in mind that this restriction affects not only your contracts, but also the contracts you import from a library. Consider for example `ERC20Capped` from OpenZeppelin Contracts: the contract initializes the token’s `cap` in its constructor.

```
pragma solidity ^0.6.0;

import "./ERC20.sol";

/**
 * @dev Extension of {ERC20} that adds a cap to the supply of tokens.
 */
contract ERC20Capped is ERC20 {
    uint256 private _cap;

    /**
     * @dev Sets the value of the `cap`. This value is immutable, it can only be
     * set once during construction.
     */
    constructor (uint256 cap) public {
        require(cap > 0, "ERC20Capped: cap is 0");
        _cap = cap;
    }
    
    //...
}
```

This means you should not be using these contracts in your OpenZeppelin Upgrades project. Instead, make sure to use `@openzeppelin/contracts-ethereum-package`, which is an official fork of OpenZeppelin Contracts that has been modified to use initializers instead of constructors. Take a look at how [ERC20Capped](https://github.com/OpenZeppelin/openzeppelin-contracts-ethereum-package/blob/v2.0.2/contracts/token/ERC20/ERC20Capped.sol) looks in `@openzeppelin/contracts-ethereum-package`:

```
pragma solidity ^0.5.0;

import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "./ERC20Mintable.sol";

/**
 * @dev Extension of {ERC20Mintable} that adds a cap to the supply of tokens.
 */
contract ERC20Capped is Initializable, ERC20Mintable {
    uint256 private _cap;

    /**
     * @dev Sets the value of the `cap`. This value is immutable, it can only be
     * set once during construction.
     */
    function initialize(uint256 cap, address sender) public initializer {
        ERC20Mintable.initialize(sender);

        require(cap > 0, "ERC20Capped: cap is 0");
        _cap = cap;
    }

	//...
}
```

Whether using OpenZeppelin Contracts or another Ethereum Package, always make sure that the package is set up to handle upgradeable contracts.

```
// contracts/Example.sol
pragma solidity ^0.6.0;

import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20Capped.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";


contract BaseExample is Initializable {
    uint256 public createdAt;
    
    function initialize() initializer public {
        createdAt = block.timestamp;
    }
    
}

contract Example is BaseExample {
    uint256 private _cap = 1000000000000000000;
    ERC20Capped public token;
 
    function initialize(uint8 cap) initializer public {
        _cap = cap;
        token = new ERC20Capped(_cap);
    }
}
```

### Limitation 2: Initial Values in Field Declarations

Solidity allows defining initial values for fields when declaring them in a contract.

```
contract Example is BaseExample {
    uint256 private _cap = 1000000000000000000;
	
    //...
}

```

This is equivalent to setting these values in the constructor, and as such, will not work for upgradeable contracts.

### Workaround: Initializer

Make sure that all initial values are set in an initializer function as shown below; otherwise, any upgradeable instances will not have these fields set.

```
//...

contract Example is BaseExample {
    uint256 private _cap;
    ERC20Capped public token;

    function initialize(uint8 cap) initializer public {
        _cap = 1000000000000000000;
        _cap = cap;
        token = new ERC20Capped(_cap);
    }
}
```

Note that it still is fine to set constants here, because the compiler [does not reserve a storage slot for these variables](https://solidity.readthedocs.io/en/latest/contracts.html#constant-state-variables), and every occurrence is replaced by the respective constant expression. So the following still works with OpenZeppelin Upgrades:

```
//...

contract Example is BaseExample {
    uint256 constant private _cap = 1000000000000000000;
    
    //...
}
```

### Limitation: Creating New Instances From Your Contract Code

When creating a new instance of a contract from your contract’s code, these creations are handled directly by Solidity and not by OpenZeppelin Upgrades, which means that ****these contracts will not be upgradeable****.

For instance, in the following example, even if `Example` is upgradeable (if created via `openzeppelin create Example`), the `token` contract created is not:

```
//...

contract Example is BaseExample {
    uint256 private _cap = 1000000000000000000;
    ERC20Capped public token;

    function initialize(uint8 cap) initializer public {
        _cap = cap;
        token = new ERC20Capped(_cap);
    }
}
```

### Workaround: Inject a pre-deployed contract from CLI

The easiest way around this issue is to avoid creating contracts on your own altogether: instead of creating a contract in an `initialize` function, simply accept an instance of that contract as a parameter, and inject it after creating it from the OpenZeppelin CLI:

```
//...

contract Example is BaseExample {
    ERC20Capped public token;
    
    function initialize(ERC20Capped _token) initializer public {
        token = _token;
    }
}
```

```
$ TOKEN=$(npx openzeppelin create TokenContract)
$ npx oz create Example --init --args $TOKEN
```

### Workaround: OpenZeppelin App Contract

An advanced alternative, if you need to create upgradeable contracts on the fly, is to keep an instance of your OpenZeppelin project’s `App` in your contracts. The [`App`](https://docs.openzeppelin.com/upgrades/2.7/api#App) is a contract that acts as the entrypoint for your OpenZeppelin project, which has references to your logic implementations, and can create new contract instances:

```
// contracts/Example.sol
pragma solidity ^0.6.0;

import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "@openzeppelin/upgrades/contracts/application/App.sol";

contract BaseExample is Initializable {
    //...
}

contract Example is BaseExample {
    
  App private app;

  function initialize(App _app) initializer public {
    app = _app;
  }

  function createNewToken() public returns(address) {
    return app.create("@openzeppelin/contracts-ethereum-package", "ERC20Capped");
  }
}
```

### Potentially Unsafe Operations

When working with upgradeable smart contracts, you will always interact with the proxy contract instance, and never with the underlying logic (implementation) contract. However, nothing prevents a malicious actor from sending transactions to the logic contract directly. This does not pose a threat, since any changes to the state of the logic contracts do not affect your proxy contract instances, as the storage of the logic contracts is never used in your project.

There is, however, an exception. If the direct call to the logic contract triggers a `selfdestruct` operation, then the logic contract will be destroyed, and all your contract instances will end up delegating all calls to an address without any code. This would effectively break all contract instances in your project.

A similar effect can be achieved if the logic contract contains a `delegatecall` operation. If the contract can be made to `delegatecall` into a malicious contract that contains a `selfdestruct`, then the calling contract will be destroyed.

```
pragma solidity ^0.6.0;

// The Exmaple contract makes a `delegatecall` to the Malicious contract. Thus, even if the Malicious contract runs the `selfdestruct` function, it is run in the context of the Example contract, thus killing the Example contract.  

contract Example {
    function testFunc(address malicious) public {
        malicious.delegatecall(abi.encodeWithSignature("kill()"));
    }
}

contract Malicious {
    function kill() public {
        address payable addr = address(uint160(address(0x4Bf8c809c898ee52Eb7fc6e1FdbB067423326B2A)));
        selfdestruct(addr);
    }
}
```

As such, it is strongly recommended to avoid any usage of either `selfdestruct` or `delegatecall` in your contracts. If you need to include them, make absolutely sure they cannot be called by an attacker on an uninitialized logic contract.

### Modifying Your Contracts

When writing new versions of your contracts, either due to new features or bugfixing, there is an additional restriction to observe: you cannot change the order in which the contract state variables are declared, nor their type. You can read more about the reasons behind this restriction by learning about [Proxies](https://docs.openzeppelin.com/upgrades/2.7/proxies).

> Violating any of these storage layout restrictions will cause the upgraded version of the contract to have its storage values mixed up, and can lead to critical errors in your application.

This means that if you have an initial contract that looks like this:

```
pragma solidity ^0.6.3;

contract Example {
    string public tokenName;
    uint8 public decimals;
}
```

Then you cannot change the type of a variable:

```
pragma solidity ^0.6.3;

contract Example {
    string public tokenName;
    uint public decimals;
}
```

Or change the order in which they are declared:

```
pragma solidity ^0.6.3;

contract Example {
    uint public decimals;
    string public tokenName;
}
```

Or introduce a new variable before existing ones:

```
pragma solidity ^0.6.3;

contract Example {
	string public tokenSymbol;
    string public tokenName;
    uint public decimals;
}
```

Or remove an existing variable:

```
pragma solidity ^0.6.3;

contract Example {
    string public tokenName;
}
```

If you need to introduce a new variable, make sure you always do so at the end:

```
pragma solidity ^0.6.3;

contract Example {
    string public tokenName;
    uint public decimals;
	string public tokenSymbol;
}
```

Keep in mind that if you rename a variable, then it will keep the same value as before after upgrading. This may be the desired behaviour if the new variable is semantically the same as the old one:

```
pragma solidity ^0.6.3;

contract Example {
    string public tokenName;
    uint public decimalCount;	// starts with the value of `decimals`
}
```

And if you remove a variable from the end of the contract, note that the storage will not be cleared. A subsequent update that adds a new variable will cause that variable to read the leftover value from the deleted one.

```
pragma solidity ^0.6.3;

contract Example1 {
    string public tokenName;
    uint public decimals;
}

// Updating Example1 --> Example2

contract Example2 {
    string public tokenName;
}

// Updating Example2 --> Example3

contract Example3 {
    string public tokenName;
    uint public decimalCount;	// starts with the value of `decimals`
}
```

Note that you may also be inadvertently changing the storage variables of your contract by changing its parent (base) contracts. For instance, if you have the following contracts:

```
pragma solidity ^0.6.3;

contract BaseExample1 {
	uint256 createdAt;
}

contract BaseExample2 {
	string version;
}

contract Example is BaseExample1, BaseExample2 {}
```

Then modifying `Example` by swapping the order in which the base contracts are declared, or adding new base contracts or removing base contracts, will change how the variables are actually stored:

```
pragma solidity ^0.6.3;

contract BaseExample1 {
	uint256 createdAt;
}

contract BaseExample2 {
	string version;
}

//swapping the order in which the base contracts are declared
contract Example is BaseExample2, BaseExample1 {}

//Or...

//removing base contract(s)
contract Example is BaseExample1 {}

//Or...

contract BaseExample3 {} 

//adding new base contract
contract Example is BaseExample1, BaseExample2, BaseExample3 {}
```

You also cannot add new variables to base contracts, if the child has any variables of its own. Given the following scenario:

```
pragma solidity ^0.6.3;

contract BaseExample {}

contract Example is BaseExample {
	string tokenName;
}

//Now, if the BaseExample is updated to the following

contract BaseExample {
	string version;		// takes the value of `tokenName` 
}

contract Example is BaseExample {
	string tokenName;
}

```

Then the variable `version` would be assigned the slot that `tokenName` had in the previous version.

You also remove a variable from the base contract, if the child has any variables of its own. For example:

```
pragma solidity ^0.6.3;

contract BaseExample {
	uint256 createdAt;
    string version;
}

contract Example is BaseExample {
	string tokenName;
}

//Now, if the BaseExample is updated to the following

contract BaseExample {
	uint256 createdAt; 
}

contract Example is BaseExample {
	string tokenName;	//takes the value of `version`
}
```

Here, as we remove the `version` variable from the `BaseExample`, the memory slot for `version` (before update) will now be used by `tokenName` (after update).

A workaround for this is to declare unused variables on base contracts that you may want to extend in the future, as a means of "reserving" those slots. So, basically, keeping the number and order of the variables in the parent and child contracts same for all the updates.

```
pragma solidity ^0.6.3;

contract BaseExample {
	string someVar1;
    string someVar2;
    string someVar3;
    
    //...
}
```

Note that this trick does **not** involve increased gas usage.

> In case you get stuck somewhere or have any doubts, let us know [here](https://discord.gg/x2kmUXW).

### References

*   [NuCypher’s Approaches to Upgradeable Contracts](https://docs.nucypher.com/en/latest/architecture/upgradeable_proxy_contracts.html)
*   [Upgrading Smart Contracts](https://docs.openzeppelin.com/learn/upgrading-smart-contracts)
*   [Writing Upgradeable Contracts](https://docs.openzeppelin.com/upgrades/2.7/writing-upgradeable)