Understanding `zos upgrade` ("Contract is up to date")

According to Documentation (https://docs.zeppelinos.org/docs/first.html), I tried out to upgrade a specific contract.

The contract was deployed, created and initialized on ropsten. Then I added two new functions for testing purposes and did zos upgrade.

However, nothing was upgraded. Obviously I miss something here?

$ zos upgrade --network ropsten
Using session with network ropsten, sender address 0x2353e45fF9613cFB05CC797E15cC37fd0d7F9658, timeout 123123 seconds
βœ“ Compiling contracts with Truffle, using settings from truffle.js file
All contracts are up to date
? Which instances would you like to upgrade? Choose by address
? Pick an instance to upgrade TokenVesting at 0x2344c3B39cE8a661453889A7c3b05338EbdEC995
? Do you want to call a function on the instance after upgrading it? No
Contract TokenVesting at 0x2344c3B39cE8a661453889A7c3b05338EbdEC995 is up to date.

"git diff" is my witness, that the particular contract has two new functions.

zos.ropsten.json:

"ncdt/TokenVesting": [
  {
    "address": "0x2344c3B39cE8a661453889A7c3b05338EbdEC995",
    "version": "v1.3.0",
    "implementation": "0x829AC1BE0448D78c5DD0A7b2B12a359795155b41",
    "admin": "0x9e78977F8a0EE5C30d8484627F9DD9b34e470556",
    "kind": "Upgradeable"
  }

I also tried to zos push, and it gives "all contracts are up to date" either.
I am using zos 2.4. Any hints available for me?

Okay, since we had to change the Symbol of the token, I tested upgradability directly on Main net.

I first changed the code of the contract (symbol-function), then did zos push:

βœ“ Contract NCDToken deployed
All contracts have been deployed

Only the modified contract was deployed again, as expected.

zos update NCDToken

βœ“ Instance upgraded at 0x9D38d8bC4993fF4E8574b807290e8eF0676E1B98. Transaction receipt: 0xa5d1981f0d24b59e82a90b82d02ad3f6902dc8444961b13c34b7e472693dd49b

But when I execute the symbol()-function on the token instance, it still prints the old value, not the new.

What have I missed here?

1 Like

Hi @itinance

I recommend testing any upgrades on a local testnet and then testing on a public testnet prior to upgrading on mainnet.

Once a contract has been initialized you can't initialize the same initialize function again as it is protected by the initializer modifer (so it is only called once).

To change the symbol you could create a new whole new contract or you could modify the contract and upgrade to display the new symbol.

You could override the symbol function in your token contract. See below for sample code and manual local testing of the upgrade.

    function symbol() public view returns (string memory) {
        return "TKN2";
    }

If you add new state variables these would need to be initialized, and any initializer function would need to be protected so that it could only be run once. See an example I did recently:

_symbol is private in ERC20Detailed.sol and there are no internal setters so you can't change the value once set.


I created some sample code to show the process for updating the token symbol.

Token.sol (original)

pragma solidity ^0.5.0;

import "zos-lib/contracts/Initializable.sol";
import "openzeppelin-eth/contracts/token/ERC20/ERC20Detailed.sol";
import "openzeppelin-eth/contracts/token/ERC20/ERC20Mintable.sol";

contract Token is Initializable, ERC20Detailed, ERC20Mintable {

    function initialize(address minter) public initializer {
        ERC20Detailed.initialize("Token", "TKN", uint8(18));
        ERC20Mintable.initialize(minter);
    }
}

zos create

$ npx zos create
βœ“ Compiled contracts with solc 0.5.10 (commit.5a6ea5b1)
? Pick a contract to instantiate Token
? Pick a network development
βœ“ Contract Token deployed
All contracts have been deployed
? Do you want to call a function on the instance after creating it? Yes
? Select which function * initialize(minter: address)
? minter (address): 0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1
βœ“ Setting everything up to create contract instances
βœ“ Instance created at 0x59d3631c86BbE35EF041872d502F218A39FBa150
0x59d3631c86BbE35EF041872d502F218A39FBa150

zos call

? Pick a network development
? Pick an instance Token at 0x59d3631c86BbE35EF041872d502F218A39FBa150
? Select which function symbol()
βœ“ Method 'symbol()' returned: TKN
TKN

Token.sol upgraded with overriden symbol

pragma solidity ^0.5.0;

import "zos-lib/contracts/Initializable.sol";
import "openzeppelin-eth/contracts/token/ERC20/ERC20Detailed.sol";
import "openzeppelin-eth/contracts/token/ERC20/ERC20Mintable.sol";

contract Token is Initializable, ERC20Detailed, ERC20Mintable {

    function initialize(address minter) public initializer {
        ERC20Detailed.initialize("Token", "TKN", uint8(18));
        ERC20Mintable.initialize(minter);
    }

    function symbol() public view returns (string memory) {
        return "TKN2";
    }
}

zos upgrade

$ npx zos upgrade
? Pick a network development
βœ“ Compiled contracts with solc 0.5.10 (commit.5a6ea5b1)
- Variable _minters (MinterRole) contains a struct or enum. These are not automatically checked for storage compatibility in the current version. See https://docs.zeppelinos.org/docs/writing_contracts.html#modifying-your-contracts for more info.
βœ“ Contract Token deployed
All contracts have been deployed
? Which instances would you like to upgrade? Choose by name
? Pick an instance to upgrade Token
? Do you want to call a function on the instance after upgrading it? No
βœ“ Instance upgraded at 0x59d3631c86BbE35EF041872d502F218A39FBa150. Transaction receipt: 0xade55073206040afc9395a0e857243a80586473b080d648445a3fff21c6cf316

zos call

$ npx zos call
? Pick a network development
? Pick an instance Token at 0x59d3631c86BbE35EF041872d502F218A39FBa150
? Select which function symbol()
βœ“ Method 'symbol()' returned: TKN2
TKN2
1 Like

Thank you @abcoathup. My experience was different, but will give it a new try and report it here then.

1 Like

Hi @itinance how did you get on?

Thanks for asking, @abcoathup!

I have redeployed everything from scratch because upgrading the contract was not how I would expect the result ^^ All values were suddenly zero (decimals, name, symbol), balances and so on.

I think it need much more practice on my side to improve the process. Starting with my next token project, I will care for upgrading in the first place and write down here my experience later.

1 Like