-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Add EIP: Enhanced RETURN opcodes #9315
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
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
6f1a968
add eip without number yet to be assigned
jhweintraub 8261774
Update and rename eip-tbd.md to eip-7877.md
SamWilsn 74cf0ad
fix linter issues
jhweintraub 0f914a2
more lint fix attempts
jhweintraub 6360f7e
spelling and formatting
jhweintraub File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
--- | ||
eip: 7877 | ||
title: Enhanced RETURN opcodes | ||
description: Deprecate RETURN opcode in favor of new opcodes that allow returning data from various locations without first having to write to memory. | ||
author: Josh Weintraub (@jhweintraub) | ||
discussions-to: https://ethereum-magicians.org/t/eip-7877-new-m-s-t-rreturn-opcodes/22731 | ||
status: Draft | ||
type: Standards Track | ||
category: Core | ||
created: 2025-01-31 | ||
requires: 6, 1153, 3855 | ||
--- | ||
|
||
## Abstract | ||
|
||
This EIP specifies a series of new `RETURN` opcodes which allow the user to specify which data location to return from | ||
instead of defaulting to returning from memory. | ||
|
||
## Motivation | ||
|
||
With the introduction of transient storage, many smart contracts have begun to store data using the new transient opcodes to optimize for gas usage, whereby a callback | ||
involves returning the data previously stored transiently. However, the current `RETURN` opcode only allows for returning sequential bytes in memory. This requires | ||
developers to incur additional gas overhead by manually writing data from transient storage to memory before returning, | ||
incuring both an additional memory expansion and opcode cost from complicated for-loops. Similar | ||
inefficiencies already occur when attempting to return data already placed in storage. This EIP attempts to rectify | ||
this by allowing developers to optimize their code by deciding where to return data from directly, instead of requiring | ||
the intermediate step of first copying the data to memory. | ||
|
||
## Specification | ||
|
||
This EIP introduces 3 new opcodes as well as renaming/aliasing an existing one. | ||
|
||
``` | ||
SRETURN (0xf6) | ||
TRETURN (0xf7) | ||
RRETURN (0xf8) | ||
|
||
RETURN -> MRETURN (0xf3) | ||
``` | ||
|
||
The `MRETURN` opcode is a rename of `RETURN`, whereby sequential bytes in memory are returned. It will operate exactly as it currenty does as of the Cancun hard-fork, and its gas cost will remain the same. | ||
|
||
`RRETURN` operates similar to `MRETURN`. It pops two items off the stack, an offset to begin reading bytes from in the | ||
existing `RETURNDATA` buffer, and a number of bytes to return. Those bytes are used to overwrite the existing `RETURNDATA` buffer and then a return to the previous function is performed. | ||
|
||
`SRETURN` and `TRETURN` operate similarly, except on storage and transient respectively. It pops two items off the stack, | ||
a slot number to begin reading from, and a number of sequential slots to return from. Ex: `SRETURN(0x0, 0x40)` returns the 64 bytes of data in slots [0, 1], and `TRETURN(0x0, 0x40)` returns the data in transient storage slots [0, 1]. Since the | ||
existing `S/TLOAD` opcodes already return 32-bytes, having the opcode return data in chunks of 32-bytes should make implementation by assembly/compiler much simpler. | ||
If the length parameter is a zero, then only the initial slot value should be returned, so `SRETURN(0x00, 0x00)` returns the value at storage slot 0. | ||
|
||
The cost for these opcodes should be similar to the cost of accessing data now. | ||
|
||
``` | ||
SRETURN = (number_of_cold_slots) * 2100 + (numer_of_warm_slots * 100) | ||
TRETURN = number_of_slots * 100 | ||
|
||
RRETURN = cost of RETURNDATACOPY without memory_expansion cost | ||
|
||
minimum_word_size = (size + 31) / 32 | ||
|
||
static_gas = 3 | ||
dynamic_gas = 3 * minimum_word_size | ||
|
||
overall = static_gas + dynamic_gas | ||
``` | ||
|
||
## Rationale | ||
|
||
Allowing for more targeted return opcodes allows for saving gas at all levels of smart contract optimization by eliminating | ||
the intermediate steps of first writing any data to memory before returning. In events where this data may be large, this can result in significant gas savings. These opcodes can be built into the Solidity compiler directly so that all contracts | ||
can take advantage of them. Similarly, by making return more explicit it allows for better static analysis by avoiding messy memory allocations. | ||
|
||
There is precedent for these changes. | ||
|
||
EIP-3855: Introducing `PUSH0` opcode to optimize away alternative methods of pushing 0 onto the stack. | ||
|
||
EIP-6: Renaming `SUICIDE` to `SELFDESTRUCT` without changing functionality. | ||
|
||
## Backwards Compatibility | ||
|
||
There are no backwards compatibility concerns, as `MRETURN` will utilize the same gas cost and opcode as `RETURN` does now. Due to EOF, it is suggested that these changes be | ||
activated in future EVM version once EOF has been fully implemented. | ||
|
||
## Security Considerations | ||
|
||
There are no security considerations as it is fully backwards compatible, and reduces potential attack space through simplified bytecode. | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md). |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
do you intend to make this EIP
require
EOF parent EIP (that lists all EOF eips)? if so then add it in require sectionUh oh!
There was an error while loading. Please reload this page.
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.
no because EOF is not strictly requried to implement first but I assumed that due to the complexity of EOF that any opcode changes would be considered until after that implementation is finished. Since I know EOF makes versioning and future upgrades simpler it seemed logical to me to include that in the document.