Skip to content
Merged
Changes from 4 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
49 changes: 32 additions & 17 deletions EIPS/eip-4788.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ restaking constructions, smart contract bridges, MEV mitigations and more.
| constants | value |
|--- |--- |
| `FORK_TIMESTAMP` | TBD |
| `HISTORY_BUFFER_LENGTH` | `98304` |
| `HISTORY_BUFFER_LENGTH` | `8191` |
| `SYSTEM_ADDRESS` | `0xfffffffffffffffffffffffffffffffffffffffe` |
| `BEACON_ROOTS_ADDRESS` | `0xbEac00dDB15f3B6d645C48263dC93862413A222D` |
| `BEACON_ROOTS_ADDRESS` | `0xBEaC020001c6C8B69E5257f4754e46e25f5dc9cB` |

### Background

Expand Down Expand Up @@ -87,6 +87,7 @@ 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.
* If the input is equal to 0, the contract must revert.
* 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 % HISTORY_BUFFER_LENGTH + HISTORY_BUFFER_LENGTH`.
Expand All @@ -109,6 +110,9 @@ def get():
if len(evm.calldata) != 32:
evm.revert()

if to_uint256_be(evm.calldata) == 0:
evm.revert()

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

Expand All @@ -133,7 +137,7 @@ def set():
The exact initcode to deploy is shared below.

```asm
push1 0x58
push1 0x61
dup1
push1 0x09
push0
Expand All @@ -144,7 +148,7 @@ return
caller
push20 0xfffffffffffffffffffffffffffffffffffffffe
eq
push1 0x44
push1 0x4d
jumpi

push1 0x20
Expand All @@ -158,24 +162,29 @@ push0
revert

jumpdest
push3 0x018000
push0
calldataload
mod
dup1
iszero
push1 0x49
jumpi

push3 0x016da0
dup2
mod
swap1
dup2
sload
push0
calldataload
eq
push1 0x37
push1 0x3c
jumpi

push0
push0
revert

jumpdest
push3 0x018000
push3 0x016da0
add
sload
push0
Expand All @@ -185,7 +194,12 @@ push0
return

jumpdest
push3 0x018000
push0
push0
revert

jumpdest
push3 0x016da0
timestamp
mod
timestamp
Expand All @@ -194,7 +208,7 @@ sstore
push0
calldataload
swap1
push3 0x018000
push3 0x016da0
add
sstore
stop
Expand All @@ -210,20 +224,21 @@ by working backwards from the desired deployment transaction:
"type": "0x0",
"nonce": "0x0",
"to": null,
"gas": "0x27eac",
"gas": "0x3d090",
"gasPrice": "0xe8d4a51000",
"maxPriorityFeePerGas": null,
"maxFeePerGas": null,
"value": "0x0",
"input": "0x60588060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
"input": "0x60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762016da0810690815414603c575f5ffd5b62016da001545f5260205ff35b5f5ffd5b62
016da042064281555f359062016da0015500",
"v": "0x1b",
"r": "0x539",
"s": "0x133700f3a77843802897db",
"hash": "0x14789a20c0508b81ab7a0287a12a3a41ca960aa18244af8e98689e37ed569f07"
"s": "0x133700f399526625760859",
"hash": "0x3bd7320b837cfe4efba41d333a1a6514b2ed691c4ffd63db84e39852df4a3292"
}
```

The sender of the transaction can be calculated as `0x3e266d3c3a70c238bdddafef1ba06fbd58958d70`. The address of the first contract deployed from the account is `rlp([sender, 0])` which equals `0xbEac00dDB15f3B6d645C48263dC93862413A222D`. This is how `BEACON_ROOTS_ADDRESS` is determined. Although this style of contract creation is not tied to any specific initcode like create2 is, the synthetic address is cryptographically bound to the input data of the transaction (e.g. the initcode).
The sender of the transaction can be calculated as `0x6ccA914845EB5413c1b7D600dC4D47f6CE85601a`. The address of the first contract deployed from the account is `rlp([sender, 0])` which equals `0xBEaC020001c6C8B69E5257f4754e46e25f5dc9cB`. This is how `BEACON_ROOTS_ADDRESS` is determined. Although this style of contract creation is not tied to any specific initcode like create2 is, the synthetic address is cryptographically bound to the input data of the transaction (e.g. the initcode).

### Block processing

Expand Down