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

Merged
merged 17 commits into from Dec 8, 2017

Conversation

@axic
Member

axic commented Feb 6, 2017

Replaces #140.

@axic

This comment has been minimized.

Show comment
Hide comment
@axic

axic Feb 6, 2017

Member

I wonder if it would make sense adjusting CALL (and CALLCODE, DELEGATECALL) to indicate a REVERT.

Currently, CALL (& co) will return 1 on success and 0 in in case it failed. Perhaps code 2 could be returned in case of REVERT. Downside is that Solidity contracts would not be backwards compatible.

Likely it would make sense to take this into consideration when designing the successor of CALL and not touching the current one.

Member

axic commented Feb 6, 2017

I wonder if it would make sense adjusting CALL (and CALLCODE, DELEGATECALL) to indicate a REVERT.

Currently, CALL (& co) will return 1 on success and 0 in in case it failed. Perhaps code 2 could be returned in case of REVERT. Downside is that Solidity contracts would not be backwards compatible.

Likely it would make sense to take this into consideration when designing the successor of CALL and not touching the current one.

@chriseth

This comment has been minimized.

Show comment
Hide comment
@chriseth

chriseth Feb 7, 2017

Contributor

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 CALL opcode and the callee provided failure data, the data is discarded.

Contributor

chriseth commented Feb 7, 2017

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 CALL opcode and the callee provided failure data, the data is discarded.

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Feb 7, 2017

Collaborator

Returning 0 from a CALL that ends in a REVERT seems reasonable, though it would be easier to check returned data if contracts had a way to detect the length of returned data; at present they could at least zero the return memory area before calling (or we could HF to specify CALL does that).

Collaborator

Arachnid commented Feb 7, 2017

Returning 0 from a CALL that ends in a REVERT seems reasonable, though it would be easier to check returned data if contracts had a way to detect the length of returned data; at present they could at least zero the return memory area before calling (or we could HF to specify CALL does that).

@axic

This comment has been minimized.

Show comment
Hide comment
@axic

axic Feb 7, 2017

Member

I agree it is better to make this low impact by not touching CALL at the moment. External callers (i.e. users of the RPC) will still be able distinguish and retrieve and error message.

Member

axic commented Feb 7, 2017

I agree it is better to make this low impact by not touching CALL at the moment. External callers (i.e. users of the RPC) will still be able distinguish and retrieve and error message.

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Feb 7, 2017

Collaborator

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?

Collaborator

Arachnid commented Feb 7, 2017

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?

@axic

This comment has been minimized.

Show comment
Hide comment
@axic

axic Feb 7, 2017

Member

I mean that CALL wouldn't differentiate and would ignore the return value. However, the return value would still be available through external calls, such as a transaction or anything invoked via an RPC.

Member

axic commented Feb 7, 2017

I mean that CALL wouldn't differentiate and would ignore the return value. However, the return value would still be available through external calls, such as a transaction or anything invoked via an RPC.

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Feb 7, 2017

Collaborator

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?

Collaborator

Arachnid commented Feb 7, 2017

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?

@chriseth

This comment has been minimized.

Show comment
Hide comment
@chriseth

chriseth Feb 7, 2017

Contributor

@Arachnid if revert writes to the same memory area as return then the caller has to be able to distinguish the two cases. Since the ABI does not have an unused bit, I don't see a good way to put the distinction into the data. The only other option (apart from a new call opcode) I see is returning 2 in case of reversion, but that would signal a success condition to older code, which is probably not what you would want.

Contributor

chriseth commented Feb 7, 2017

@Arachnid if revert writes to the same memory area as return then the caller has to be able to distinguish the two cases. Since the ABI does not have an unused bit, I don't see a good way to put the distinction into the data. The only other option (apart from a new call opcode) I see is returning 2 in case of reversion, but that would signal a success condition to older code, which is probably not what you would want.

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Feb 7, 2017

Collaborator

@Arachnid if revert writes to the same memory area as return then the caller has to be able to distinguish the two cases. Since the ABI does not have an unused bit, I don't see a good way to put the distinction into the data.

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.

Collaborator

Arachnid commented Feb 7, 2017

@Arachnid if revert writes to the same memory area as return then the caller has to be able to distinguish the two cases. Since the ABI does not have an unused bit, I don't see a good way to put the distinction into the data.

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.

@chriseth

This comment has been minimized.

Show comment
Hide comment
@chriseth

chriseth Feb 7, 2017

Contributor

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).

Contributor

chriseth commented Feb 7, 2017

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).

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Feb 7, 2017

Collaborator

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).

Collaborator

Arachnid commented Feb 7, 2017

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).

@axic axic referenced this pull request Feb 7, 2017

Closed

All Core Devs Meeting 10 Agenda #5

@chriseth

This comment has been minimized.

Show comment
Hide comment
@chriseth

chriseth Feb 8, 2017

Contributor

@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.

Contributor

chriseth commented Feb 8, 2017

@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.

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Feb 8, 2017

Collaborator

@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'.

Collaborator

Arachnid commented Feb 8, 2017

@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'.

@VoR0220

This comment has been minimized.

Show comment
Hide comment
@VoR0220

VoR0220 Feb 8, 2017

@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.".

VoR0220 commented Feb 8, 2017

@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

This comment has been minimized.

Show comment
Hide comment
@chriseth

chriseth Feb 9, 2017

Contributor

@Arachnid @VoR0220 of course that can be done but we still need a flag to indicate whether the data is an error or regular return data.

Contributor

chriseth commented Feb 9, 2017

@Arachnid @VoR0220 of course that can be done but we still need a flag to indicate whether the data is an error or regular return data.

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Feb 9, 2017

Collaborator

@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.

Collaborator

Arachnid commented Feb 9, 2017

@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.

@chriseth

This comment has been minimized.

Show comment
Hide comment
@chriseth

chriseth Feb 9, 2017

Contributor

@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.

Contributor

chriseth commented Feb 9, 2017

@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.

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Feb 9, 2017

Collaborator

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.

Collaborator

Arachnid commented Feb 9, 2017

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.

@chriseth

This comment has been minimized.

Show comment
Hide comment
@chriseth

chriseth Feb 9, 2017

Contributor

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.

Contributor

chriseth commented Feb 9, 2017

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.

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Feb 9, 2017

Collaborator

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.

Collaborator

Arachnid commented Feb 9, 2017

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.

@vbuterin

This comment has been minimized.

Show comment
Hide comment
@vbuterin

vbuterin Feb 9, 2017

Collaborator

Looks good to me.

Collaborator

vbuterin commented Feb 9, 2017

Looks good to me.

@Souptacular Souptacular referenced this pull request Feb 10, 2017

Closed

Metropolis Plan Discussion #4

0 of 3 tasks complete

@pirapira pirapira referenced this pull request Feb 10, 2017

Closed

Byzantium changes #229

12 of 12 tasks complete
@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Feb 13, 2017

Collaborator

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.

Collaborator

Arachnid commented Feb 13, 2017

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.

@pirapira pirapira referenced this pull request Feb 13, 2017

Closed

EIP140: REVERT #232

@jo-tud jo-tud referenced this pull request Oct 13, 2017

Merged

Byzantium HF #162

@pipermerriam

This comment has been minimized.

Show comment
Hide comment
@pipermerriam

pipermerriam Oct 18, 2017

Member

@Souptacular

Can this be merged now that Byzantium is live?

Member

pipermerriam commented Oct 18, 2017

@Souptacular

Can this be merged now that Byzantium is live?

@pipermerriam pipermerriam referenced this pull request Oct 20, 2017

Merged

Byzantium Fork Rules #123

9 of 9 tasks complete

@pirapira pirapira referenced this pull request Oct 23, 2017

Open

Apply Byzantium changes #459

0 of 10 tasks complete
Show outdated Hide outdated EIPS/eip-140.md
Show outdated Hide outdated EIPS/eip-140.md
Show outdated Hide outdated EIPS/eip-140.md
Show outdated Hide outdated EIPS/eip-140.md
@pirapira

I left some small comments. After a week of silence, I'll apply those cosmetic changes myself.

@frangio

This comment has been minimized.

Show comment
Hide comment
@frangio

frangio Nov 17, 2017

The "Backwards Compatibility" section seems to imply that REVERT is treated as an invalid opcode for a contract created before the Byzantium hard fork.

Is this interpretation correct?

frangio commented Nov 17, 2017

The "Backwards Compatibility" section seems to imply that REVERT is treated as an invalid opcode for a contract created before the Byzantium hard fork.

Is this interpretation correct?

@pirapira

This comment has been minimized.

Show comment
Hide comment
@pirapira

pirapira Nov 20, 2017

Member

@frangio you are correct with how you interpret the section. I'll leave a comment there.

Member

pirapira commented Nov 20, 2017

@frangio you are correct with how you interpret the section. I'll leave a comment there.

Show outdated Hide outdated EIPS/eip-140.md

pirapira added some commits Nov 30, 2017

@pirapira

This comment has been minimized.

Show comment
Hide comment
@pirapira

pirapira Nov 30, 2017

Member

I think this EIP should say

If block.number >= BYZANTIUM_FORK_BLKNUM

I wait for another week and apply the change.

Member

pirapira commented Nov 30, 2017

I think this EIP should say

If block.number >= BYZANTIUM_FORK_BLKNUM

I wait for another week and apply the change.

pirapira and others added some commits Dec 1, 2017

@axic axic changed the title from Draft EIP for the REVERT opcode to REVERT instruction Dec 5, 2017

@pirapira

Looks good to me.

@pirapira pirapira merged commit 75edcfd into ethereum:master Dec 8, 2017

@pirapira pirapira deleted the axic:revert branch Dec 8, 2017

@cleanunicorn

This comment has been minimized.

Show comment
Hide comment
@cleanunicorn

cleanunicorn Mar 6, 2018

If REVERT is called with a message where is this returned?
Will this be returned in eth_getTransactionReceipt for that transaction?

cleanunicorn commented Mar 6, 2018

If REVERT is called with a message where is this returned?
Will this be returned in eth_getTransactionReceipt for that transaction?

@pirapira

This comment has been minimized.

Show comment
Hide comment
@pirapira

pirapira Mar 6, 2018

Member

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).

Member

pirapira commented Mar 6, 2018

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).

@aerth aerth referenced this pull request Jun 5, 2018

Merged

HF7 @ 36050 #24

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment