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
REVERT instruction #206
REVERT instruction #206
Conversation
EIPS/eip-draft_revert_opcode.md
Outdated
@@ -0,0 +1,47 @@ | |||
## Preamble | |||
|
|||
EIP: <to be assigned> |
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 assume we did assign 140 for this, given issue 140 was accepted.
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.
You can either assign the issue or PR number. In this case it would be better to assign the issue # since that is what it has been referred to most widely.
I wonder if it would make sense adjusting Currently, Likely it would make sense to take this into consideration when designing the successor of |
For the sake of backwards compatibility, anything that reverts state changes should signal a "failure" to the caller. Since we cannot distinguish the two cases where the callee did provide a return value and where it didn't, I would propose to postpone that feature until we have a means to signal this e.g. in a new call opcode: If the caller used the |
Returning 0 from a |
I agree it is better to make this low impact by not touching |
If we add it without any return support initially, then it'll be even more complex to add it later. Shouldn't we try and solve this once-and-for-all? |
I mean that |
Wouldn't it make more sense to have CALL copy the return value, though? Does Solidity currently make any assumptions about the return memory area in case of a failed call? |
@Arachnid if |
If CALL returns 0, the data area contains any return data from a REVERT. If it returns 1, the data area contains any return data from a normal return. Both have the issue that you can't directly determine the return data length, but that's orthogonal. |
That's not correct: If CALL returns 0, the data area either contains the data from the revert or whatever was there before (because it was an OOG). |
Right; just like if call returns 1 - the data area either contains the return data, or whatever was there before (if the return length was 0). |
@Arachnid the difference is that currently, with contracts adhering to the ABI, you always know the type of the contents from the type of the contract. |
@chriseth That could still be the case - just extend the ABI spec to specify an ABI definition for error returns, too. The default would be 'null'. |
@chriseth there is a good way around this by just creating a new type in the ABI, that type being the "error" type. I fully agree with @Arachnid here. An error type has been sorely needed and missed here and has created much confusion for newcomers as to why the only error they ever get with their solidity code is "invalid jump dest.". |
@chriseth But we already have that flag - the return code of CALL. If it's zero, the return data - if any - follows the error ABI. If it's nonzero, the return data - if any - follows the return ABI. |
@Arachnid sure, but we have three situations instead of two: OOG, revert, success. There is currently no way to distinguish between OOG and revert, so new code that wants to read the revert error code has to clear the output area beforehand. In any case, it is really messy and complicated and thus I would propose to move the feature of actually reading the error data (not supplying it) to a new call opcode. |
But what I'm saying is that the issue of "was any data returned" is orthogonal to returning the data; we already have this problem (and the need to zero out the data before calling) with regular returns, where the called contract could return 0 bytes of data and the caller wouldn't know. It makes far more sense to me to just return error data using the existing mechanism, and then add a 'RETURNDATALEN' (or similar) opcode afterwards. |
Sure, but I would say that something like "returndatalen" should be a feature of the call opcode. I don't think it is a nice design if you can check the size of the returned data at any time after the call. This is another word of state the VM (and all related tools) have to keep. |
I agree - a better CALL opcode would be an improvement. But I don't see why that means that CALL shouldn't return error data with the introduction of REVERT. We shouldn't make it impossible just because the current design is not ideal. |
Looks good to me. |
Update post all-core-devs meeting: The consensus was that REVERT should take the same arguments as RETURN, and CALL should return data provided to REVERT, with another EIP to be opened on improving handling of return data from CALL and other related opcodes. |
Can this be merged now that Byzantium is live? |
EIPS/eip-140.md
Outdated
|
||
EIP: 140 | ||
Title: REVERT instruction in the Ethereum Virtual Machine | ||
Author: Alex Beregszaszi, Nikolai Mushegian (nikolai@nexusdev.us) |
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.
EIPS/eip-140.md
Outdated
|
||
## Motivation | ||
|
||
Currently this is not possible. There are two practical ways to revert a transaction from within a contract: running out of gas or executing an invalid instruction. Both of these options will consume all remaining gas. Additionally, reverting a transaction means that all changes, including LOGs, are lost and there is no way to convey a reason for aborting a transaction. |
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.
reverting a transaction
aborting a transaction
We are here talking about something smaller than a transaction. Perhaps "reverting an EVM execution" and "aborting an execution"?
EIPS/eip-140.md
Outdated
|
||
## Specification | ||
|
||
The `REVERT` instruction is introduced at `0xfd`. It expects two stack items, the top item is the `memory_offset` followed by `memory_length`. It does not return anything because it stops execution. |
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.
return anything
is ambiguous. It might be talking about return data to the caller, or returned word on top of the stack.
Perhaps It does not produce any stack elements because it stops execution
?
EIPS/eip-140.md
Outdated
should: | ||
- return `726576657274206d657373616765` as `REVERT` data, | ||
- the storage at key `0x0` should be left as unset and | ||
- use 20024 gas in total. |
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.
20024
here should be interpreted as decimal while 726576657274206d657373616765
might be hex.
Would it hurt to add 0x
in front of the hex?
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 left some small comments. After a week of silence, I'll apply those cosmetic changes myself.
The "Backwards Compatibility" section seems to imply that Is this interpretation correct? |
@frangio you are correct with how you interpret the section. I'll leave a comment there. |
EIPS/eip-140.md
Outdated
|
||
## Backwards Compatibility | ||
|
||
This change has no effect on contracts created in the past. |
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.
This is not true if those contracts contain 0xfd
as an instruction.
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'll add unless they contain
0xfd as an instruction
after a week of silence.
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.
Okay, that is a pretty important difference! IIRC Solidity had been emitting 0xfd
opcodes several months before Byzantium, so there were many contracts out there whose behavior changed after being created.
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.
1 week of silence. :)
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.
Added.
I think this EIP should say
I wait for another week and apply the change. |
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.
Looks good to me.
If |
The message is returned to the caller if the caller is also a program in EVM. Transaction receipts do not contain the REVERTed messages (that was once considered). |
Replaces #140.