Creating upgradeable smart contracts using contract factory


#1

Hi, I’m playing around with ZeppelinOS and I’m trying do use it with simple contract factory (using App contract).
I have MyContract.sol that works as contract factory and creates NewContract.sol

MyContract.sol:

pragma solidity ^0.4.24;

import "zos-lib/contracts/Initializable.sol";
import "zos-lib/contracts/application/App.sol";

contract MyContract is Initializable {
App private app;

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

function createNewContract() public returns(address) {
    return app.create("zos-fact", "NewContract", '0x69E3a4A7Ff6C1AEff4B096E4A6CF4d094D195a5A');
}

}

NewContarct.sol:

    pragma solidity ^0.4.24;

import "zos-lib/contracts/Initializable.sol";

contract NewContract is Initializable {

    uint256 public x;

    function initialize() initializer public {
        x = 10;
    }

    function setNumber(uint256 _x) public returns (bool) {
        x = _x;
    }

}

I have published my project to use App as admin of the proxies.
When I try to create new upgradeable contract on the fly I got error:

truffle(ganache)> myContract.createNewContract()
Error: VM Exception while processing transaction: revert

Do you have any ideas what a problem might be? I would be grateful for your advices


#2

Hello @paulinablaszk! Thanks again for posting here :slight_smile:

Hmm, I’m not the most informed on ZeppelinOS so maybe @spalladino can help out? We’re at ETHDenver right now so apologies if it takes a moment for him to respond :smiley:


#3

Hi @IvanTheGreatDev , thank you, no prob :slight_smile:


#4

@IvanTheGreatDev Now I see I’ve posted it in the wrong place so I will move it to “Smart contract development”


#5

It’s fine here! The issue might be ZeppelinOS specific!


#6

Hey @paulinablaszk! Have you run zos add NewContract and zos push on the corresponding network, so the App has registered the NewContract implementation? Does it work fine if you run zos create NewContract directly? And if all of the above fails, can you upload your project somewhere, so we can help in troubleshooting it? Thanks!


#7

Hi @spalladino. Thanks for your response. Yes, I’ve added and pushed NewContract. zos create NewContract also works fine. I uploaded my project here https://github.com/paulinablaszk/zos-fact


#8

Hey @paulinablaszk! The issue that is causing the REVERT is in https://github.com/paulinablaszk/zos-fact/blob/master/contracts/MyContract.sol#L14. There, App#create is being called with 3 params (package name, contract name, and an admin address), which corresponds to the App interface in v2.2. However, in your project you have v2.1 as a dependency, where the App interface is slightly different. In 2.1, create takes 3 params: package name, contract name, and the data that will be forwarded to the contract upon initialization. The admin address you are supplying is actually being parsed as that data, is sent to the contract, and thus fails.

TL;DR: You should either upgrade to zos and zos-lib v2.2 (recommended) or change the call to create by removing the last 0x69E3a4A7Ff6C1AEff4B096E4A6CF4d094D195a5A parameter.

Hope this helps! Cheers!


#9

Thank you very much @spalladino!


#10

I have one more question connected with this topic. I upgraded my zos and zos-lib to 2.2 but now MyContract.sol does not compile because of the create function. I am getting an error:

TypeError: Wrong argument count for the function call: 3 arguments given but expected 4.

Is it correct behavior when the 4th param data is optional?

Update:
I tried to put as data first 4 bytes of the Keccak hash of the signature initialize() and function app.create() has returned some address(?) but NewContract wasn’t deployed to the network
truffle(ganache)> contract.methods.createNewContract("zos-fact", "NewContract", "0x69E3a4A7Ff6C1AEff4B096E4A6CF4d094D195a5A", "0x8129fc1c").call() '0xD6C3A17f91D873352E882315269c1183278a96Ae'

Thanks


#11

Hey Paulina! I’m gonna go ahead and tag @spalladino because he’ll know more to help you :slight_smile:


#12

Greetings @spalladino,

The following is the content of my zos.json

{
  "zosversion": "2",
  "name": "TheFaustFlick",
  "version": "0.1.0",
  "contracts": {},
  "dependencies": {
    "openzeppelin-eth": "^2.1.3"
  }
}

Since I already initialized my project with zos init TheFaustFlick, could you please point to me the documentation on how do I properly upgrade zos and zos.lib to the latest version?

g.a.


#13

Hi @jaureguino, I’ve used
npm install zos@latest
and
npm install zos-lib@latest

Or you can choose any other from “Versions” tab here:



#14

Thanks a lot @paulinablaszk,

I just used both commands and they worked perfectly. However, the content of my zos.json file remains the same, is that ok? I am new on this, hence my basic questions… :flushed:


#15

@jaureguino No problem, nice to help :slight_smile:
In zos.json you have:

The documentation says: The field zosversion indicates the major version of ZeppelinOS you are using
So it doesn’t change because it can by only “1” or “2” (without detailed versions).

and "openzeppelin-eth": "^2.1.3" is OpenZeppelin EVM package - it is not the same as zos-lib. You should find info about zos-lib version in your package.json file.


#16

@paulinablaszk

Thank you so much for making it all clear for me, you are very kind. :+1:

Cheers and keep on coding!

g.a.


#17

How did you do that? After linking the openzeppelin-eth evm package, my app instance does not register the implementation addresses and thus i cannot use
app.create("openzeppelin-eth", "StandaloneERC20", msg.sender, abi.encode(...))

app.getImplementation("openzeppelin-eth", "StandaloneERC20")
returns ‘0x0000000000000000000000000000000000000000’

The documentation under https://docs.zeppelinos.org/docs/writing_contracts.html#creating-new-instances-from-your-contract-code states:

An advanced alternative, if you need to create upgradeable contracts on the fly, is to keep an instance of your ZeppelinOS App in your contracts.

But how? I’m out of ideas :frowning:


#18

Hi @imbenwolf, did you use:
zos push --deploy-dependencies? (–deploy dependencies is needed when you use openzeppelin-eth on your local network)
and then zos publish ?

You can also check new example on zos github: Creating instances from solidity . It was very helpful for me when I was trying to create an upgradeable smart contract using factory


#19

Hi @paulinablaszk

Thank you!

That was the piece I was missing. The example also helped a lot :smiley:


#20

@imbenwolf great :slight_smile: It was nice to help