0

I have main address: const fromAddress

There is also an array of addresses and their keys:foreth/keys

I need to send all erc20 tokens from: foreth array to the: fromAddress

Tokens are sent only from the first address of the foreth array, a hash is generated for all subsequent addresses, which is not on etherscan with error: Sorry, We are unable to locate this TxnHash

It is necessary to make sure that tokens are sent from all addresses that are in the array foreth

let tokenAddress = "erc20_contract_addr";
let fromAddress = 'main_addr'
let privateKey = Buffer.from('key_main_addr', 'hex')

const contractInstance = new web3.eth.Contract(minABI, tokenAddress)
let foreth = ["addr1", "addr2", "addr3", "addr4"];
let keys = ['addr1_key', 'addr2_key', 'addr3_key', 'addr4_key']

function nonce_addr(address) {
    return web3.eth.getTransactionCount(address)
}

foreth.forEach(async function(recipient, i) {

    const balance = await contractInstance.methods.balanceOf(recipient).call(function(err, result) {
        let contract = new web3.eth.Contract(minABI, tokenAddress, {
            from: recipient
        })

        if (result < 0) return
        web3.eth.getTransactionCount(fromAddress)
            .then((count) => {
                let rawTransaction = {
                    'from': fromAddress,
                    'gasPrice': web3.utils.toHex(20 * 1e9),
                    'gasLimit': web3.utils.toHex(21000),
                    'to': recipient,
                    'value': web3.utils.toHex(web3.utils.toWei("0.0008")),
                    'nonce': web3.utils.toHex(count + i)
                }
                let transaction = new Tx(rawTransaction)
                transaction.sign(privateKey)
                return new Promise((resolve, reject) => {
                    web3.eth.sendSignedTransaction('0x' + transaction.serialize().toString('hex'))
                        .on('transactionHash', console.log)
                        .on('receipt', resolve)
                        .on('error', reject)
                })
            }).then(receipt => {
                console.log("eth was send")

                keys.forEach(async function(keys) {
                    let nonce = await web3.eth.getTransactionCount(recipient, 'pending');

                    let rawTransaction = {
                        'from': recipient,
                        'gasPrice': web3.utils.toHex(20 * 1e9),
                        'gasLimit': web3.utils.toHex(100000),
                        'to': tokenAddress,
                        'value': 0x0,
                        'data': contract.methods.transfer(fromAddress, web3.utils.toHex(result)).encodeABI(),
                        'nonce': web3.utils.toHex(nonce)
                    }
                    nonce++
                    let transaction = new Tx(rawTransaction)
                    transaction.sign(Buffer.from(keys, 'hex'))
                    let serializedTx = '0x' + transaction.serialize().toString('hex')
                    return new Promise(resolve => {
                        web3.eth.sendSignedTransaction(serializedTx)
                            .on('transactionHash', console.log)

                    })
                })


            })
    })

})
7
  • Your question is a total mess - both the description at the top and the code that follows. Please do a minimal effort to split this one long description into short readable sentences in separate lines. Then, please align your code properly. Commented Dec 9, 2019 at 6:13
  • @goodvibration I aligned the code
    – Ayurpwnz
    Commented Dec 9, 2019 at 6:38
  • I fixed your description a bit. Still looks bad though. For example, couldn't you find a better way to write "I have address A = fromAddress and an array of addresses B (foreth)"? Or "hashes of transactions that are not on etherscan are created"? It's totally unclear in the language-aspect of it. Also, your code is way too long for the problem that you're describing. Try to include only the part which is absolutely necessary. Commented Dec 9, 2019 at 6:45
  • @goodvibration I edited the description and tried to leave only the problem part of the code
    – Ayurpwnz
    Commented Dec 9, 2019 at 7:15
  • are you on a testnet? If so, can you post the rawTransactions - this might help get to the bottom of it?
    – Zakalwe
    Commented Dec 10, 2019 at 16:19

2 Answers 2

0

well, this:

'nonce': web3.utils.toHex(count + k)

is unlikely to work. Each account has a separate nonce. So, if all the accounts here had, say, nonce = 2, then each nonce would need to be 3, not 3, 4, 5 etc...

you can find the current nonce of an account using web3.eth.getTransactionCount(accountAddress)

and then add one to it. You need to do this for each address.

Note that this will not necessarily be accurate if there are pending transactions against the accounts. Welcome to the wonderful world of managing Ethereum nonces!

6
  • Thanks for your answer, when I try to output nonce to the console, I get: Promise {<pending>}
    – Ayurpwnz
    Commented Dec 9, 2019 at 9:48
  • And what is the best way to do this? Write a function that receives an address at the input and returns nonce?
    – Ayurpwnz
    Commented Dec 9, 2019 at 10:18
  • I wrote a nonce_addr function that returns: return web3.eth.getTransactionCount (address) and replaced web3.eth.getTransactionCount (recipient) with nonce_addr (recipient), but now, the first 2 addresses of the foreth array are processed fine, and 3 writes nonce too low
    – Ayurpwnz
    Commented Dec 9, 2019 at 11:46
  • can you post your updated code?
    – Zakalwe
    Commented Dec 10, 2019 at 8:36
  • yea, check now plz
    – Ayurpwnz
    Commented Dec 10, 2019 at 12:16
0

You may also need to add pending flag to getTransactionCount.this flag also includes unconfirmed transactions in transaction count, which is important in your case.

I haven't tested but following code (roughly written) should work:

const testStackCode = async() => {
  let fromAddress = ''
  const contractInstance = new web3.eth.Contract(minABI, contractAddress)
  let foreth = []
  let keys = []

  for(let i=0; i< foreth.length; i++) {
    let recipeint = foreth[i]
    let balance = await contractInstance.methods.balanceOf(recipeint).call()
    if(balance < 0 ) continue
    key = keys[i]
    let nonce = await web3.eth.getTransactionCount(recipeint, 'pending');
    let extraData = contractInstance.methods.transfer(fromAddress, balance);
    let data = extraData.encodeABI()
    let txParams = {
      to: contractAddress,
      data,
      value: web3.utils.toHex(0),
      nonce: web3.utils.toHex(nonce)

    }
    console.log({ from: recipeint, to: fromAddress, nonce, amount: balance})
    var tx = new Tx(txParams)
    let privKey = _validatePrivKey(key)
    privKey = new Buffer(privKey, 'hex')
    tx.sign(privKey)
    let serializedTx = '0x' + tx.serialize().toString('hex')
    await submitSignedTx(serializedTx)
  }
}

function _validatePrivKey(privKey){
  if(privKey.startsWith('0x')) privKey = privKey.substr(2)
  return privKey
}

const submitSignedTx = async(serializedTx) => {
  try{
    return new Promise((fullfill, reject) => {
      web3.eth.sendSignedTransaction(serializedTx)
        .on('transactionHash', txHash => {
         console.log(logmsg, 'transaction sent. hash =>', txHash)
          return fullfill({success: true, txHash : txHash})
        })
        .on('error', e => {
          console.log('unable to send tx', e);
          return fullfill({success: false, message: e})
        })
    })
  } catch(e){
    console.log(e)
    return {success: false, message: e.message };
  }
}
22
  • with ur part error: RangeError: private key length is invalid at transaction.sign(Buffer.from(keys, 'hex'))
    – Ayurpwnz
    Commented Dec 10, 2019 at 12:42
  • Remove 0x from private key Commented Dec 11, 2019 at 9:12
  • If I use 4 accounts, then the last account is ignored for some reason, and many nonce too low errors appear. I updated the code in question
    – Ayurpwnz
    Commented Dec 11, 2019 at 14:47
  • can u help me? plz
    – Ayurpwnz
    Commented Dec 12, 2019 at 2:51
  • Did you tried debugging the solution, checking when is nonce repeated? Go ahead with logging nonce, account and then you can know what is causing the issue. To replicate this I will need enough time to setup different contracts to check what's wrong. First thing to start with is to use synchronous for loop instead of for-each Commented Dec 13, 2019 at 6:45

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.