-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Add EIP: MLOAD8 and CALLDATALOAD8 Opcodes #11038
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
+118
−0
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
3a4a460
Add files via upload
Helkomine efc788c
Merge branch 'ethereum:master' into master
Helkomine 61d0b71
Add MLOAD8 and CALLDATALOAD8 opcodes
Helkomine f947fc9
MLOAD8 and CALLDATALOAD8 instructions
Helkomine e57b1d6
Update EIP-XXXX with specific opcode references
Helkomine aaab2fc
Introduce new opcodes for single-byte calldata access
Helkomine f490416
Update eip-XXXX.md
Helkomine bd89225
Update eip-XXXX.md
Helkomine e744c15
Update eip-XXXX.md
Helkomine c018405
Merge branch 'ethereum:master' into master
Helkomine 34e0f6c
Add placeholder numbers to pass the eth-bot check
Helkomine 5e819b8
Revise the title information.
Helkomine 8c13971
Temporary update of EIP number
Helkomine 229f460
Edit markdown linter
Helkomine 0a616f7
Edit markdown linter
Helkomine 1e02ee3
Edit markdown linter
Helkomine 1d7af9c
Edit markdown linter
Helkomine a5ed4dc
Edit reference
Helkomine 8b8b250
Remove reference
Helkomine 6c60fa0
Update and rename eip-9999.md to eip-8120.md
Helkomine 55b461f
EIP Style Editing
Helkomine a761a38
Fix markdown linter errors
Helkomine f2f604c
Merge branch 'ethereum:master' into master
Helkomine 8108bac
Fix the line spacing and add TODO note.
Helkomine d663137
Update eip-8120.md
Helkomine 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,118 @@ | ||
| --- | ||
| eip: 8120 | ||
| title: MLOAD8 and CALLDATALOAD8 Opcodes | ||
| description: Adds EVM opcodes for efficient single-byte memory and calldata loads. | ||
| author: Helkomine (@Helkomine) | ||
| discussions-to: https://ethereum-magicians.org/t/eip-8120-mload8-and-calldataload8-opcodes/27396 | ||
| status: Draft | ||
| type: Standards Track | ||
| category: Core | ||
| created: 2026-01-07 | ||
| --- | ||
|
|
||
| ## Abstract | ||
|
|
||
| This EIP introduces new EVM opcodes that allow loading a single byte from memory or calldata in a single operation, reducing gas cost and bytecode size compared to existing patterns based on `MLOAD (0x51)` or `CALLDATALOAD (0x35)` followed by bit shifting. | ||
|
|
||
| ## Motivation | ||
|
|
||
| Currently, the only way to read a single byte from calldata or memory is to use `CALLDATALOAD` or `MLOAD` and then shift the loaded 32-byte word. | ||
| For example, reading the byte at offset x from calldata requires: | ||
|
|
||
| ``` | ||
| PUSH x | ||
| CALLDATALOAD | ||
| PUSH1 248 | ||
| SHR | ||
| ``` | ||
|
|
||
| This pattern increases runtime gas cost and adds three extra bytes to the deployed bytecode for each single-byte access. Contracts that frequently parse byte-oriented calldata or instruction streams incur unnecessary overhead. | ||
| This EIP proposes two new opcodes that allow loading a single byte directly in one operation. | ||
|
|
||
| ## Specification | ||
|
|
||
| ### MLOAD8 (TBD) | ||
|
|
||
| <!-- TODO: Replace TBD with assigned opcode value --> | ||
|
Check warning on line 36 in EIPS/eip-8120.md
|
||
|
|
||
| - **Stack input**: `offset` | ||
| - **Stack output**: `value` | ||
|
|
||
| Reads one byte from memory at position offset and pushes it onto the stack as a 32-byte word, with the byte placed in the least significant position. | ||
| Memory expansion occurs prior to the load, after which the loaded byte is read. | ||
| If the accessed byte lies beyond the previously allocated memory, the returned value is 0 due to zero-initialization. | ||
| Memory expansion rules apply in the same way as for `MSTORE8` (extending memory to at least `offset + 1` bytes). | ||
|
|
||
| ### CALLDATALOAD8 (TBD) | ||
Helkomine marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| <!-- TODO: Replace TBD with assigned opcode value --> | ||
|
|
||
| - **Stack input**: `offset` | ||
| - **Stack output**: `value` | ||
|
|
||
| Reads one byte from calldata at position offset and pushes it onto the stack as a 32-byte word, with the byte placed in the least significant position. | ||
| If offset is greater than or equal to `CALLDATASIZE (0x36)`, the returned value is 0. | ||
|
|
||
| ### Gas Cost | ||
|
|
||
| - Base cost: 3 gas | ||
| - `MLOAD8` additionally incurs memory expansion cost as defined by existing memory access rules. | ||
| The base gas cost matches `MLOAD`, `MSTORE8`, and `CALLDATALOAD`, ensuring consistency with existing EVM pricing. | ||
|
|
||
| ### Exceptional Conditions | ||
|
|
||
| Execution results in an exceptional halt if: | ||
|
|
||
| - There is insufficient gas to execute the instruction | ||
| - There are insufficient stack items (stack underflow) | ||
|
|
||
| In both cases, execution halts and the current call frame is reverted, consistent with existing EVM behavior. | ||
|
|
||
Helkomine marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ## Rationale | ||
|
|
||
| ### Opcode Symmetry | ||
|
|
||
| `MLOAD8` serves as a natural counterpart to `MSTORE8 (0x53)`: one stores exactly one byte from the stack to memory, while the other loads exactly one byte from memory to the stack. This symmetry improves conceptual clarity and developer ergonomics. | ||
|
|
||
| ### Efficiency for Byte-Oriented Contracts | ||
|
|
||
| Instruction-based architectures that interpret calldata as a sequence of byte-level commands benefit from reduced gas usage and smaller bytecode size when parsing instruction streams. | ||
| A common pattern for reading a single byte from calldata today consists of the following instruction sequence: | ||
|
|
||
| - `CALLDATALOAD` (3 gas) | ||
| - `PUSH1` (3 gas) | ||
| - `SHR` (3 gas) | ||
|
|
||
| This results in a total cost of 9 gas per byte read, excluding additional stack manipulation overhead, and increases deployed bytecode size due to the extra instructions. | ||
| Replacing this sequence with a single `CALLDATALOAD8` instruction priced at 3 gas saves 6 gas per byte read and reduces deployed bytecode size by approximately 3 bytes per occurrence. These savings compound in contracts that repeatedly parse byte-oriented calldata or instruction streams. | ||
|
|
||
| ### Opcode Assignment | ||
|
|
||
| While the final opcode values are subject to allocation during review, this proposal suggests placing `MLOAD8` and `CALLDATALOAD8` in the `0x4X` opcode range. The `0x5X` range, which primarily contains stack, memory, storage, and control flow operations, is largely exhausted. | ||
| Tentative values of `0x4e` for `MLOAD8` and `0x4f` for `CALLDATALOAD8` are suggested to group these instructions near existing data access operations while minimizing the risk of opcode collisions. These assignments are intended to facilitate early client prototyping and collision checking and may be adjusted during the standardization process. | ||
|
|
||
| ## Backwards Compatibility | ||
|
|
||
| This EIP introduces new opcodes and does not modify the semantics of existing instructions. No backwards compatibility issues are introduced beyond those inherent to any opcode-adding hard fork. | ||
|
|
||
| ## Test Cases | ||
|
|
||
| Assume: | ||
|
|
||
| - `calldata = 0x0123456789abcdef` | ||
| - `memory = 0xfedcba9876543210` | ||
|
|
||
| | Bytecode | Description | Result | | ||
| |----------|-------------|--------| | ||
| | `5f <CALLDATALOAD8>` | `PUSH0; CALLDATALOAD8` | pushes `0x01` | | ||
| | `6002 <MLOAD8>` | `PUSH1 0x02; MLOAD8` | pushes `0xba` | | ||
| | `<CALLDATALOAD8>` | missing stack operand | exceptional halt | | ||
| | `<MLOAD8>` | missing stack operand | exceptional halt | | ||
|
|
||
| ## Security Considerations | ||
|
|
||
| No new security considerations are introduced beyond those already known for memory and calldata access. | ||
|
|
||
| ## Copyright | ||
|
|
||
| Copyright and related rights waived via [CC0](../LICENSE.md). | ||
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.
While
(TBD)is acceptable for an initial draft, consider proposing specific opcode values (e.g., from the0x5Xrange if available) to facilitate early client prototyping and collision checking.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.
also add an hmtl <-- TODO --> marker with all TBDs for the EIP bot to flag it if not addressed later when moving to review stage