Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Bug fix: Provide reason for calls #2340

Closed
wants to merge 3 commits into from
Closed

Conversation

eggplantzzz
Copy link
Contributor

Fixes #2321

Previously, reasons for reverts were provided only when a "send" was reverted. This PR extracts a method that parses out a revert reason and uses it when "call"s revert as well.

@eggplantzzz
Copy link
Contributor Author

NOTE: I'm not sure I fully understand the role of the file ./packages/truffle-contract/lib/override.js so it is quite possible that the architecture here should be tweaked a bit.

@coveralls
Copy link

coveralls commented Aug 27, 2019

Coverage Status

Coverage increased (+0.03%) to 70.532% when pulling 3797858 on bug-provide-reason into a5b121e on develop.

Copy link
Contributor

@CruzMolina CruzMolina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get a test for this?

@eggplantzzz
Copy link
Contributor Author

Sounds like a great idea, comin' right up!

@CruzMolina CruzMolina self-requested a review August 28, 2019 15:24
Copy link
Contributor

@CruzMolina CruzMolina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎭

@gnidan
Copy link
Contributor

gnidan commented Aug 28, 2019

@cgewecke if you're around, do you remember if there was a reason we didn't implement this in the first place?

@cgewecke
Copy link
Contributor

cgewecke commented Aug 28, 2019

@eggplantzzz @gnidan

Calls don't return a receipt with a status and that's how we (or web3) detect whether or not a failure occurred. If you ran these changes against geth or ganache with --noVMErrorsOnRPCResponse I think the view test wouldn't work. Not sure what the various client responses are though, it could be the reason string data? It could vary depending on the return sig in Solidity?

Very unclear to me if require should be used in view methods and last week I opened an issue at EthPM suggesting we amend EIP1319 to define 'null' return values for its Read API because of the lack of clarity around how this stuff is supposed to work. I'm not sure what's normal here.

WDYT?

@eggplantzzz
Copy link
Contributor Author

Are you basically saying that against a node in production that any call that reverts won't be caught by that catch in the call code? I mean, as it stands currently. Is Ganache modeling incorrectly or is there some other thing that I'm missing here?


describe("revert reasons", function() {
let RevertingContract;
const providerOptions = { vmErrorsOnRPCResponse: true }; // <--- TRUE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eggplantzzz If you set this option to false (e.g emulate production nodes) does the view test pass?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The view test fails when I set it to false. I think it is true by default as it passes when I don't give any options to util.setUpProvider...weird. Actually this got lifted from the errors test in truffle-contract. Maybe it should be removed.

Copy link
Contributor Author

@eggplantzzz eggplantzzz Aug 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the point here I suppose is that I wasn't aware that this was production node behavior, in which case this PR probably shouldn't go through. Although I can see value in it for testing purposes I suppose. I dunno, what do you think @gnidan? You can make the call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the tests are crazy because there are two clients (geth and ganache) and then ganache can be run in these two modes. And responses vary across those. IIRC responses varied depending on whether ganache was run as a provider or a server when these tests were written, so it's a mess. There was also a lot of discussion about what ganache's default run mode should be . . .

I think the risk here is that TC makes a design pattern seem like it will work in the wild and people don't do due diligence re: their tests passing vs. a reference client.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that is my worry as well. It seems like it could be useful but it also doesn't seem good to create expectations about what will happen in prod.

Copy link
Contributor

@gnidan gnidan Aug 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gosh I forgot that the JSON RPC completely excludes any kind of status information at all for eth_call.

I concur with @cgewecke about this being a dangerous idea. I think we should hold off until we do something like run the call though ethereumjs-vm ourselves to get this data.

(cc @haltman-at to try to put the idea in your head)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh geez, I didn't realize this was an issue -- thanks for notifying me, because this actually potentially affects some stuff I've been thinking about.

But, I'm a little confused here. At least with Ganache, running normally, on a revert, the response -- whether to a call or a sendTransaction -- does not have the usual form specified by the RPC, but rather puts all its info in an error field, and if you dig into that you can find the revert message (both decoded by Ganache and in its raw binary form). In the case of a sendTransaction, this allows getting the return value (which normally isn't possible); and in the case of a call, this allows getting the status (which normally isn't possible).

Being largely unfamiliar with the other ethereum clients, I didn't realize that this behavior was not universal, or could be turned off in Ganache, forcing JSON-RPC-conforming (but less informative) responses even on a revert. Is that indeed the case? Am I understanding this correctly? @cgewecke, can you provide any clarity here? I would really like to know when I should expect a standard RPC response even on error, vs when I should expect this other error format. (Or are there other alternatives out there that I haven't even seen...?) Or at the least I would like to know for a certainty whether I do potentially have to handle both. (Not that I'm going to get to this stuff for quite a while, but...)

Anyway thank you! I'd been wondering about this question so I'm glad I was tagged here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@haltman-at The production clients do not attach an error field. That's a convenience ganache/testrpc added in order to be an effective chain simulator for tests in the days before transaction receipts included a status field.

Truffle has fixtures to run tests against an insta-mining geth client (@CruzMolina knows all about) and ganache has a flag you can enable to make it more geth-like as well. (See above)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, I totally didn't realize. So that's not a standard thing at all, huh. OK, thanks a bunch, I'll have to account for that!

@cgewecke
Copy link
Contributor

cgewecke commented Aug 28, 2019

against a node in production that any call that reverts won't be caught by that catch in the call code

@eggplantzzz yes, I think this is correct. The tests are using ganache in a "pre-byzantium" mode which errors the client response. This behavior was necessary before status fields were added to the receipts to do any sort of meaningful contract testing, but it's not how production clients respond.

@eggplantzzz
Copy link
Contributor Author

I am going to close this for now.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

err.reason undefined when require() fails with reason in a view
6 participants