6

I'm trying to develop a contract that creates a contract (factory/worker, faucet pattern). Think my issue may be with the tools I'm using:

  • testrpc (local blockchain)
  • Remix Browser Solidity (connected to testrpc)
  • MetaMask (for watching transactions, balances etc)
  • truffle (for deployment/migration)

When I deploy my contracts using truffle, I can see the transaction and contract address immediately in testrpc:

Transaction: 0x153a84e6478df590deb21a95cd9042dd5820e838ac14986fb47a8b13df34bd1b Contract created: 0x7a5812ba512df41432ed408ed0a1b266aa8a27dc Gas usage: 0x094d2a Block Number: 0x49 Block Time: Tue Mar 21 2017 19:30:56 GMT+0000 (GMT)

However, when I get my Factory contract to create a contract I can only get the transaction - yet using Event's for logging I can see an address, but can't interact with it. Also testrpc reports the transaction but no contract address:

Transaction: 0x2984356f7ea77ac86f6dee92472736a682061fbeab7de335bc4a6aa7ed66462b Gas usage: 0x0532a9 Block Number: 0x4c Block Time: Tue Mar 21 2017 19:30:59 GMT+0000 (GMT)

It seems that testrpc isn't mining, I've tried adding the switch -b 1, but still same effect. Also I've tried the demo from embark, when I fire it up the framework deploys contracts successfully, as with truffle, but when I try their dapp transactions get created but never mined.

Factory contract

pragma solidity ^0.4.2;

import './Bar.sol';

contract Foo{

    function createBar(){

      Bar bar = new Bar();
    }
}

Worker / Child contract

pragma solidity ^0.4.2;

contract Bar{

}

The issue also persists with embark framework, where the frame work can create contracts but I can't. Seems like their not being mined?

1
  • When a contract creates a contract, there's no separate transaction- if you got an event with an address, then the child contract was definitely deployed. This sounds like a Solidity issue, not an issue with the toolchain, but without more detailed code there's not much else I can tell you Commented Mar 22, 2017 at 23:00

3 Answers 3

3

Someone may improve this answer but the solution was simple...

testrpc doesn't mine embark doesn't mine

geth does mine, but I couldn't get it working - namely a bug with --fast. Parity was the solution.

Sync to testnet (ropsten) with Parity, has web interface to check status. Then mine with Parity, doesn't take long.

Then add a network to truffle:

truffle.js ... "ropsten": { network_id: 3, host: "localhost", port: 8545, from: "$address_from_parity_wallet" }, ...

Now whilst parity is running, run truffle migrate --reset.

Seems testrpc, remix and embark are excellent for general building but for lower level work Parity and the testnet is the job... at the moment (I expect the tools will improve and testnet will be more staging/preprod)

1

From my understanding the problem lies in the "nested" contract structure. If you create a contract with new() the situation is clear - There is one transaction to the address 0x0, creating exactly one contract. So the EVM can set the "contractAddress" field in the transaction receipt.

But when you deal with a factory the situation changes. The transaction initiating the contract creation is not sent to 0x0, but to the factory, so for the EVM it looks like an ordinary function, so the contractAddress field is not set.

Thinking further it get's even more complex. What happens if contract Bar would create another contract FooBar in it's constructor? Now you end up with one transaction to the Factory that implicitly creates 2 new contracts. So it is impossible to set a valid contractAddress field.

From my (limited) experience the only way to get to the address of a contract created by a factory is by having the factory emit an event with the address of the new contract and listening to that event.

0

I might be missing some information here, but if your contract is emitting an event with a valid address in it (e.g not 0x0000...0000), your contract is deployed.

Do you have the ABI for the child contract? When you have the address, you'll need the ABI to get yourself an instance of the contract from web3. This will look something like:

var Bar = web3.eth.contract(abi).at(eventAddress);

Where abi is your json ABI, and eventAddress is the address produced by the event emitted by your parent contract.

Generally, for non-top-level contracts, you can't rely on the frameworks (e.g. embark/truffle) to automatically configure the interfaces for them, since they don't usually directly accommodate that use case. You'll likely need to fall back to using web3 directly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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