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:
- Get contract instance from ABI and address
- Encode contract method call to raw ABI value
- Create transaction to contract address with raw ABI value
- Sign transaction
- 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.