0

I am working on a private development network set up with geth with PoA consensus. Everything is working well from the geth console. I have written a Solidity contract to initiate some ether transfers and I am calling methods from my JavaScript code using web3js and it is all working well.

My question is about a specific use case where I am trying to transfer ether from one EOA to another EOA by calling a contract method. Let me refer to three addresses, the first two are EOAs: <sender_address>,<beneficiary_address> and the third is what shows as the contract address when I deploy the contract <contract_address>. When I deploy the contract (using truffle) , the account shown in the deployment summary is <sender_address>.

The relevant snippets of code are below:

In my .sol file:

function payBeneficiary(address payable beneficiary, uint256 amount) external payable{
  beneficiary.transfer(amount);
  //Or, since I also pass the same amount in msg.value
  //beneficiary.transfer(msg.value);
}

Update: See the additional code below to include events as recommended by @goodvibrations. Also, it is now recommended to use address.call{}():

//Declare an event in the contract
event PaidBeneficiary(address indexed sender, address indexed beneficiary, uint256 indexed amount);

//Make the transfer call
(bool success, bytes memory response) = beneficiary.call{value: amount}("");
require(success, "Pay Beneficiary was not successful.");

//And emit the event on success
if(success){
  emit PaidBeneficiary(msg.sender, beneficiary, amount);
}else{
  //emit failure event maybe?
}

In my .js file where I use web3js:

var myContract = new web3.eth.Contract(myContract_abi, "<contract_address>");
myContract.methods.payBeneficiary(bene_address, amount_ether).send(
{
  from: "<sender_address>",
  value: web3.utils.toWei(amount_ether, "ether"),
}
)
.on('transactionHash', function(hash){
  console.log(hash);
  web3.eth.getTransaction(hash,(error, result) => {
    if(error){console.log(error);}
    else {console.log(result);}
  })
})
.on('receipt', function(receipt){
})
.on('confirmation', function(confirmationNumber, receipt){
})
.on('error', function(error, receipt) {
  if(error){console.log(error);}
  else {console.log(receipt);}
});

Update: The JavaScript code needs to be updated as below to read the events.

//Listen for events
myContract.events.PaidBeneficiary({
  filter: {},
  fromBlock: 0
}, function(error, event){ console.log(event); })
.on('data', function(event){
  console.log(event); // same results as the optional callback above
})
.on('changed', function(event){
  // remove event from local database
})
.on('error', console.error);

My questions:

The contract method is getting executed and ether is being transferred from <sender_account> to <beneficiary_account> as expected. But, when I print the transaction object returned from the getTransaction method call passing the hash, I see from:<sender_address> but to:<contract_address>. The <contract_address> balance is 0 and remains 0.

Is this the right approach and behaviour? If so, how do I track the transaction which will show me an ether transfer from <sender_account> to <beneficiary_account>?

And what is the difference between msg.value and the amount passed as a parameter to the method? Or can I only use msg.value and do not need the parameter?

2
  • "since I also pass the same amount in msg.value" - the correct approach is to get rid of the amount parameter. Jun 13, 2020 at 10:19
  • Thanks, that answers one of my questions. Hoping for an answer to the other question too - where is the transaction shows the from and to accounts as sender and beneficiary? I need this primarily to build a transaction history view for tracking and auditing. Jun 13, 2020 at 16:06

1 Answer 1

1

I see from:<sender_address> but to:<contract_address>.

This is because you've sent a transaction from <sender_address> to <contract_address>.


The <contract_address> balance is 0 and remains 0.

This is because the contract function transfers the received amount to <beneficiary_account>.


What is the difference between msg.value and the amount passed as a parameter?

  • msg.value indicates the amount of ether (in wei) passed in the transaction
  • amount indicates whatever you want it to indicate

Can I only use msg.value and do not need the parameter?

If you always pass the same value in both, then you obviously do not need the parameter.

4
  • Thanks again. But still have one thing I need some help with: where from the blockchain records can I find a transaction that records the fact that I have sent ether from the sender to the beneficiary? If I have to maintain that information outside the blockchain, it kind of defeats the purpose. Even if I can get two transactions - one from sender to contract and one from contract to beneficiary I can work with that. Jun 14, 2020 at 4:19
  • @VikasMujumdar: add event MyEvent(address indexed sender, address indexed beneficiary); in your contract, and then emit that event at the end of the function. The information that you're asking for will be recorded on the blockchain, and you'll be able to fetch it at any time. Jun 14, 2020 at 5:01
  • Thank you very much @goodvibration, that was a very good solution. I had to enable my geth nodes to listen on WebSockets port since events are not supported on HTTP and it works very well. Jun 15, 2020 at 7:21
  • I have updated my original question with the modified code if anyone is looking for a similar solution. @goodvibration, due to my low reputation :-), I cannot give you a vote for your answer but hope others will vote it up. Jun 15, 2020 at 7:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.