I have an application written in NodeJS that each time it starts has to deploy a smart contract. Once the contract is deployed this application will interact with it making some transactions and listening for its events.
The part about making transactions, invoking smart contract functions and listening events works fine, the once thing I am not be able to do is deploy the smart contract with NodeJS.
To deploy it I have to use truffle via command line and then launch my NodeJS application passing it the smart contract address. And in this way all works fine.
I found a very ugly workaround doing it automatically by running the console commands directly from the NodeJS application (process exec, catch its output, parse string and find the contract address... and... yes, it works!).
Obviously I’ve tried to do it via Infura, but didn’t work. Why? I don’t know, but I can explain what I did. Since deploying a smart contract is not more or less than making a normal transaction, I prepared it, signed it and sending it in the same way used for the other normal transactions and contract function call I cited above. It seems to works! But each time I get two similar errors:
- gas price * gas + value are not sufficient
- if I raise the gas I get gas limit exceeded
I am almost sure that it is not a problem about the gas, but something else wrong in the process prepare > sign > send.
Please, note that I have no need to compile the smart contract at each run! ABI and bytecode are the same at each run, so migrate/deploy it without recompile is enough.
This is the code of the function in NodeJS that I use to deploy the smart contract which fails and returns gas errors:
const amountToSend = 0.010000;
const contract_PrintProofOfWork = new web3.eth.Contract(contractAbi, process.env.SMART_CONTRACT_ADDRESS, {
from: web3.eth.defaultAccount,
gasPrice: '10000000'
});
async function getBalance(address) {
let destinationBalanceWei = await web3.eth.getBalance(address);
let destinationBalance = web3.utils.fromWei(destinationBalanceWei, 'ether');
return destinationBalance;
}
const getCurrentGasPrices = async () => {
let response = await axios.get('https://ethgasstation.info/json/ethgasAPI.json');
let prices = {
low: response.data.safeLow / 10,
medium: response.data.average / 10,
high: response.data.fast / 10
};
log("\r\n");
log('Current ETH Gas Prices (in GWEI):');
log(`Low: ${prices.low} (transaction completes in < 30 minutes)`);
log(`Standard: ${prices.medium} (transaction completes in < 5 minutes)`);
log(`Fast: ${prices.high} (transaction completes in < 2 minutes)`);
log("\r\n");
return prices
};
// This function is used to deploy contract
const deploy = async () => {
log(process.env.WALLET_ADDRESS);
log(`Local PC wallet balance is currently ${await getBalance(web3.eth.defaultAccount)} ETH`.cyan);
let deploy = contract_PrintProofOfWork.deploy({
data: contractByteCode
//arguments: []
}).encodeABI();
let nonce = await web3.eth.getTransactionCount(web3.eth.defaultAccount);
log(`The outgoing transaction count for your wallet address is: ${nonce}`.yellow);
// Fetch the current transaction gas prices from https://ethgasstation.info/
let gasPrices = await getCurrentGasPrices();
// Build a new transaction object and sign it locally
let transactionObject = {
"to": process.env.DESTINATION_WALLET_ADDRESS,
"value": web3.utils.toHex(web3.utils.toWei(amountToSend.toString(), 'ether')),
"gas": 8000000,
"gasPrice": gasPrices.high * 1000000000, // converts the gwei price to wei
"nonce": nonce,
"chainId": 3 // EIP 155 chainId - mainnet: 1, ropsten: 3, rinkeby: 4 (https://ethereum.stackexchange.com/questions/17051/how-to-select-a-network-id-or-is-there-a-list-of-network-ids/17101#17101)
};
web3.eth.accounts.signTransaction(transactionObject, process.env.WALLET_PRIVATE_KEY, function (error, signedTx) {
if (error) {
log(`${error}`.red);
} else {
web3.eth.sendSignedTransaction(signedTx.rawTransaction)
.on('confirmation', function (number) {//dostuff
log(`Success: ${number}`.green);
});
// Note this address. It will be used to create contract instance from Angular 5 application.
//console.log("contract deployed to", result.options.address);
}
}).catch(function(err){
log(`${err}`.red);
});
};
// Call deploy function.
deploy();
Errors:
(node:23315) UnhandledPromiseRejectionWarning: Error: Node error: {"code":-32000,"message":"insufficient funds for gas * price + value"} at Function.validate (/Users/sahelanthropus/IdeaProjects/ThesisPrototype/prototype-local-simple/node_modules/web3-providers/dist/web3-providers.cjs.js:349:18) at /Users/sahelanthropus/IdeaProjects/ThesisPrototype/prototype-local-simple/node_modules/web3-providers/dist/web3-providers.cjs.js:692:57 at processTicksAndRejections (internal/process/next_tick.js:81:5)
Or if I raise the gas to be used:
(node:23329) UnhandledPromiseRejectionWarning: Error: Node error: {"code":-32000,"message":"exceeds block gas limit"} at Function.validate (/Users/sahelanthropus/IdeaProjects/ThesisPrototype/prototype-local-simple/node_modules/web3-providers/dist/web3-providers.cjs.js:349:18) at /Users/sahelanthropus/IdeaProjects/ThesisPrototype/prototype-local-simple/node_modules/web3-providers/dist/web3-providers.cjs.js:692:57 at processTicksAndRejections (internal/process/next_tick.js:81:5)
Can anyone simply show me how I can deploy a smart contract using web3js
e Infura
even without referring to the code and the problem I have exposed in this question?
Update:
process.env.WALLET_PRIVATE_KEY
has enough Ropsten testnet ether?