4

It seems that geth and ganache-cli (testrpc) have differing behaviour on failed transactions. Suppose

(1) I have a trivial smart contract with a variable, a getter&setter, and an event. The setter takes a boolean argument, and if that argument is false, it fails. Otherwise, it sets the variable and fires and event.

(2) I have a test that does get()/set(true,42)/get()/set(false,84)/get()

(3) when I run with ganache-cli as a backend, the second set() produces a VM revert exception

(4) when I run with geth, I get a transaction hash, and looking it up, yields a receipt with empty log (so the tran didn't run). Further, the subsequent get() shows that the variable has not been changed.

(5) by contrast, the first set() yields a tranhash/receipt from both backends, and of course, the log is there and I can find the events.

To sum up: running against both backends, the state-behaviour of ethereum is the same. BUT against geth, we get no exception on the second set(), whereas with ganache-cli, we DO get an exception.

I don't know whether this is expected behaviour. But I do know this: I checked both openzeppelin-solidity and gnosis/MultiSigWallet, and both of them have unit-tests that expect the ganache-cli behaviour, and fail when run against geth.

One of the two is wrong here. If I'd make a guess, it's ganache-cli. But OTOH, two well-respected projects both count on this behaviour.

Not sure what to think. Anybody got a clue about this?

contract Bar
{
  uint n ;
  event Argle(uint arg);
  function argle_int(uint arg) internal {
    n = arg ;
  }

  function argle(bool pass, uint arg) public {
    Argle(arg) ;
    require(pass) ;
    argle_int(arg);
  }

  function get() public view returns (uint) {
    return n ;
  }
}
0

sendTransaction to ganache-cli will synchronously return the revert or the return value of the function. This is not how it works in a real network which is asynchronous in nature. AFAIK, there is no way to configure this in ganache-cli.

As stated by benjamincburns in https://github.com/trufflesuite/ganache-cli/issues/412, the focus seems to be in implementing the JSON RPC pedantically, but not necessarily in behaving identically to geth or partiy.

As I said over there, our goal isn't to behave identically to geth or parity, but rather to somewhat pedantically implement the JSON RPC spec."

If you want that your tests work for both, you'll have to check for both cases:

  • catch the throw (ganache-cli)
  • wait for transaction receipt and check for status 0x00/0x01 (geth / partiy / ...).

IMHO, this is rather a workaround and ganache-cli should behave in the same way like geth/parity do.

Btw. you should always test your code at least once with a real node.

  • IMHO it is an error to depend on the sync nature of ganache when writing tests. It is better to always wait for the receipt. – Ismael Mar 25 '18 at 0:19
  • Yes, you‘re right. The correct way in a real network is to wait for the receipt. I‘ve modified the answer to reflect this. – ivicaa Mar 25 '18 at 2:38
  • I agree. My question was really: "why does ganache-cli do this, and is there a way to make it behave as geth does?" B/c the divergence in behaviour (not the only one) is not a good thing. – Chet Mar 26 '18 at 17:53
  • AFAIK there is no way to configure it to behave asynchronously like real node software does. They're design goal doesn't seem to be to simulate the behaviour 1:1 but to pedantically implement the JSON RFC spec. (see -> github.com/trufflesuite/ganache-cli/issues/412 : "As I said over there, our goal isn't to behave identically to geth or parity, but rather to somewhat pedantically implement the JSON RPC spec.") – ivicaa Mar 26 '18 at 18:23
  • I've extended the answer above to include this information. – ivicaa Mar 26 '18 at 18:31

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.