32

This may be a very basic question, I don't know why but I am unable to find correct solution to how can I call my contract's method using sendTransaction. I have a transfer(address, uint256) function which I want to call using sendTransaction and callTransaction. I have my contract compiled and I have it's abi and address. Now, how can I call different metrhods of the contract using sendTransaction?
I was reading the question Syntax for calling contract state changing methods, and I got explanations for function having single parameter but what if it has more than a parameter of different types, like here transfer() function accepts 2 parameters.

5 Answers 5

43

Posting solution to my own question for anyone who needs it. To call a contract function from geth:

const contractAbi = eth.contract(AbiOfContract);
const myContract = contractAbi.at(contractAddress);
// suppose you want to call a function named myFunction of myContract
const getData = myContract.myFunction.getData(function_parameters);
// finally pass this data parameter to send Transaction
web3.eth.sendTransaction({ to:Contractaddress, from:Accountaddress, data: getData });

Note: You can add other fields in sendTransaction like value etcetera, I have skipped that for simplicity to new use users.


To all the users who face challanges with signing data using private key. The pseudo code for signing and sending a transaction to contract using private key:

const Tx = require('ethereumjs-tx')
const web3 = new Web3()
web3.setProvider(new web3.providers.HttpProvider(web3RpcAddr))
const yourContract = new web3.eth.Contract(yourContract.abi, yourContract.address)

function sendCoin(toAddress, amount) {
  const nonce = await web3.eth.getTransactionCount(fromAddress, 'pending')
  const extraData = await yourContract.methods.transfer(toAddress, amount)
  const data = extraData.encodeABI()
  const txObj = {
    from: adminAddress,
    to: yourContractAddress,
    data,
    value: '0',
    gas: gasSent, // calculation of gas and gas Price is skipped here
    gasPrice: gasPriceSent,
    privKey: adminPvtKey,
    nonce
  }

  let signedTx = await signTx(txObj)
  signedTx = "0x" + signedTx.serialize().toString('hex')
  await submitSignedTx(signedTx)
}

async function signTx(payload) {
  let { from, to, data, value, gas, gasPrice, privKey, nonce } = payload
  let txParams = {
    to,
    data,
    value: web3.utils.toHex(value),
    gasPrice: web3.utils.toHex(gasPrice),
    gas: web3.utils.toHex(gas),
    nonce: web3.utils.toHex(nonce)
  }
  const tx = new Tx(txParams)
  privKey = await _validatePrivKey(privKey)
  privKey = new Buffer(privKey, 'hex')
  tx.sign(privKey)
  privKey = null
  return tx
}

async function submitSignedTx(serializedTx) {
  return new Promise((fullfill, reject) => {
    web3.eth.sendSignedTransaction(serializedTx)
      .on('transactionHash', txHash => {
        l.info('transaction sent. hash =>', txHash)
        return fullfill({success: true, txHash : txHash})
      })
      .on('error', e => {
        // console.log('unable to send tx', e)
        l.error(logmsg, e.message)
        return fullfill({success: false, message: e})
      })
  })
}
13
  • 1
    this is an excellent answer! worked for me- remember to put the addresses in quotes. Commented Jul 31, 2017 at 21:29
  • it is not clear what is getData() method doing. is it a builtin method or has to be created by the developer who wrote the contract?
    – Nulik
    Commented Oct 16, 2017 at 15:24
  • You need not implement getData method.It is used to retrieve the value of data in state storage. You can read more here: solidity.readthedocs.io/en/develop/… Commented Oct 17, 2017 at 4:09
  • Do you need to specify the IP of the Ethereum node that you're sending this transaction to?
    – RagHaven
    Commented Jan 20, 2018 at 4:27
  • Yes, you need to specify that. That is while making the connection to web3. Keep in mind not to expose personal over RPC Commented Jan 20, 2018 at 6:43
7

Have you tried:

// In Javascript
myContract.transfer(otherAddress, aNumber, { from: myAccount });
// Or
myContract.transfer.sendTransaction(otherAddress, aNumber, { from: myAccount });
// Or
myContract.transfer.call(otherAddress, aNumber, { from: myAccount });

See the whole documentation.

1
  • correct for web3.js, but please provide references to the documentation.
    – Paul S
    Commented Sep 20, 2016 at 18:19
2

Improving @Prashant Prabhakar Singh answer:

var contractAbi = eth.contract(AbiOfContract);
var myContract = contractAbi.at(contractAddress);
// suppose you want to call a function named myFunction of myContract
var getData = myContract.myFunction.getData("1","boy");//just parameters you pass to myFunction
// And that is where all the magic happens
web3.eth.sendTransaction({
    to:ContractAddress,//contracts address
    from:web3.eth.accounts[0],
    data: getData,
    value: web3.toWei(EtherAmount, 'ether')//EtherAmount=>how much ether you want to move
},function (error, result){ 
            if(!error){
                console.log(result);//transaction successful
            } else{
                console.log(error);//transaction failed
            }
    });
1
var abi=[//your abi array];
var contractAddress = "//your contract address";
var contract = web3.eth.contract(abi).at(contractAddress);

contract.functionName.sendTransaction(parameter_1,parameter_2,parameter_n,{
            from:web3.eth.accounts[0],
            gas:4000000},function (error, result){ //get callback from function which is your transaction key
                if(!error){
                    console.log(result);
                } else{
                    console.log(error);
                }
        });

you can then try to get transaction receipt by using

var receipt=web3.eth.getTransactionReceipt(trHash);

-if you get receipt as null that means your transaction is not mined, you can keep trying after some time until you get receipt values. -You can check in the receipt that all the provided gas is used or not, all gas used indicated your transaction is failed

1
  • Any updated code is there?It not working on latest web3 Commented Feb 21, 2019 at 6:56
0

With Etherjs utilities data can be created as follows which can be directly sent to sendTransaction function.

//ethereum provider instance creation
let ethereum = window.ethereum;
// Request account access if needed
await ethereum.enable();
let provider = new ethers.providers.Web3Provider(ethereum);


 //Get method id (transfer function method id)
 const METHOD_ID = "0x05555555"; //replace with actual transfer function method id

 //creating encoded data
 let encodedData = ethers.utils.hexConcat([
      METHOD_ID,
      ethers.utils.defaultAbiCoder.encode(
        ["address", "uint256"],
        [receiverAddress, amount] //replace with receiver and amount to be transferred
      ),
    ]);

//Create raw transaction param
 const param = {
          from: sender, //replace with sender wallet address
          to: ERC20_CONTRACT_ADDRESS, //replace with your contract address
          data: encodedData
 };

 //Send Transaction using etherjs
 const transactionHash = await provider.send('eth_sendTransaction', params)

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.