I am trying to execute a transaction on a private network, using my account.

The general flow:

Web3.js --> Parity node --> Private network

The transaction:

Invoke a method in a contract deployed beforehand

My first approach was to unlock the account, and then send the transaction.

The procedure:

  1. Create a transaction object for the method (see Web3 docs).
  2. Unlock the account using my password (see Parity docs).
  3. Send the transaction object (see Web3 docs).

My code:

let transaction = contract.methods.myFunc();
let options = {
    gasPrice: GAS_PRICE,
    gas: await transaction.estimateGas()
await web3.eth.personal.unlockAccount(ACCOUNT_ADDRESS, ACCOUNT_PASSWORD);
await transaction.send(options);

This seems to work just fine.

However, I have later realized that unlocking my account leaves a serious security breach, as others might be able to submit requests during the time the account is unlocked. Of course, this may be prevented in several different ways I suppose (for example, by checking the sender's IP). But I believe that I would be better off executing it without unlocking the account (i.e., instead of creating a problem and then trying to solve it, avoid the problem to begin with).

So my second approach is to sign the transaction, and only then send it.

The procedure:

  1. Create a transaction object for the method (see Web3 docs).
  2. Sign the transaction with my account's private key (see Web3 docs).
  3. Send the signed transaction string to the Parity node (see Web3 docs).

My code:

let transaction = contract.methods.myFunc();
let tx = {
    to: contract._address, 
    data: transaction.encodeABI(),
    gasPrice: GAS_PRICE,
    gas: await transaction.estimateGas()
let signedTransaction = await web3.eth.accounts.signTransaction(tx, PRIVATE_KEY);
await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction);

However, executing the code above results with the following error:

Insufficient funds.
The account you tried to send transaction from does not have enough funds.
Required 63611 and got: 0.

Obviously, since the first approach completes successfully, there shouldn't be any issue of insufficient funds here.

Can anyone please explain what I'm doing wrong?

Thank you!

  • check for "from: ACCOUNT_ADDRESS" in first case, whereas in second case no "from:" address is specified manually. is same from addresses are passed in both cases? – kherwa Jun 17 '18 at 18:10
  • @kherwa: That is why I added a link to the documentation of each function. According to the documentation of web3.eth.accounts.signTransaction, the object passed to this function does not need to have a from field. By the way, I tried to add this field just in case they forgot to mention it in the docs, but got the same result. – goodvibration Jun 17 '18 at 20:08
  • I meant that, are both addresses same? One derived from PRIVATE KEY and ACCOUNT_ADDRESS used in first case. – kherwa Jun 17 '18 at 20:16
  • @kherwa: In the first case, I use ACCOUNT_ADDRESS and ACCOUNT_PASSWORD. In the second case, I use the ciphertext field given in the key file, where ACCOUNT_ADDRESS also appears. So I'm assuming that the private key matches the account address. BTW, I prefix this ciphertext with 0x. – goodvibration Jun 18 '18 at 5:27
  • No private key is stored in encrypted form in key file. – kherwa Jun 18 '18 at 5:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.