2

I have the following code, which is malfunctioning, to create a payable contract from another contract.

pragma solidity ^0.4.16;

Contract Factory {
    uint contractCount = 0;
    mapping(uint => MyContract) public myContracts;

    function createContract(uint money) external payable {
        require(msg.value >= money);
        contractCount++;
        // the following line fails
        myContracts[contractCount] = new MyContract(money);
    }
}

Contract MyContract {
    uint money;

    function MyContract(uint _money) {
        require(msg.value >= _money);
        money = _money;
    }
}

I am using Remix IDE. I can create an instance of Factory without a problem, however, it fails to create a new MyContract instance when I try createContract(money). I suspect it is because the way to call new MyContract() is not transferring any value and thus fails the require(msg.value >= _money) in MyContract constructor.

So how do I create an instance of a payable constructor from a contract?

3tbraden
  • 667
  • 1
  • 10
  • 21

2 Answers2

6

First you need to make your constructor payable for this to work.

I suspect it is because the way to call new MyContract() is not transferring any value and thus fails the require(msg.value >= _money) in MyContract constructor.

You are right. Solidity's syntax for doing this is somewhat unusual. Take a look at this section of the documentation.

child = (new B).value(10)(); //construct a new B with 10 wei

If the constructor takes arguments, they go in the final parentheses attached to the new expression.

In your example it would look like this:

myContracts[contractCount] = (new MyContract).value(msg.value)(money);
Fischa7
  • 181
  • 3
6

For those of you still looking to solve this. .value has been deprecated and the example using the new syntax would look like this:

myContracts[contractCount] = (new MyContract){value: msg.value}(money);
Andras2000
  • 61
  • 1
  • 1