Skip to content
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

Update EIP-4788: bound state growth of beacon root contract #7126

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions EIPS/eip-4788.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ restaking constructions, smart contract bridges, MEV mitigations and more.
| `FORK_TIMESTAMP` | TBD |
| `HISTORY_STORAGE_ADDRESS` | `0xfffffffffffffffffffffffffffffffffffffffd` |
| `G_beacon_root` | 2100 | gas
| `HISTORY_ACCUMULATOR_LENGTH` | 98304 |

### Background

Expand All @@ -53,37 +54,39 @@ Beginning at the execution timestamp `FORK_TIMESTAMP`, execution clients **MUST*
At the start of processing any execution block where `block.timestamp >= FORK_TIMESTAMP` (i.e. before processing any transactions),
write the parent beacon root provided in the block header into the storage of the contract at `HISTORY_STORAGE_ADDRESS`.

The root itself is used as a key into the contract's storage and the timestamp of the header is written as the key's value.
The timestamp (a 64-bit unsigned integer value) is encoded as 32 bytes in big-endian format.
The timestamp from the header is used as a key into the contract's storage.
The timestamp (a 64-bit unsigned integer value) is encoded as 32 bytes in big-endian format when used as this key into the storage.

In Python pseudocode:

```python
timestamp_key = block_header.timestamp % HISTORY_ACCUMULATOR_LENGTH
key = to_uint256_be(timestamp_key)
parent_beacon_block_root = block_header.parent_beacon_block_root
timestamp = to_uint256_be(block_header.timestamp)

sstore(HISTORY_STORAGE_ADDRESS, parent_beacon_block_root, timestamp)
sstore(HISTORY_STORAGE_ADDRESS, key, parent_beacon_block_root)
```

#### New stateful precompile

Beginning at the execution timestamp `FORK_TIMESTAMP`, the code and storage at `HISTORY_STORAGE_ADDRESS` constitute a "stateful" precompile.

Callers of the precompile should provide the `root` they are querying encoded as 32 bytes.
Callers of the precompile should provide the `timestamp` they are querying encoded as 32 bytes in big-endian format.

Alongside the existing gas for calling the precompile, there is an additional gas cost of `G_beacon_root` cost to reflect the implicit `SLOAD` from
the precompile's state. The timestamp of the corresponding root is returned as 32 bytes in the caller's provided return buffer and represents the
64-bit unsigned integer from the header in big-endian format.
the precompile's state. The root of the corresponding timestamp is returned as 32 bytes in the caller's provided return buffer.

In pseudocode:

```python
root = evm.calldata[:32]
timestamp = sload(HISTORY_STORAGE_ADDRESS, root)
evm.returndata[:32].set(timestamp)
timestamp_data = evm.calldata[:32]
timestamp = to_uint64_be(timestamp_data) % HISTORY_ACCUMULATOR_LENGTH
key = to_uint256_be(timestamp)
root = sload(HISTORY_STORAGE_ADDRESS, key)
evm.returndata[:32].set(root)
```

If there is no timestamp stored at the given root, the opcode follows the existing EVM semantics of `sload` returning `0`.
If there is no root stored at the given timestamp, the opcode follows the existing EVM semantics of `sload` returning `0`.

## Rationale

Expand Down
Loading