4

I am having problems in accessing the address of a new contract generated within another contract acting as Factory. My code:

contract Object {

    string name;
    function Object(String _name) {
        name = _name
    }
}

contract ObjectFactory {
    function createObject(string name) returns (address objectAddress) {
        return address(new Object(name));
    }
}

when I compile and execute the method createObject(''), I expect to be returned the address of the new contract. Instead, I receive the hash of the transaction. I use Web3 to execute the function:

var address = web3.eth.contract(objectFactoryAbi)
                  .at(contractFactoryAddress)
                  .createObject("object", { gas: price, from: accountAddress });

I tried also to modify the function to store the address in an array, returning the length of the array, and then retrieve it at a later time, with the same results: always the transaction hash is returned.

Any light on this is welcome.

  • If you stored the address in an array in Solidity, it is not the hash of the transaction. Show the code of the array thingy. – Xavier Leprêtre B9lab Sep 20 '16 at 23:06
  • good question. All the normal design patterns (e.g. factories) need to be well documented for Solidity – Paul S Sep 21 '16 at 20:30
1

Often the contract itself is going to need to store the address for future use. So just store the address in the contract as an attribute, and retrieve it from outside the contract using the usual methods (e.g. call to the default getter ABI if you declare it public scope), after the transaction has been completed: (note, untested pseudo code, but I've done similar stuff a few times)

contract ObjectFactory {
    Object public theObj;

    function createObject(string name) returns (address objectAddress) {
        theObj = address(new Object(name));
        return theObj;
    }
}
1

You should make a call before you make a transaction:

var address = web3.eth.contract(objectFactoryAbi)
                  .at(contractFactoryAddress)
                  .createObject.call("object");

Now that you have the address, yes, you do the transaction:

var txHash = web3.eth.contract(objectFactoryAbi)
                  .at(contractFactoryAddress)
                  .createObject("object", { gas: price, from: accountAddress });

Otherwise, you can calculate the address of the future contract like so (code not verified):

var ethJsUtil = require('ethereumjs-util');
var futureAddress = ethJsUtil.bufferToHex(ethJsUtil.generateAddress(
      contractFactoryAddress,
      await web3.eth.getTransactionCount(contractFactoryAddress)));
  • thanks a lot.I did some tries, and actually I found that the other way round works: web3.eth.contract(objectFactoryAbi).at(contractFactoryAddress).createObject("object", { gas: price, from: accountAddress }); returns the transaction id while web3.eth.contract(objectFactoryAbi).at(contractFactoryAddress).createObject.call("object") will return the actual result of the latest transaction – massi Sep 21 '16 at 19:05
  • I updated the answer to reflect the fact that the second line receives the txHash. My oversight. – Xavier Leprêtre B9lab Sep 21 '16 at 19:18

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.