1

I have a very simple Smart Contract deployed using remix.ethereum which is:

pragma solidity ^ 0.6.0;

contract primerContrato {

uint storeddata;

function set(uint x) public{
    storeddata = x;
}

function get() public view returns (uint){
    return storeddata;
}

}

I'm using Metamask to test set function, and it works properly. I can see on Etherscan my transaction hash and the input I entered on Remix.

I want to do this automatically, without having to accept transactions on Metamask. I'm using NodeJS to generate files and I want to store them hashes into the testnet blockchain. So I would be waiting for files to be generated, and calling set function of my Smart Contract to store that value. For this first test it would be a single call with a single value to store.

I've been reading a bit about signed transactions, and I've tried this code from https://medium.com/coinmonks/ethereum-tutorial-sending-transaction-via-nodejs-backend-7b623b885707 Which I changed because I don't need a web process to execute it:

const web3 = require('web3');
const express = require('express');
const Tx = require('ethereumjs-tx').Transaction;


//Infura HttpProvider Endpoint
web3js = new web3(new web3.providers.HttpProvider("https://kovan.infura.io/v3/APIKEY")); //there goes my API

enviar();

function enviar (req,res){

        var myAddress = '0x68d9...'; //from Metamask
        var privateKey = Buffer.from('42AE...', 'hex') //from Metamask
        var toAddress ; //no address as I am posting it to the smart contract

        //contract abi is the array that you can get from the ethereum wallet or etherscan
        var contractABI =[
                            {
                                "inputs": [],
                                "name": "get",
                                "outputs": [
                                    {
                                        "internalType": "uint256",
                                        "name": "",
                                        "type": "uint256"
                                    }
                                ],
                                "stateMutability": "view",
                                "type": "function"
                            },
                            {
                                "inputs": [
                                    {
                                        "internalType": "uint256",
                                        "name": "x",
                                        "type": "uint256"
                                    }
                                ],
                                "name": "set",
                                "outputs": [],
                                "stateMutability": "nonpayable",
                                "type": "function"
                            }
                        ];
        var contractAddress ="0xb031..."; //my contract address
        //creating contract object
        var contract = new web3js.eth.Contract(contractABI,contractAddress);

        var count;
        // get transaction count, later will used as nonce
        web3js.eth.getTransactionCount(myAddress).then(function(v){
            console.log("Count: "+v);
            count = v;
            var amount = web3js.utils.toHex(1e16);
            //creating raw tranaction
            var rawTransaction = {"from":myAddress, "gasPrice":web3js.utils.toHex(60* 1e9),"gasLimit":web3js.utils.toHex(3000000),"to":contractAddress,"value":"0x0","data":contract.methods.set(0x849787ab...).encodeABI(),"nonce":web3js.utils.toHex(count+2)}
            console.log(rawTransaction);
            //creating tranaction via ethereumjs-tx
            var transaction = new Tx (rawTransaction);
            //signing transaction with private key
            transaction.sign(privateKey);
            //sending transacton via web3js module
            web3js.eth.sendSignedTransaction('0x'+transaction.serialize().toString('hex'))
            .on('transactionHash',console.log);  

        })
    };

I've found two errors:

1st. When I try to send a 256 bit integer (uint) on contract.methods.set(0x849787ab...), console throw an overflow error (1e77)

2nd. If I change this value to a smaller one, it actually shows a transaction hash, but I does not charge anything on my wallet and I doesn't appear on etherscan consequently.

Is there a simpler method to do so? Do you have any doubts?

Thank you in advance! I'm in a hurry to send this project and I would appreciate your help a lot!!!

1 Answer 1

0

When I try to send a 256 bit integer (uint) on contract.methods.set(0x849787ab...), console throw an overflow error (1e77)

In Javascript, Number.MAX_SAFE_INTEGER is equal to 2 ^ 53 - 1.

Therefore, always use strings: contract.methods.set("0x849787ab...").


Is there a simpler method to do so?

Here is what I use (tested with web3.js v1.2.1):

const Web3 = require("web3");

const YOUR_NODE_ADDRESS = "...";
const YOUR_PRIVATE_KEY  = "...";
const YOUR_INPUT_VALUE  = "...";
const YOUR_GAS_PRICE    = "...";

async function send(web3, account, gasPrice, transaction, value = 0) {
    const options = {
        to      : transaction._parent._address,
        data    : transaction.encodeABI(),
        gas     : await transaction.estimateGas({from: account.address, value: value}),
        gasPrice: gasPrice,
        value   : value
    };
    const signed  = await web3.eth.accounts.signTransaction(options, account.privateKey);
    const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
    return receipt;
}

async function run() {
    const web3 = new Web3(YOUR_NODE_ADDRESS);
    const contract = new web3.eth.Contract(contractABI,contractAddress);
    const account = web3.eth.accounts.privateKeyToAccount(YOUR_PRIVATE_KEY);
    const transaction = contract.methods.set(YOUR_INPUT_VALUE);
    const receipt = await send(web3, account, YOUR_GAS_PRICE, transaction);
    console.log(receipt);
}

run();
10
  • my node address is the one I obtain from Infura? Where does my contract hash go? and abi? Or it automatically retrieves it?
    – salgarji
    Commented Jun 29, 2020 at 14:20
  • @salgarji: You seem to already have that part (initializing the web3 instance and the contract instance) in your code. So you probably don't need to take that from my answer. Commented Jun 29, 2020 at 14:21
  • I would just use "https://kovan.infura.io/v3/APIKEY", BTW (i.e., no need to wrap it with new web3.providers.HttpProvider as far as I'm aware of). Commented Jun 29, 2020 at 14:22
  • I have this in return: (node:1025) UnhandledPromiseRejectionWarning: Error: Returned error: Transaction gas price supplied is too low. There is another transaction with same nonce in the queue. Try increasing the gas price or incrementing the nonce. I don't know how to increase nonce. My gas limit is over 60.000.000.000 in Kovan test net. Is not enough?
    – salgarji
    Commented Jun 29, 2020 at 15:22
  • @salgarji: That's when you try to execute many transactions. In that case, you should control the nonce and increment it properly (by adding it in the options object above). Commented Jun 29, 2020 at 15:25

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.