1

The callback function for web3.eth.contract.new doesn't get called twice. After successfully deploying a contract, I do not receive the result.contractAddress (which is supposed to get set after the the contract gets mined into the chain within a second callback function call).

I found several threads, discussions and so on that this is a known issue within the community or at least for several people. I read the first 10 pages of google search results and most of the official 0.xx web3js API documentation already, without solving the problem fundamentally.

https://github.com/ethereum/web3.js/issues/500 -> really waiting for 1.0 to get deployed!

Meanwhile I wrote a little (quick and dirty) fix for it, but I would love to implement it properly and scalable:

//deploy contract defined in remix
//================================================
var contract = myweb3.eth.contract(abi);

var gas = 47000000;

var  params = {
   from: "0xe97bab7a8b9A86AA1174Df9f5559398daD795f4c",
   data: bytecode,
   gas: gas
};

var constructor_param = 10;

var deployedContract = 
contract.new(constructor_param,params,function(error,result){
if (!error) {
    // never happens
    if (result.address) {
        // gets set in the second call
        console.log("contract address: " + result.address);
        console.log(createEtherscanIoUrl('address', result.address));

        // should work, callback doesnt get called a 2nd time :(
        // myweb3.eth.getTransactionReceipt(deployedContract.transactionHash, function(error, result) {
        //     if(error) {
        //         console.log(error);
        //     }
        //     else {
        //         console.log("receipt: " + result);
        //     }
        // });

    } else {
        // gets set in the first call
        console.log("contract transaction hash: " + result.transactionHash);
        console.log(createEtherscanIoUrl('tx', result.transactionHash));

        myweb3.eth.getTransaction(result.transactionHash, function(error, result) {
            if(error) {
                console.log(error);
            }
            else {
                console.log("transaction: " + result);
            }
        });

        pollTransactionReceipt(result.transactionHash);
    }
} else {
    console.log("error contract.new: " + error);
}
});

/**
 * Create the etherscan link
 */
 function createEtherscanIoUrl(type,hashOrNumber){

var etherscanBaseUrl='https://ropsten.etherscan.io/';

var url = etherscanBaseUrl;
if(type === 'tx'){
    url += 'tx/'+hashOrNumber;
} else if(type === 'block'){
    url += 'block/'+hashOrNumber;
} else if(type === 'address'){
    url += 'address/'+hashOrNumber;
}
return url;
}


function pollTransactionReceipt(transactionHash) {
var delay = 2000;

var receipt = myweb3.eth.getTransactionReceipt(transactionHash, function(error, result) {
    if(error) {
        console.log("error:  " + error);
    }
    else {
        console.log("receipt: " + result);
    }
});


//TODO whats the receipt var meanwhile exactly? NULL no object whatever....

if(typeof receipt === "undefined" || receipt.contractAddress === null) {
    setTimeout(function() {
        pollTransactionReceipt(transactionHash);
    }, delay);
}
else {
    console.log(receipt.contractAddress);
}
}

It's basically working BUT the exit condition is bugged tough.

I tried several checks and combinations for the condition.

The docs are stating that null is received, but a simple check for:

"receipt === null" didn't do the job. The recursion does not stop, even I receive an object after the contract gets mined correctly.

https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethgettransactionreceipt

Part of the console output:

...

index.js:167 https://ropsten.etherscan.io/tx/0xb98f61b51d89041f630b7cfdfac841124cacb4bad5f71dc07b7078f451a5d654

index.js:212 receipt: null

index.js:174 transaction: [object Object]

475 index.js:212 receipt: null

14908 index.js:212 receipt: [object Object]

...

475 times as I tested it with alot of transactions and it took some time to get the last one processed. And 14908 times receiving a receipt object as I fall asleep while waiting and the condition didn't stop.

Any hints, tips or advises to my code or workaround appreciated. Getting the problem solved fundamentally would still be awesome tough.

Greetings from cold Austria,

Mario

1
  • As I'm very new to Blockchain and Ethereum yet, is it possible to handle this issue with filters/watch/events? It seems just a bit overwhelming to do so, without actually having the contract address. Commented Feb 27, 2018 at 15:02

1 Answer 1

1

I fixed the workaround now too. And it works as "expected" (besides not getting called if the contract gets deployed).

pollTransactionReceipt gets called when the send transaction of contract.new was successful. It polls the transaction receipt until result is given:

contract.new(constructor_param,params,function(error,result){
if (!error) {
    // never happens!
    if (result.address) {
        // gets set in the second call
        console.log(createEtherscanIoUrl('address', result.address));
    } else {
        // gets set in the first call
        console.log(createEtherscanIoUrl('tx', result.transactionHash));
        // new white magic!
        pollTransactionReceipt(result.transactionHash);
    }
} else {
    console.log("error contract.new: " + error);
}
});

pollTransactionReceipt:

function pollTransactionReceipt(transactionHash) {
var delay = 1000;

myweb3.eth.getTransactionReceipt(transactionHash, function(error, result) {
    if(error) {
        console.log("error executing getTransactionReceipt:  " + error);
    }
    else {
        if(result === null) {
            setTimeout(function() {
                pollTransactionReceipt(transactionHash);
            }, delay);
        }
        else {
            console.log(createEtherscanIoUrl('address', result.contractAddress));
        }
    }
});
}

Your Answer

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

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