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)

                    })
                })


            })
    })

})
  • 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. – goodvibration Dec 9 '19 at 6:13
  • @goodvibration I aligned the code – Ayurpwnz Dec 9 '19 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. – goodvibration Dec 9 '19 at 6:45
  • @goodvibration I edited the description and tried to leave only the problem part of the code – Ayurpwnz Dec 9 '19 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 Dec 10 '19 at 16:19
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!

  • Thanks for your answer, when I try to output nonce to the console, I get: Promise {<pending>} – Ayurpwnz Dec 9 '19 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 Dec 9 '19 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 Dec 9 '19 at 11:46
  • can you post your updated code? – Zakalwe Dec 10 '19 at 8:36
  • yea, check now plz – Ayurpwnz Dec 10 '19 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 };
  }
}
  • with ur part error: RangeError: private key length is invalid at transaction.sign(Buffer.from(keys, 'hex')) – Ayurpwnz Dec 10 '19 at 12:42
  • Remove 0x from private key – Prashant Prabhakar Singh Dec 11 '19 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 Dec 11 '19 at 14:47
  • can u help me? plz – Ayurpwnz Dec 12 '19 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 – Prashant Prabhakar Singh Dec 13 '19 at 6:45

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.