0

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...

  • 1
    The typical solution is to log an event from the transaction and then look at it when you fetch the transaction receipt. – user19510 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
| improve this answer | |

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