Skip to content

Commit

Permalink
change name of length of the EIP-4788 ring buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
ralexstokes committed Aug 24, 2023
1 parent a5a4047 commit bb28b8d
Showing 1 changed file with 10 additions and 10 deletions.
20 changes: 10 additions & 10 deletions EIPS/eip-4788.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ restaking constructions, smart contract bridges, MEV mitigations and more.
| constants | value |
|--- |--- |
| `FORK_TIMESTAMP` | TBD |
| `HISTORICAL_ROOTS_MODULUS` | `98304` |
| `HISTORY_BUFFER_LENGTH` | `98304` |
| `SYSTEM_ADDRESS` | `0xfffffffffffffffffffffffffffffffffffffffe` |
| `BEACON_ROOTS_ADDRESS` | `0xbEac00dDB15f3B6d645C48263dC93862413A222D` |

Expand Down Expand Up @@ -87,15 +87,15 @@ The beacon roots contract has two operations: `get` and `set`. The input itself

* Callers provide the `timestamp` they are querying encoded as 32 bytes in big-endian format.
* If the input is not exactly 32 bytes, the contract must revert.
* Given `timestamp`, the contract computes the storage index in which the timestamp is stored by computing the modulo `timestamp % HISTORICAL_ROOTS_MODULUS` and reads the value.
* Given `timestamp`, the contract computes the storage index in which the timestamp is stored by computing the modulo `timestamp % HISTORY_BUFFER_LENGTH` and reads the value.
* If the `timestamp` does not match, the contract must revert.
* Finally, the beacon root associated with the timestamp is returned to the user. It is stored at `timestamp % HISTORICAL_ROOTS_MODULUS + HISTORICAL_ROOTS_MODULUS`.
* Finally, the beacon root associated with the timestamp is returned to the user. It is stored at `timestamp % HISTORY_BUFFER_LENGTH + HISTORY_BUFFER_LENGTH`.

##### `set`

* Caller provides the parent beacon block root as calldata to the contract.
* Set the storage value at `header.timestamp % HISTORICAL_ROOTS_MODULUS` to be `header.timestamp`
* Set the storage value at `header.timestamp % HISTORICAL_ROOTS_MODULUS + HISTORICAL_ROOTS_MODULUS` to be `calldata[0:32]`
* Set the storage value at `header.timestamp % HISTORY_BUFFER_LENGTH` to be `header.timestamp`
* Set the storage value at `header.timestamp % HISTORY_BUFFER_LENGTH + HISTORY_BUFFER_LENGTH` to be `calldata[0:32]`

##### Pseudocode

Expand All @@ -109,20 +109,20 @@ def get():
if len(evm.calldata) != 32:
evm.revert()

timestamp_idx = to_uint256_be(evm.calldata) % HISTORICAL_ROOTS_MODULUS
timestamp_idx = to_uint256_be(evm.calldata) % HISTORY_BUFFER_LENGTH
timestamp = storage.get(timestamp_idx)

if timestamp != evm.calldata:
evm.revert()

root_idx = timestamp_idx + HISTORICAL_ROOTS_MODULUS
root_idx = timestamp_idx + HISTORY_BUFFER_LENGTH
root = storage.get(root_idx)

evm.return(root)

def set():
timestamp_idx = to_uint256_be(evm.timestamp) % HISTORICAL_ROOTS_MODULUS
root_idx = timestamp_idx + HISTORICAL_ROOTS_MODULUS
timestamp_idx = to_uint256_be(evm.timestamp) % HISTORY_BUFFER_LENGTH
root_idx = timestamp_idx + HISTORY_BUFFER_LENGTH

storage.set(timestamp_idx, evm.timestamp)
storage.set(root_idx, evm.calldata)
Expand Down Expand Up @@ -260,7 +260,7 @@ e.g. with a singleton state root contract that caches the proof per slot).

### Why two ring buffers?

The first ring buffer only tracks `HISTORICAL_ROOTS_MODULUS` worth of roots and so for all possible timestamp values would consume a constant amount of storage.
The first ring buffer only tracks `HISTORY_BUFFER_LENGTH` worth of roots and so for all possible timestamp values would consume a constant amount of storage.
However, this design opens the precompile to an attack where a skipped slot that has the same value modulo the ring buffer length would return an old root value,
rather than the most recent one.

Expand Down

0 comments on commit bb28b8d

Please sign in to comment.