0

I have a factory contract (Factory.sol) that creates new contracts (YourContract.sol). The createNewContract function in the factory defines some state variables that the new contract picks up in its constructor.

When I try to deploy my project in Truffle I'm unable to deploy YourContract.sol because of the undefined variables ("Invalid number of parameters for "undefined". Got 0 expected 3!")

Question 1. Do I have to deploy YourContract.sol for my Factory.sol to work?

Question 2. Is there some way I can define the state variables in YourContract but still have them change with the new variables passed through the createNewContract function?

Factory.sol:

pragma solidity ^0.5.1;

import "./YourContract.sol";

contract Factory {

    //
    // Factory general info
    //    
    address Admin;

    constructor () public {
        Admin = msg.sender;
    }    

    function createNewContract(string memory Name, string memory Type, uint Fee) public returns(YourContract) {
        address YourContract = address(new YourContract(Name, Type, Fee));
    }

YourContract.sol:

pragma solidity ^0.5.1;

import "./Factory.sol";

contract YourContract {

    //
    // The state variables that per now are undefined
    //
    string public Name;
    string public Type;
    uint public Fee;
    address owner;

    //    
    // the constructor that pulls info from the function
    //
    constructor(string memory Name, string memory Type, uint Fee) public {
        owner = msg.sender;
        Name = Name;
        Type = Type;
        Fee = Fee;
    }
0

Question 1. Do I have to deploy YourContract.sol for my Factory.sol to work?

No. The factory will roll up the bytecode imported from YourContract.sol when you import it and when it sees new YourContact(). new implies that it will need a copy of the bytecode in order to deploy it. It will then look for it, which is why you import it.

Question 2. Is there some way I can define the state variables in YourContract but still have them change with the new variables passed through the createNewContract function?

It appears that you are. The state variable declarations define the layout and your constructor() accept arguments that are assigned to them.

The Factory also accepts arguments and passes to YourContract's constructor with address YourContract = address(new YourContract(Name, Type, Fee));.

From eyeballing this, it seems approximately correct but you have naming conflicts. YourContract is defined in contract YourContract and also in address YourContract ... so, is it an address or a type of contract?

There is an unnecessary import (circular?) in YourContract. The Factory does need to import YourContract so it knows what to deploy. YourContract does not need knowledge of the Factory. Remove `import "./Factory.sol";

Fix the Factory:

pragma solidity ^0.5.1;

import "./YourContract.sol";

contract Factory {

    //
    // Factory general info
    //    
    address Admin;

    constructor () public {
        Admin = msg.sender;
    }    

    function createNewContract(string memory Name, string memory Type, uint Fee) public returns(address) {
        YourContract newContract = new YourContract(Name, Type, Fee);
        return address(newContract);
    }
}

Hope it helps.

  • Hey @Rob! Thanks a lot for the answer. I didn't include all the code of createNewContract which is why it seems a bit weird. I'm mapping a struct that is passed all new addresses created by this function. And also pushing them into an address array. So the way you wrote it gives me all sorts of errors when I try to use newContract for variables that are supposed to be an address (error msg: "type contract newContract is not implicitly convertible to expected type address" and so on). Here is the code I have. – AndreG Apr 24 at 15:01
  • function createNewContract(string memory Name, string memory Type, uint Fee) public returns(address) { YourContract newContract = new YourContract(Name, Type, Fee); newContractDBs[newContract] = newContractDB(Name, Type, msg.sender, newContract, Fee); contractArray.push(newContract); return address(newContract); – AndreG Apr 24 at 15:03
  • When newContract is cast as type YourContract it picks up methods that are not part of a generic address. It is explicitly convertible with address(newContract). If you find yourself repeating that a lot, then address newContractAddress = address(newContract);. It helps to be explicit/consistent with variable names so you don't get confused about type (array of addresses, or array of contracts?). Consider contractArray.push(newContractAddress); – Rob Hitchens Apr 24 at 15:36
  • Thanks for upvoting and accepting the answer to the original question. ;-) – Rob Hitchens Apr 24 at 15:37
  • 1
    Definitely. Thank you so much for explaining how to convert the output of newContract into an address I can map and/or push into an array. These small hints make a big difference to me. – AndreG Apr 24 at 16:28
0

Question 1. Do I have to deploy YourContract.sol for my Factory.sol to work?

No, your factory contract just needs to know "what" to deploy and you do that by importing the YourContract.sol file.

Question 2. Is there some way I can define the state variables in YourContract but still have them change with the new variables passed through the createNewContract function?

Every variable is initialized to 0, there is no "undefined" variables in Solidity.

  • Thanks so much, @Eli. The answer to question 1 means I don't have to deal with the deployment problem in Truffle. But just for my understanding I guess my second question was asked in the wrong way seeing as I didn't know that there aren't any "undefined" variables in Solidity. I should have asked if there is any way to give the parameters missing without changing the constructor in YourContract.sol? Maybe passing them as a sort of temporary parameter in my Factory.sol somewhere? – AndreG Apr 24 at 14:38
  • I don't understand what you mean. Can you give an example? – Eli Drion Apr 24 at 14:41
  • Ah, sorry. I'll try with an example. – AndreG Apr 24 at 14:42
  • Calling the function called createNewContract lets me assign Name, Type and Fee which the constructor in the new contract then uses for its state variables. Could I for example assign Name = TempName, Type = TempType, Fee = 0 in the constructor of Factory.sol? Or in some other way? – AndreG Apr 24 at 14:47
  • I don't see why you couldn't – Eli Drion Apr 24 at 15:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.