12

Let's say there's a payable Solidity function

function doSomething() 
  payable
  returns(uint)
{
  require(msg.value == 1 ether);
  return 1;
}

And you call this function

instance.doSomething({
      from:_account,
      value:1 ether
    }).then(function(value) {
    }).catch(function(err) {
    });

This will send ether to the function, make transaction and will return the transaction result. Cool.

But how can I get the return value of that Solidity function? Transaction record does not have anything about it.

'instance.doSomething.sendTransaction()' also the same situation.

Because the function is payable, it should receive ethereum.

Many thanks, coindevbw

0

2 Answers 2

15

Since transactions don't return values outside Solidity, what you need to do inside the function is to fire an event. Then, in your front-end you can watch events and filter them accordingly to retrieve whatever data you provided to that event.

If you use truffle, here's a simple way to do it form their docs:

http://truffleframework.com/docs/getting_started/contracts

var account_one = "0x1234..."; // an address
var account_two = "0xabcd..."; // another address

var meta;
MetaCoin.deployed().then(function(instance) {
  meta = instance;  
  return meta.sendCoin(account_two, 10, {from: account_one});
}).then(function(result) {
  // result is an object with the following values:
  //
  // result.tx      => transaction hash, string
  // result.logs    => array of decoded events that were triggered within this transaction
  // result.receipt => transaction receipt object, which includes gas used

  // We can loop through result.logs to see if we triggered the Transfer event.
  for (var i = 0; i < result.logs.length; i++) {
    var log = result.logs[i];

    if (log.event == "Transfer") {
      // We found the event!
      break;
    }
  }
}).catch(function(err) {
  // There was an error! Handle it.
});
4
  • Yes, but the problem here is that you pay for the information (the payable function), and everybody can get the information by tracking the event. Another approach somebody else is suggesting, that I call the transaction first and fire '.call()', this also does not make sense because why would you pay when you can get it free?
    – coindevbw
    Nov 22, 2017 at 21:40
  • 3
    All info transactioned over the blockchain is publicly accesible. Nov 22, 2017 at 22:42
  • do you really think private values calculated only for the request is also on the transaction?
    – coindevbw
    Nov 23, 2017 at 16:45
  • 1
    You cannot use call with a transaction. That's just against its definition. Jan 26, 2018 at 8:18
7

I have no points to comment yet, so I will paste a link to a very simple solution from Force Hero.

In a nutshell:

const tx = await contract.transfer(...args); // 100ms
const rc = await tx.wait(); // 0ms, as tx is already confirmed
const event = rc.events.find(event => event.event === 'Transfer');
const [from, to, value] = event.args;
console.log(from, to, value);

Hope it helps someone.

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