Smart contract upgrade

I have an Ethereum smart contract which works on Ganache test network and I want to add Zeppelin to it so that I can make it upgradable.
I have gone through the tutorial and managed to implement the Initialise in the current contract.
I am able to run the UI which will interact with the smart contract but I am getting the following error when trying to call functions from the smart contract.

Contract has not been deployed to detected network (network/artifact mismatch)

1 Like

Hi @techbro965
Which tutorial are you following?
What version of ZeppelinOS (zos --version), Truffle (truffle version) are you using?
Are you able to share your contract?

Hi @abcoathup

zos version => 2.3.0
truffle version => 5.0.19
Tutorial I am following How to Write Upgradeable Smart Contracts with Truffle ^5.0 and ZeppelinOS ^2.0

Below is the contract I am using, I have tried multiple times to create a new Gacnahe workspace but it still returns the same error. In the Ganache UI, I am seeing the gas reduced for the first account and in the logs, it states that the contact has been created, but I still get that error when trying to interact with the contract from UI.

pragma solidity ^0.5.0;
import '../node_modules/zos-lib/contracts/Initializable.sol';
/**
 * Contract to store the mileage of a vehicle 
 */
contract VehicleService is Initializable  {
    struct Vehicle {
        string vin;
        address owner;
        uint kilometers;
        string ipfsHash;
    }

    mapping (string => Vehicle) vehicles;

    event Creation(address indexed from, string vin);
    
    event Transfer(address indexed from, address indexed to, string vin);
    
    // constructor () public {}//this will not work with ZeppelinOS
    
    /**
     * Create new vehicle in mapping. 
     * If vehicle already exists => transaction fail and burns gas.
     */
    function createVehicle(string memory vin, string memory ipfsHash) public {
        assert(vehicles[vin].owner == address(0x0));
        vehicles[vin].vin = vin;
        vehicles[vin].owner = msg.sender;
        vehicles[vin].kilometers = 0;
        vehicles[vin].ipfsHash = ipfsHash;
        emit Creation(msg.sender, vin);
    }
    

    /**
    * Update the mileage of the vehicle. 
    * If the mileage entered is smaller than the previous mileage stored => transaction fail and burns gas.
    */
    function updateKilometers(string memory vin, uint kilometers) public {
        Vehicle storage transferObject = vehicles[vin];
        assert(transferObject.owner == msg.sender); 
        assert(transferObject.kilometers < kilometers);
        transferObject.kilometers = kilometers;
    }
    
    /**
     * Returns the details of the vehicle
     */
    function getVehicle(string memory vin) public view returns(address owner, uint kilometers, string memory ipfsHash) {
        owner = vehicles[vin].owner;
        kilometers = vehicles[vin].kilometers;
        ipfsHash = vehicles[vin].ipfsHash;
    }
    
    
}
1 Like

I used the following tutorial as well as the tutorial you used.

I used the following steps to deploy your contract:

Install Truffle globally (suggest v5.0.20)
npm install -g truffle

Create your project directory
mkdir vs
cd vs

Use npm to create a package.json file
npm init -y

Install ZeppelinOS in your project folder
npm install zos

Initialize the ZeppelinOS project
npx zos init vs

save VehicleService.sol into contracts directory. Please note I changed the import statement from import '../node_modules/zos-lib/contracts/Initializable.sol'; to import "zos-lib/contracts/Initializable.sol";

pragma solidity ^0.5.0;
import "zos-lib/contracts/Initializable.sol";
/**
 * Contract to store the mileage of a vehicle
 */
contract VehicleService is Initializable  {
    struct Vehicle {
        string vin;
        address owner;
        uint kilometers;
        string ipfsHash;
    }

    mapping (string => Vehicle) vehicles;

    event Creation(address indexed from, string vin);

    event Transfer(address indexed from, address indexed to, string vin);

    // constructor () public {}//this will not work with ZeppelinOS

    /**
     * Create new vehicle in mapping.
     * If vehicle already exists => transaction fail and burns gas.
     */
    function createVehicle(string memory vin, string memory ipfsHash) public {
        assert(vehicles[vin].owner == address(0x0));
        vehicles[vin].vin = vin;
        vehicles[vin].owner = msg.sender;
        vehicles[vin].kilometers = 0;
        vehicles[vin].ipfsHash = ipfsHash;
        emit Creation(msg.sender, vin);
    }

    /**
    * Update the mileage of the vehicle.
    * If the mileage entered is smaller than the previous mileage stored => transaction fail and burns gas.
    */
    function updateKilometers(string memory vin, uint kilometers) public {
        Vehicle storage transferObject = vehicles[vin];
        assert(transferObject.owner == msg.sender);
        assert(transferObject.kilometers < kilometers);
        transferObject.kilometers = kilometers;
    }

    /**
     * Returns the details of the vehicle
     */
    function getVehicle(string memory vin) public view returns(address owner, uint kilometers, string memory ipfsHash) {
        owner = vehicles[vin].owner;
        kilometers = vehicles[vin].kilometers;
        ipfsHash = vehicles[vin].ipfsHash;
    }
}

This contract imports another contract from the zos-lib package, so we have to install it:
npm install zos-lib

Add the contract to the project
npx zos add VehicleService

run ganache (I tend to use ganache-cli and haven’t played much with ganache GUI version)

Change the port in truffle-config.js so it matches ganache (Ganache GUI 7545)

module.exports = {
  networks: {
    local: {
      host: 'localhost',
      port: 7545,
      gas: 5000000,
      gasPrice: 5e9,
      network_id: '*',
    }
  }
}

Starts a session to work with a desired network
npx zos session --network local --from ADD_ADDRESS_OF_SECOND_GANACHE_ACCOUNT
Accept defaults for timeout and expiration time

Deploy the project
npx zos push

Create an upgradeable instance for the logic contract (your contract doesn’t take any parameters in an Initialize function)
npx zos create VehicleService

Interact with your contract e.g. using truffle console

truffle console --network local

vs = await VehicleService.deployed()
await vs.createVehicle("VIN1", "Qmabc")
await vs.getVehicle("VIN1")
1 Like

@abcoathup Thanks a lot for the explanation, I got it to work using the ganache cli network and can also manage the data from browser.

I have a question which I got confused.

As you noted in my contract I don’t have an Initialize function does this mean I cannot update/upgrade the other functions such as createVehicle? for example, I want to add a new field to the vehicle structure or I want to make the kilometres to 5, can this be done the way the contract is set up?

2 Likes

Hi @techbro965, initialize function just replaces the constructor in ZeppelinOS. You don’t have to use a constructor in your smart contract if there is no need to. So it shouldn’t affect on upgradeability of your contract in zos.

3 Likes

ok understood, Thanks a lot

2 Likes

Hi @techbro965 glad you got it working. I have marked my answer as the solution.

Thanks @paulinablaszk for explaining initialize

More information on initializers can be found in the documentation:

Moved to #support:zeppelinos

1 Like