0

I've already interacted with this contract instance using a local Geth node with my wallet loaded/unlocked, so I know there's nothing wrong with the contract.

Now I'm using an Infura RPC node instead to interact with contracts and therefore must sign transactions locally. So:

  1. Get contract instance from ABI and address
  2. Encode contract method call to raw ABI value
  3. Create transaction to contract address with raw ABI value
  4. Sign transaction
  5. Broadcast signed transaction

Using web3js 1.0.0, docs and examples would suggest this:

const Web3 = require('web3');
const Tx = require('ethereumjs-tx');
var web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/token...'));

var from_addr = "0xdeadbeef..."; // my wallet address
var privateKey = "deadbeef..."; // my wallet private key
var contract_abi = [...]; // Compiler output from Remix
var contract_addr = "0xdeadbeef..."; // I already deployed this contract using Remix

// get the contract instance
var contract = new web3.eth.Contract(contract_abi, contract_addr)

// call `myMethod` method on contract instance
var method_call_abi = contract.methods.myMethod(arg1, arg2, ...).encodeABI();

web3.eth.getTransactionCount(from_addr).then(txCount => { // get tx count of my wallet...

    // build transaction dict
    const txData = {
      nonce: web3.utils.toHex(txCount),
      gasLimit: web3.utils.toHex(25000),
      gasPrice: web3.utils.toHex(10e8), // 1 Gwei
      to: contract_addr,
      from: from_addr,
      value: method_call_abi,
    };

    // serialize and sign transaction
    var transaction = new Tx(txData); // ERROR IS HERE
    var privateKeyBuf = new Buffer(privateKey, 'hex');
    transaction.sign(privateKeyBuf);
    var serializedTx = transaction.serialize().toString('hex');

    // finally send
    web3.eth.sendSignedTransaction('0x' + serializedTx, cb).then(console.log);

});

And here's what I get:

Promise {
  <pending>,
  domain:
   Domain {
     domain: null,
     _events:
      { removeListener: [Function: updateExceptionCapture],
        newListener: [Function: updateExceptionCapture],
        error: [Function: debugDomainError] },
     _eventsCount: 3,
     _maxListeners: undefined,
     members: [] } }
> (node:23512) UnhandledPromiseRejectionWarning: AssertionError [ERR_ASSERTION]: The field value must not have more 32 bytes
    at Transaction.setter [as value] (/mnt/ethereum/ubuntu/node_modules/ethereumjs-util/dist/index.js:633:9)
    at /mnt/ethereum/ubuntu/node_modules/ethereumjs-util/dist/index.js:685:63
    at Array.forEach (<anonymous>)
    at Object.exports.defineProperties (/mnt/ethereum/ubuntu/node_modules/ethereumjs-util/dist/index.js:684:14)
    at new Transaction (/mnt/ethereum/ubuntu/node_modules/ethereumjs-tx/es5/index.js:112:13)
    at web3.eth.getTransactionCount.then.txCount (repl:13:23)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:160:7)

Stepping through, this error happens on the var transaction = new Tx(txData); line. What am I doing wrong here?

I also tried creating the transaction on remix.ethereum.org. The data it gives me is the exact same as what encodeABI() produces, so it's correct.

1

After looking at the ethereumjs-tx docs, my txData dictionary should have the key "data" instead of "value." "value" just the number of ether tokens to send, not an encoded transaction.

Unfortunately, I saw "value" being used in examples and took a while to realize that was wrong because I thought ether coin transactions and contract transactions were the same. I probably also misread "value" as "data" a few times. Here's one example; I should also maybe credit it for part of my code.

  • 1
    Thanks for following up and letting us know. It might help someone. – Rob Hitchens - B9lab Apr 9 '18 at 3:55

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.