Getting the address of a contract deployed by another contract
Asked Answered
L

2

17

I am trying to deploy a contract from another factory contract and then return the address of the newly created contract. The address it returns however is the transaction hash not the contract address. I believe this is because the contract is not yet mined when the address is returned. When I deploy a contract using the web3 deploy it seems to wait until the contract is deployed before outputting the address.

The factory contract:

contract Factory {
mapping(uint256 => Contract) deployedContracts;
uint256 numContracts;
function Factory(){
    numContracts = 0;
}

function createContract (uint32 name) returns (address){
    deployedContracts[numContracts] = new Contract(name);
    numContracts++;
    return deployedContracts[numContracts];
}}

This is how I am calling the createContract function.

factory.createContract(2,function(err, res){
        if (err){
            console.log(err)
        }else{
        console.log(res)
        }
    });
Lunarian answered 14/2, 2017 at 15:50 Comment(0)
B
37

Consider the below example. There are a number of ways you can get the address of the contract:

contract Object {

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

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

1 Store the Address and Return it:

Store the address in the contract as an attribute and retrieve it using a normal getter method.

contract ObjectFactory {
    Object public theObj;

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

2 Call Before You Make A Transaction

You can make a call before you make a transaction:

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

Once you have the address perform the transaction:

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

3 Calculate the Future Address

Otherwise, you can calculate the address of the future contract like so:

var ethJsUtil = require('ethereumjs-util');
var futureAddress = ethJsUtil.bufferToHex(ethJsUtil.generateAddress(
      contractFactoryAddress,
      await web3.eth.getTransactionCount(contractFactoryAddress)));
Baccy answered 23/2, 2017 at 13:19 Comment(3)
Where is the address var used in #2 ?Rosena
The address var in #2 is the new contract address, so you can do what ever you want to do with it. Probably save it somewhere.Baccy
Using approach #1 I'm getting back an address that does not represent the child object. What is possibly causing this error?Pub
G
3

We ran across this problem today, and we're solving it as follows:

In the creation of the new contract raise an event.

Then once the block has been mined use the transaction hash and call web3.eth.getTransaction: http://web3js.readthedocs.io/en/1.0/web3-eth.html#gettransaction

Then look at the logs object and you should find the event called by your newly created contract with its address.

Note: this assumes you're able to update the Solidity code for the contract being created, or that it already calls such an event upon creation.

Ginoginsberg answered 3/5, 2018 at 18:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.