Upgrade contracts in Solidity
Tags: blockchain, solidity, smartcontracts, soliditytutorial
Published: 2021-02-02 05:39:35

---
title: Upgrade contracts in Solidity
published: true
date: 2021-02-01 08:30:22 UTC
tags: blockchain,solidity,smartcontracts,soliditytutorial
canonical_url: https://medium.com/coinmonks/upgrade-contracts-in-solidity-500a34c1dde
---

![The planet from a distance with light connections on surface](https://cdn-images-1.medium.com/max/1024/0*Gqmiihku1-C-rm1g)<figcaption>Photo by <a href="https://unsplash.com/@nasa?utm_source=medium&amp;utm_medium=referral">NASA</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption>

### Upgradability in Solidity — Data and App contracts

Once a smart contract is deployed it cannot be changed. However, there are good reasons one might want to change a contract after it is deployed:

- a bug is found and needs to be fixed
- business rules have changed and require the contract code to be updated
- access to owner’s private key is lost or compromised
- gas fees have increased and code optimization is required

In this post we’ll talk about separating the contract into a Data and App contracts. This works well unless you need to change data structures. There are alternatives, such as contract migration, app/proxy/data and eternal storage, to name a few. Each comes with its own benefits and drawbacks, so no one solution will fit all use cases.

#### Simple Contract: Num

Num.sol:

```
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.8.0 < 0.9.0;

contract Num {
    uint num;
    
    function set(uint n) external {
        num = n;
    }

    function get() external view returns (uint) {
        return num;
    }

}
```

We’ll focus on the method of separation instead of the actual app

1. Create App contract

```
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.8.0 < 0.9.0;

contract NumApp {
    
}
```

2. Move logic that can change from Data to App contract

```
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.8.0 < 0.9.0;

contract NumApp {
    function set(uint n) external {
        num = n;
    }

    function get() external view returns (uint) {
        return num;
    }

}
```

3. Create stubs for missing functions (copy function definition from data to app contract)

Here we will create a public function which uses the internal set function

```
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.8.0 < 0.9.0;

contract NumApp {
    function setNum(uint n) external {
        set(n);
    }
        
    function getNum() ex returns (uint) {
        return get();
    }

}
```

4. Move internal/private functions in use in App contract to Data contract interface and change to external in both contracts

```
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.8.0 < 0.9.0;

contract NumApp {
    function setNum(uint n) external {
        set(n);
    }
        
    function getNum() external returns (uint) {
        return get();
    }

}

interface Num {
    set(uint n) external;
    get() external returns (uint);

}
```

5. Create dataContract state variable inside App contract and initialize it in constructor

```
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.8.0 < 0.9.0;

contract NumApp {
    Num dataContract;

    constructor(address dataContractAddress) {
        dataContract = Num(dataContractAddress);
    }

    function setNum(uint n) external {
        set(n);
    }
        
    function getNum() external returns (uint) {
        return get();
    }
}

interface Num {
    set(uint n) external;
    get() external returns (uint);

}
```

6. Change App contract functions that are present in the Data contract to dataContract.<function> inside the App contract

```
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.8.0 < 0.9.0;

contract NumApp {
    Num dataContract;

constructor(address dataContractAddress) {
        dataContract = Num(dataContractAddress);
    }

    function setNum(uint n) external {
        dataContract.set(n);
    }
        
    function getNum() external returns (uint) {
        return dataContract.get();
    }
}

interface Num {
    set(uint n) external;
    get() external returns (uint);

}
```

7. Restrict Data contract callers

Inside the Data contract:

- create mapping(address => bool) private authorizedAddresses
- add if missing:

```
address private contractOwner

constructor() {
    contractOwner = msg.sender;
}

modifier requireContractOwner() {
    require(msg.sender == contractOwner, "Caller is not contract owner");
    _;
}
```

- add a way to authorize and deauthorize contracts:

```
function authorizeContract(address appContract) external requireContractOwner {
    authorizedContracts[appContract] = true;
}

function deauthorizeContract(address appContract) external requireContractOwner {
    delete authorizedContracts[appContract];
}
```

- add modifier to functions that will be called externally to make sure the caller is authorized

```
modifier isCallerAuthorized() {
    require(authorizedContracts[msg.sender] == true, "Caller is not authorized");
    _;
}
```

#### Final Data Contract

```
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.8.0 < 0.9.0;

contract Num {
    uint num;
    
    address private contractOwner;
    mapping(address => bool) private authorizedContracts;
    
    constructor() {
        contractOwner = msg.sender;
    }
    
    modifier requireContractOwner() {
        require(msg.sender == contractOwner, "Caller is not contract owner");
        _;
    }
    
    modifier isCallerAuthorized() {
        require(authorizedContracts[msg.sender] == true, "Caller is not authorized");
        _;
    }
    
    function authorizeContract(address appContract) external requireContractOwner {
        authorizedContracts[appContract] = true;
    }
    
    function deauthorizeContract(address appContract) external requireContractOwner {
        delete authorizedContracts[appContract];
    }
    
    function set(uint n) external isCallerAuthorized {
        num = n;
    }
    
    function get() external view isCallerAuthorized returns (uint) {
        return num;
    }
}
```

#### Final App Contract

```
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.8.0 < 0.9.0;

contract NumApp {
    Num dataContract;
    
    constructor(address dataContractAddress) {
        dataContract = Num(dataContractAddress);
    }
    
    function setNum(uint n) external {
        dataContract.set(n);
    }
    
    function getNum() external view returns (uint) {
        return dataContract.get();
    }
}

interface Num {
    function set(uint n) external;
    function get() external view returns (uint);
}
```

#### How to deploy and test

1. Go to [https://remix.ethereum.org](https://remix.ethereum.org)
2. Create Num.sol and paste Data contract
3. Create NumApp.sol and paste App contract
4. Compiler version needs to be at least 0.8.0
5. Go to the deploy tab (3rd from top to bottom)
6. Deploy Num
7. Copy Num address, select NumApp contract paste address next to deploy button and click deploy
8. Copy NumApp contract address, open Num contract, paste next to authorize and click button

Noteworthy:

- NumApp should not work before being authorized
- To change App contract, create new App contract, deploy in the same way, authorize it and deauthorize previous

Comments and suggestions are welcome.

> Join Coinmonks [Telegram group](https://t.me/joinchat/EPmjKpNYwRMsBI4p) and learn about crypto trading and investing

#### Also, Read

- What is a [Flash loan](https://blog.coincodecap.com/what-are-flash-loans-on-ethereum)?
- The Best [Crypto Trading Bot](https://medium.com/coinmonks/crypto-trading-bot-c2ffce8acb2a) | [Grid Trading](https://blog.coincodecap.com/grid-trading)
- [3Commas Review](https://medium.com/coinmonks/3commas-review-an-excellent-crypto-trading-bot-2020-1313a58bec92) | [Pionex Review](https://medium.com/coinmonks/pionex-review-exchange-with-crypto-trading-bot-1e459d0191ea) | [Coinrule review](https://blog.coincodecap.com/coinrule-review-a-perfect-trading-bot)
- [AAX Exchange Review](https://medium.com/coinmonks/aax-exchange-review-2021-67c5ea09330c) | [Deribit Review](https://medium.com/coinmonks/deribit-review-options-fees-apis-and-testnet-2ca16c4bbdb2) |[FTX Crypto Exchange Review](https://medium.com/coinmonks/ftx-crypto-exchange-review-53664ac1198f)
- [NGRAVE ZERO review](https://medium.com/coinmonks/ngrave-zero-review-c465cf8307fc)
- [Bybit Exchange Review](https://medium.com/coinmonks/bybit-exchange-review-dbd570019b71) | [Bityard Review](https://blog.coincodecap.com/bityard-reivew) | [Interdax Review](https://blog.coincodecap.com/interdax-review)
- [3Commas vs Cryptohopper](https://medium.com/coinmonks/3commas-vs-pionex-vs-cryptohopper-best-crypto-bot-6a98d2baa203)
- The Best Bitcoin [Hardware wallet](https://medium.com/coinmonks/the-best-cryptocurrency-hardware-wallets-of-2020-e28b1c124069?source=friends_link&sk=324dd9ff8556ab578d71e7ad7658ad7c) | [BitBox02 Review](https://medium.com/coinmonks/bitbox02-review-your-swiss-bitcoin-hardware-wallet-c36c88fff29)
- [Ledger vs Ngrave](https://blog.coincodecap.com/ngrave-vs-ledger)
- [Crypto Copy Trading Platforms](https://medium.com/coinmonks/top-10-crypto-copy-trading-platforms-for-beginners-d0c37c7d698c) | [Bityard copy trading](https://blog.coincodecap.com/bityard-copy-trading)
- [ledger nano s vs x](https://blog.coincodecap.com/ledger-nano-s-vs-x)
- [Vauld Review](https://blog.coincodecap.com/vauld-review) | [YouHodler Review](https://medium.com/coinmonks/youhodler-4-easy-ways-to-make-money-98969b9689f2) | [BlockFi Review](https://medium.com/coinmonks/blockfi-review-53096053c097)
- The Best [Crypto Tax Software](https://medium.com/coinmonks/best-crypto-tax-tool-for-my-money-72d4b430816b) | [CoinTracking Review](https://medium.com/coinmonks/cointracking-review-a-reliable-cryptocurrency-tax-software-5114e3eb5737)
- Best [Crypto Lending Platforms](https://medium.com/coinmonks/top-5-crypto-lending-platforms-in-2020-that-you-need-to-know-a1b675cec3fa)
- [Ledger Nano S vs Trezor one vs Trezor T vs Ledger Nano X](https://blog.coincodecap.com/ledger-nano-s-vs-trezor-one-ledger-nano-x-trezor-t)
- [BlockFi vs Celsius](https://medium.com/coinmonks/blockfi-vs-celsius-vs-hodlnaut-8a1cc8c26630) | [Hodlnaut Review](https://blog.coincodecap.com/hodlnaut-review)
- [Bitsgap review](https://medium.com/coinmonks/bitsgap-review-a-crypto-trading-bot-that-makes-easy-money-a5d88a336df2) | [Quadency Review](https://medium.com/coinmonks/quadency-review-a-crypto-trading-automation-platform-3068eaa374e1)
- [Ellipal Titan Review](https://medium.com/coinmonks/ellipal-titan-review-85e9071dd029) | [SecuX Stone Review](https://blog.coincodecap.com/secux-stone-hardware-wallet-review)
- [BlockFi Review](https://medium.com/coinmonks/blockfi-review-53096053c097) | Earn up to 8.6% interests in your Crypto
- [DEX Explorer](https://explorer.bitquery.io/ethereum/dex) and [Blockchain APIs](https://explorer.bitquery.io/graphql)
- [Crypto arbitrage](https://medium.com/coinmonks/crypto-arbitrage-guide-how-to-make-money-as-a-beginner-62bfe5c868f6) guide: How to make money as a beginner
- Best [Crypto Charting Tool](https://medium.com/coinmonks/what-are-the-best-charting-platforms-for-cryptocurrency-trading-85aade584d80)
- What are the [best books to learn about Bitcoin](https://medium.com/coinmonks/what-are-the-best-books-to-learn-bitcoin-409aeb9aff4b)?

> [Get Best Software Deals Directly In Your Inbox](https://medium.com/coinmonks/newsletters/coinmonks)

[![](https://cdn-images-1.medium.com/max/584/1*BoDnKUyK8p4hitHAJZ5Pdw.png)](https://medium.com/coinmonks/newsletters/coinmonks)

* * *