1

I used this guide to deploy a smart contract with Node-js. I followed as far as my contract was created as an object. Because the mentioned guide is old some web3 methods changed nowadays. So it looks like i cannot continue following that. My question is "how do i assign address and data and gas to my contract object for deploying?". Please guide me with an appropriate code to deploy contract.

app.js:

var Web3=require('web3');
var fs=require('fs');
var solc=require('solc');
var web3=new Web3('ws://127.0.0.1:8545');
var address="0xdC3881248306fd62bbA5d9F0FDD39b5693bd1737";
var contractAbi=[
    {
        "constant": true,
        "inputs": [],
        "name": "notation",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            }
        ],
        "payable": false,
        "stateMutability": "pure",
        "type": "function"
    }
];
var contract_sol=fs.readFileSync('E:/Deploy/contracts/Deploy.sol','utf8');
var contract_compiled=solc.compile(contract_sol);
for (let contractName in contract_compiled.contracts) {
var contract_byteCode=contract_compiled.contracts[contractName].bytecode;
}
var gasEstimate=web3.eth.estimateGas({data:contract_byteCode});
var contract_object=new web3.eth.Contract(contractAbi);
  • what is var address="0xdC3881248306fd62bbA5d9F0FDD39b5693bd1737"; for??? – goodvibration Mar 8 at 15:11
  • This is my Truffle address. I want to use it as address of contract creator. – Alireza Mar 8 at 15:28
  • Is your contract already deployed at that address? – goodvibration Mar 8 at 15:36
  • No, i didn't deploy the contract. – Alireza Mar 8 at 15:38
  • So how are you planning to deploy it specifically at that address (why and how did you choose it)? – goodvibration Mar 8 at 15:46
1

Assuming that you have already compiled the contract, and that its abi and bytecode are in files <ContractName>.abi and <ContractName>.bin respectively, you can use this script (web3 v1.2.1):

const fs   = require("fs");
const Web3 = require("web3");

const NODE_ADDRESS  = "...";
const PRIVATE_KEY   = "...";
const CONTRACT_NAME = "...";
const CONTRACT_ARGS = [...];

async function scan(message) {
    process.stdout.write(message);
    return await new Promise(function(resolve, reject) {
        process.stdin.resume();
        process.stdin.once("data", function(data) {
            process.stdin.pause();
            resolve(data.toString().trim());
        });
    });
}

async function getGasPrice(web3) {
    while (true) {
        const nodeGasPrice = await web3.eth.getGasPrice();
        const userGasPrice = await scan(`Enter gas-price or leave empty to use ${nodeGasPrice}: `);
        if (/^\d+$/.test(userGasPrice))
            return userGasPrice;
        if (userGasPrice == "")
            return nodeGasPrice;
        console.log("Illegal gas-price");
    }
}

async function getTransactionReceipt(web3) {
    while (true) {
        const hash = await scan("Enter transaction-hash or leave empty to retry: ");
        if (/^0x([0-9A-Fa-f]{64})$/.test(hash)) {
            const receipt = await web3.eth.getTransactionReceipt(hash);
            if (receipt)
                return receipt;
            console.log("Invalid transaction-hash");
        }
        else if (hash) {
            console.log("Illegal transaction-hash");
        }
        else {
            return null;
        }
    }
}

async function send(web3, account, transaction) {
    while (true) {
        try {
            const options = {
                data    : transaction.encodeABI(),
                gas     : await transaction.estimateGas({from: account.address}),
                gasPrice: await getGasPrice(web3),
            };
            const signed  = await web3.eth.accounts.signTransaction(options, account.privateKey);
            const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
            return receipt;
        }
        catch (error) {
            console.log(error.message);
            const receipt = await getTransactionReceipt(web3);
            if (receipt)
                return receipt;
        }
    }
}

async function run() {
    const web3        = new Web3(NODE_ADDRESS);
    const account     = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
    const abi         = fs.readFileSync(CONTRACT_NAME + ".abi", {encoding: "utf8"});
    const bin         = fs.readFileSync(CONTRACT_NAME + ".bin", {encoding: "utf8"});
    const contract    = new web3.eth.Contract(JSON.parse(abi));
    const options     = {data: "0x" + bin, arguments: CONTRACT_ARGS};
    const transaction = contract.deploy(options);
    const receipt     = await send(web3, account, transaction);
    console.log(receipt.contractAddress);
    if (web3.currentProvider.constructor.name == "WebsocketProvider")
        web3.currentProvider.connection.close();
}

run();
| improve this answer | |
  • Thanks for your code. These two messages emerged and i don't know what should i do? 1- The data field must be HEX encoded data. and after that 2- Enter transaction-hash or leave empty to retry:. I don't know which transaction hash that means. Data field is const options = {data: "0x" + bin};. I set const NODE_ADDRESS = "ws://127.0.0.1:8545"; and const PRIVATE_KEY = to a private key belongs to a Ganache account. – Alireza Mar 9 at 6:45
  • Now that problem is eliminated. I set const options = {data: "0x" + bin}; to the bytecode that exists in Truffle json file and the mentioned messages never emerge. – Alireza Mar 9 at 6:49
  • @A.Kiakojouri: It means that you don't have a proper byte code in the file <CONTRACT_NAME >.bin. – goodvibration Mar 9 at 6:50
  • As I wrote at the top of the answer, it assumes that your bytecode is in file <CONTRACT_NAME >.bin. If you take it from the Truffle json output file, then I believe that it is already prefixed with "0x". Run console.log(bin) and find out for sure. – goodvibration Mar 9 at 6:52
  • Another problem. By this code the contract deployment occurs and Ganache shows it by a block mining. In the mined block it is mentioned that a smart contract created. But in contracts list of Ganache it is mentioned that the given contract is not deployed. What is the reason? – Alireza Mar 9 at 7:19
0

Hey if you are using truffle framework you can set your gas limit and gas price in your truffle-config.js file for different network and env like this:

module.exports = {

  networks: {
    development: {
    host: "127.0.0.1",
    port: 7545,
    network_id: "*" // Match any network id
},
develop: {
  port: 8545
},
rinkeby: {
  provider: () => new HDWalletProvider(mnemonic, `https://rinkeby.infura.io/v3/${infuraKey}`),
    network_id: 4,       // rinkeby's id
    gas: 6500000,        // rinkeby has a lower block limit than mainnet
    gasPrice: 10000000000
  }
}
};
| improve this answer | |
  • I think you are using Rinkeby in your answer. But i want to use my own testnet. I think i should put gas and gasPrice in development field. – Alireza Mar 8 at 15:33
0

The code provided in the question lacks just the followed command in the end of itself to a smart contract be deployed:

contract_object.deploy().send({from: address, gas: gasEstimate, gasPrice:1000000});

address is the address of deployer account and gasEstimate determines the required value of gas to deploy this contract. If you put the both in .send(…) just as send({from: address, gas: gasEstimate}); infact you are telling contract_object should be deployed from the account with address address and with gasEstimate gases in the network.

| improve this answer | |

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.