10

I understand how the below web3js code block works, adapted from here:

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

But how does one save the contract address programmatically? One could, I suppose, open a file and persist it within the callback, but not that. =:)

And I don't believe the myContractReturned identifier helps us; given the asynchronous nature of JavaScript (not to mention the mining delay). How does one even use that?

It's kind of an academic question (because there's no guarantee an address will even be generated), but curious as to what friends in the community have done (or thought). Thank you!

--

var myContractReturned = MyContract.new(param1,param2, {
   from:mySenderAddress,
   data:bytecode,
   gas:gasEstimate},
   function(error, myContract){
     if(!error) {
        if(!myContract.address) {
            // Step-1: Runs on contract submission/deployment.
            console.log(myContract.transactionHash)
        } 
        else {
            // Step-2: Runs after contract is deployed.
            console.log(myContract.address)
        }

     }
  });
  • Thank you "@Mikko Ohtamaa" and "@Xavier Leprêtre B9lab" for your respective answers. Both are quite good answers and I encourage readers to view both! Xavier's answer reminds us that -- by pre-computing it -- we can know the Contract Address even before it is submitted. – NYCeyes Feb 1 '17 at 15:30
7

The contract's address is computed out of the deployer's address and the transaction nonce. You need not wait for the contract to be mined to get it.

In NodeJs, something like that will do:

var ethUtil = require('ethereumjs-util');

var currentNonce = web3.eth.getTransactionCount(myAccount);
var futureAddress = ethUtil.bufferToHex(ethUtil.generateAddress(myAccount, currentNonce));
// futureAddress is the address of the contract that you deploy below

var MyContract = web3.eth.contract(abiArray);
var contractInstance = MyContract.new([contructorParam1] [, contructorParam2], {data: '0x12345...', from: myAccount, gas: 1000000});

// Here you can confirm that its address is indeed the one you calculated earlier.

Don't forget to improve this demo-code by using asynchronous calls.

  • 1
    Too bad people who come to the accepted answer will believe that you cannot have the address before it has been mined. – Xavier Leprêtre B9lab Jan 31 '17 at 15:19
  • 1
    @"Xavier Leprêtre B9lab" True, and is why I updated my accepted answer, so people can see it. The accepted answer was changed since your above comment :) – NYCeyes Jan 4 at 20:56
10

The contract constructor will return a transaction hash where the contract is being deployed. The final contract address can be deterministically determined from deployer address and deployer address nonce (see another answer). This information is also available through web3.eth.getTransactionReceipt after the deployment transaction has been mined.

Note that you don't know if the contract deployment will success or fail before the transaction has been mined. You cannot interact with the contract before the transaction has been mined.

Here is a sample deployment script for Node 7 (read full tutorial):

// Copyright 2017 https://tokenmarket.net - MIT licensed
//
// Run with Node 7.x as:
//
// node --harmony-async-await  deploy.js
//
// DO NOT RUN IN GETH CONSOLE

let fs = require("fs");
let Web3 = require('web3'); // https://www.npmjs.com/package/web3

// Create a web3 connection to a running geth node over JSON-RPC running at
// http://localhost:8545
// For geth VPS server + SSH tunneling see
// https://gist.github.com/miohtama/ce612b35415e74268ff243af645048f4
let web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));

// Read the compiled contract code
// Compile with
// solc SampleContract.sol --combined-json abi,asm,ast,bin,bin-runtime,clone-bin,devdoc,interface,opcodes,srcmap,srcmap-runtime,userdoc > contracts.json
let source = fs.readFileSync("contracts.json");
let contracts = JSON.parse(source)["contracts"];

// ABI description as JSON structure
let abi = JSON.parse(contracts.SampleContract.abi);

// Smart contract EVM bytecode as hex
let code = contracts.SampleContract.bin;

// Create Contract proxy class
let SampleContract = web3.eth.contract(abi);

// Unlock the coinbase account to make transactions out of it
console.log("Unlocking coinbase account");
var password = "";
try {
  web3.personal.unlockAccount(web3.eth.coinbase, password);
} catch(e) {
  console.log(e);
  return;
}

console.log("Deploying the contract");
let contract = SampleContract.new({from: web3.eth.coinbase, gas: 1000000, data: code});

// Transaction has entered to geth memory pool
console.log("Your contract is being deployed in transaction at http://testnet.etherscan.io/tx/" + contract.transactionHash);

// http://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// We need to wait until any miner has included the transaction
// in a block to get the address of the contract
async function waitBlock() {
  while (true) {
    let receipt = web3.eth.getTransactionReceipt(contract.transactionHash);
    if (receipt && receipt.contractAddress) {
      console.log("Your contract has been deployed at http://testnet.etherscan.io/address/" + receipt.contractAddress);
      console.log("Note that it might take 30 - 90 sceonds for the block to propagate befor it's visible in etherscan.io");
      break;
    }
    console.log("Waiting a mined block to include your contract... currently in block " + web3.eth.blockNumber);
    await sleep(4000);
  }
}

waitBlock();
  • Thank you for this answer "@Mikko Ohtamaa". Appreciated. Below "@Xavier Leprêtre B9lab" provides an alternative approach, and readers should leverage both answers (appropriate to their use-case). :) – NYCeyes Jan 31 '17 at 15:51
  • Please, clarify that the provided code is not compatible with the geth JavaScript console (the code uses ES6 features like arrow functions, while geth only supports ES5). I made the mistake myself, and it looks like I am not the first one: ethereum.stackexchange.com/q/33978/36845 – Gallaecio Apr 17 '18 at 10:05

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.