-
Notifications
You must be signed in to change notification settings - Fork 5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prefer receipt status when checking for OOG #3189
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for proposing this PR! I've added a comment with some questions about the extended conditions.
if (!receipt.outOfGas && | ||
(!gasProvided || gasProvided !== utils.numberToHex(receipt.gasUsed)) && | ||
(!gasProvided || !isOOG) && | ||
(receipt.status === true || receipt.status === '0x1' || typeof receipt.status === 'undefined')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- What exactly are the thoughts behind
hasStatus
? (Because thestatus
field does always exists in post Byzantium hard fork chains) - The
if
conditions who check the status based on the hex value e.g.:receipt.status === '0x1'
aren't required because thereceipt.status
property does get type casted to a boolean value type in theoutputTransactionReceiptFormatter
of the usedgetTransactionReceipt
method.- If the status property is of type
undefined
ornull
is no type cast applied.
- If the status property is of type
- Shouldn't
isOOG
be like this:isOOG = !receipt.status && gasProvided === utils.numberToHex(receipt.gasUsed);
? - Shouldn't we add here the
isOOG
condition as well?- I would propose those conditions:
if(receipt.status === true || receipt.status === null || typeof receipt.status === 'undefined' ) { // resolve with receipt } else { if (gasProvided === utils.numberToHex(receipt.gasUsed)) { // reject with out of gas } else { // reject with reverted by EVM } }
- I would propose those conditions:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly are the thoughts behind hasStatus
My thought is that the reason for the original correction in #3123 is to support non-byzantium chains where gasUsed === gasSent is (almost) logically equivalent to status === false. What is your view of this?
'0x1' aren't required
👍 Will remove
Shouldn't isOOG be like this:
isOOG = !receipt.status...
That was my initial thought as well. But it's a problem when people combine estimateGas
with tx's that actually revert. In that case receipt status is false and exact gas is consumed. See this added test. My theory is that preferring the status / ignoring the gas is closest to what the 1.2.1 behavior is.
If you look at what GabMontes suggests in #3175, there are other receipt fields they're looking at to disambiguate real OOG from revert-like transaction failure. I'm ambivalent about adding those without being able to add a test against an ETC client here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! I just realized the test has a copy-pasta mistake in it. Let me investigate this further...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed the test for using perfect gas to fuel a tx which reverts because it's not possible to get an estimate in that case with the simple contracts here.
- ganache rejects
estimateGas
with: Error: Returned error: execution error: revert - geth rejects
estimateGas
with: exceeds allowance ... or always failing transaction
Tbh this may always happen.
@nivida What is |
Another quick note. If these changes need careful review and we'll need to take our time getting this right, maybe #3123 should be reverted as a stop-gap and a hot-fix of uncontroversial changes published early next week. At the moment this very basic, common tx throws an error: web3.eth.sendTransaction({
from: accounts[0],
to: accounts[1],
value: web3.utils.toWei('1', 'ether'),
gas: 21000
}) And MEW has had to undo their attempt to upgrade from 1.2.1. |
True that we should support non-byzantium chains as well. Means this condition would be what we want to have?: if(receipt.status === true || ((typeof receipt.status === 'undefined' || receipt.status === null) && gasProvided !== utils.numberToHex(receipt.gasUsed))) {
// resolve with receipt
} else {
if (gasProvided === utils.numberToHex(receipt.gasUsed)) {
// reject with out of gas
} else {
// reject with reverted by EVM
}
}
I've tried to find the corresponding node who is returning null but can't find it. Let us keep the
I think we will manage to merge and release this PR this week. Let us see what the state of the open PRs is on Thursday. If those still do take some days will I quickly set up a hotfix PR and release it on Thursday evening (CEST). |
@nivida I see what you're saying and your approach is simpler / cleaner. But what about all the other conditions like |
We can keep the
The |
@nivida Why is Consider this case:
How does your re-writing handle that? |
There is in my view of point no reason for it but we can keep it just to be sure we do not break anything.
In the else case the first if condition. |
if(receipt.status === true || ((typeof receipt.status === 'undefined' || receipt.status === null) && gasProvided !== utils.numberToHex(receipt.gasUsed))) {
// resolve with receipt
} else {
if (gasProvided === utils.numberToHex(receipt.gasUsed)) {
// reject with out of gas
} else {
// reject with reverted by EVM
}
} @nivida As I read this when status is false and gas usage is exact it will OOG instead of revert. |
This would be the correct behavior as mentioned in issue #3175:
Edit: |
@nivida Ah! Now I see what our disagreement is finally.
I don't think this is right. Consider the bug we are currently fixing where status is true and gas usage is exact. It should succeed. In the inverse case it should revert, not be OOG. It's not perfect but it's what's closest current behavior. |
This does work because the parent IF condition will be |
@nivida To me it seems like the behavior for
Why do you feel changing the symmetry is better? |
@cgewecke The logic I have proposed:
This logic would fix the OOG and revert detection for all post-Byzantium chains. To determine the success or failure of a transaction for pre-Byzantium chains can we use Edit:
I mean we do not have any other possibility for pre-Byzantium chains and the post-Byzantium case can get improved more with implementing the revert reason msg detection and decoding. |
@nivida Ok yes I think your analysis looks correct 💯 Trying to be quite cautious about changes here - tbh I'm completely paranoid about this because I think people have built their own error handling logic around Web3's existing behavior whether it's "correct/makes sense" or not. A small thing that might make this +/- non-breaking is to keep the current failure case evaluation order but modify the messages so they're clearer about what happened.
It also looks like Parity supports pre-byzantium with
We should talk about how to do this on 1.x, I'm going to open a design discussion issue about it. |
@cgewecke I think we have now new possibilities to improve the error handling of a transaction because of the added |
@nivida Agree, I will close here and re-open this as an extension of the new revert behavior. |
Description
If receipt has a valid (e.g
true
orfalse
) value, it cannot be OOG anymore. This is slightly different than what is suggested in #3175 by @nivida, and does not include the additional contract data checks suggested by @gabmontes. Pinging both of you for review...RE:
This PR includes the second case as a test which expects
revert
. It's possible for someone to use a perfect estimate for a method that callsrequire
for example. I think this is closest the currently expected behavior since the gas check wasn't really being done before.Fixes #3175
Type of change
Checklist:
npm run test
with success and extended the tests if necessary.npm run build
and tested the resulting file fromdist
folder in a browser.