0

This question already has an answer here:

from what I (quickly) looked up, payable functions do not return values to the web3 API.

In my particular use case, I have a 'Master' contract that serves as a factory for other contracts, and stores all contracts created in such way in an array.

How can I call something like master.createAnotherContract() and know the address of the newly created contract?

I think a function that gets the last contract in the array can deliver messed up results; creating the contract using the factory and reading the last contract would not be atomic...

marked as duplicate by Ismael, Roman Frolov, flygoing, Richard Horrocks, Luiz Soares Jan 17 '18 at 13:15

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    The typical solution is to log an event from the transaction and then look at it when you fetch the transaction receipt. – smarx Jan 15 '18 at 23:58
0

For this kind of scenario, I would use a Solidity event which is a great feature to return data from a transaction. Because of the asynchronous nature of the blockchain, a transaction / write operation (payable or not) doesn't return any data. However, you can trigger an event and read this event from a watcher.

Example:

I created two contracts A and B where A create B.

A.sol

pragma solidity ^0.4.18;

import './B.sol';

contract A {

   // Declare event
   event newContractB(address contractAddress);

   function createB() returns (){
       // Deploy a new contract B
       address addressB = new B(); 

       // Trigger event
       newContractB(addressB);
   }
}

B.sol

pragma solidity ^0.4.18;

contract B {
    // ...
}

Using Web3, you can define a filter of event to watch it:

var filter = web3.eth.filter({ romBlock: 0, toBlock: "latest" });
filter.watch(function (error, result) {
  console.log(JSON.stringify(result.data));
});

> "0x000000000000000000000000c7f1527fcf66a3c53d06299646e4a0e3bd8f6d17"

Using Truffle, you an directly get the event from the transaction receipt

var A = artifacts.require("./A.sol");

contract('A', function(accounts) {
    it("test", function() {

        var aInstance;

        A.deployed().then(function (instance) {
            aInstance = instance;

            aInstance.createB(5, {from: accounts[0]})
                .then(function (tx) {
                    console.log(tx.logs[0].args);


                }).catch(function (error) {
                    console.log(error);
                })
        })
    });
});

> { contractAddress: '0xc7f1527fcf66a3c53d06299646e4a0e3bd8f6d17' }

I pushed my example on GitHub, you can test via:

> truffle compile

> truffle migrate

> truffle test

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