-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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: post audit tweaks #7672
Changes from all commits
87453ee
e469656
f4fa5c2
4b96512
761af94
5f1871e
2a6a9d6
b6be8bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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` | `0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02` | | ||
|
||
### Background | ||
|
||
|
@@ -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`. | ||
|
@@ -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) | ||
|
||
|
@@ -130,21 +134,13 @@ def set(): | |
|
||
##### Bytecode | ||
|
||
The exact initcode to deploy is shared below. | ||
The exact contract bytecode is shared below. | ||
|
||
```asm | ||
push1 0x58 | ||
dup1 | ||
push1 0x09 | ||
push0 | ||
codecopy | ||
push0 | ||
return | ||
|
||
caller | ||
push20 0xfffffffffffffffffffffffffffffffffffffffe | ||
eq | ||
push1 0x44 | ||
push1 0x4d | ||
jumpi | ||
|
||
push1 0x20 | ||
|
@@ -158,24 +154,29 @@ push0 | |
revert | ||
|
||
jumpdest | ||
push3 0x018000 | ||
push0 | ||
calldataload | ||
mod | ||
dup1 | ||
iszero | ||
push1 0x49 | ||
jumpi | ||
|
||
push3 0x001fff | ||
dup2 | ||
mod | ||
swap1 | ||
dup2 | ||
sload | ||
push0 | ||
calldataload | ||
eq | ||
push1 0x37 | ||
push1 0x3c | ||
jumpi | ||
|
||
push0 | ||
push0 | ||
revert | ||
|
||
jumpdest | ||
push3 0x018000 | ||
push3 0x001fff | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be push2 now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, this was a miss. However, not worth fixing, the runtime execution gascost is identical, the only difference is that the code is one byte larger than it would have needed to be. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This repeats 4x so 4 bytes wasted. Forever :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. Now there are 32 bits less left in the world. 🚻 ☮️ |
||
add | ||
sload | ||
push0 | ||
|
@@ -185,7 +186,12 @@ push0 | |
return | ||
|
||
jumpdest | ||
push3 0x018000 | ||
push0 | ||
push0 | ||
revert | ||
|
||
jumpdest | ||
push3 0x001fff | ||
timestamp | ||
mod | ||
timestamp | ||
|
@@ -194,7 +200,7 @@ sstore | |
push0 | ||
calldataload | ||
swap1 | ||
push3 0x018000 | ||
push3 0x001fff | ||
add | ||
sstore | ||
stop | ||
|
@@ -210,20 +216,22 @@ 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": "0x60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", | ||
"v": "0x1b", | ||
"r": "0x539", | ||
"s": "0x133700f3a77843802897db", | ||
"hash": "0x14789a20c0508b81ab7a0287a12a3a41ca960aa18244af8e98689e37ed569f07" | ||
"s": "0x1b9b6eb1f0", | ||
"hash": "0xdf52c2d3bbe38820fff7b5eaab3db1b91f8e1412b56497d88388fb5d4ea1fde0" | ||
} | ||
``` | ||
|
||
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). | ||
Note, the input in the transaction has a simple constructor prefixing the desired runtime code. | ||
|
||
The sender of the transaction can be calculated as `0x0B799C86a49DEeb90402691F1041aa3AF2d3C875`. The address of the first contract deployed from the account is `rlp([sender, 0])` which equals `0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02`. 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 | ||
|
||
|
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.
Why was the address changed?