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.

2
  • 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. Sep 20, 2016 at 23:06
  • good question. All the normal design patterns (e.g. factories) need to be well documented for Solidity
    – Paul S
    Sep 21, 2016 at 20:30

2 Answers 2

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)));
2
  • 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, 2016 at 19:05
  • I updated the answer to reflect the fact that the second line receives the txHash. My oversight. Sep 21, 2016 at 19:18

Your Answer

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

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