Skip to content

Commit 96b0845

Browse files
authored
💥 Add EIP-2935-based Utility Functions (#316)
### 🕓 Changelog This PR adds [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935)-based utility functions. These functions can be used to access the historical block hashes beyond the default `256`-block limit. We use the [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935) history contract, which maintains a ring buffer of the last `8,191` block hashes stored in state. For the blocks within the last `256` blocks, we use the native [`BLOCKHASH`](https://www.evm.codes/?fork=cancun#40) opcode. For blocks between `257` and `8,191` blocks ago, the function `_block_hash` queries via the specified [`get`](https://eips.ethereum.org/EIPS/eip-2935#get) method the [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935) history contract. For blocks older than `8,191` or future blocks (including the current one), we return zero, matching the [`BLOCKHASH`](https://www.evm.codes/?fork=cancun#40) behaviour. It's important to note that the Vyper built-in function [`blockhash`](https://docs.vyperlang.org/en/stable/built-in-functions.html#blockhash) reverts if the block number is more than `256` blocks behind the current block. We explicitly handle this case (i.e. `delta > 8191`) to ensure the function returns an empty `bytes32` value rather than reverting (i.e. exactly matching the [`BLOCKHASH`](https://www.evm.codes/?fork=cancun#40) opcode behaviour). In the stateless fuzzing tests we use `uint64` as upper bound for the `block.number` due to Revm's internal [saturation](https://github.com/bluealloy/revm/blob/b2c789d42d4eee93ce111f1a7d3d0708f1e34180/crates/interpreter/src/instructions/host.rs#L144) of `block.number` to `u64::MAX` (see also my issue [here](foundry-rs/foundry#10367)). If `requested_number >= block_number` (after saturation), Revm returns `U256::ZERO` [early](https://github.com/bluealloy/revm/blob/b2c789d42d4eee93ce111f1a7d3d0708f1e34180/crates/interpreter/src/instructions/host.rs#L148-L157) without querying the database. Eventually, `block.number` is replaced with the [`vm.getBlockNumber()`](https://book.getfoundry.sh/cheatcodes/get-block-number) cheat code in the tests. --------- Signed-off-by: Pascal Marco Caversaccio <[email protected]>
1 parent 6691780 commit 96b0845

File tree

18 files changed

+1101
-632
lines changed

18 files changed

+1101
-632
lines changed

.gas-snapshot

Lines changed: 133 additions & 123 deletions
Large diffs are not rendered by default.

.gas-snapshot-venom

Lines changed: 435 additions & 425 deletions
Large diffs are not rendered by default.

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## [`0.1.2`](https://github.com/pcaversaccio/snekmate/releases/tag/v0.1.2) (Unreleased)
44

5+
### 💥 New Features
6+
7+
- **Utility Functions**
8+
- [`block_hash`](https://github.com/pcaversaccio/snekmate/blob/v0.1.2/src/snekmate/utils/block_hash.vy): Add [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935)-based utility functions. ([#316](https://github.com/pcaversaccio/snekmate/pull/316))
9+
510
### 📄 Licensing
611

712
- Add the [MIT License](https://opensource.org/license/mit) as a dual-licensing option. ([#315](https://github.com/pcaversaccio/snekmate/pull/315))

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ src
7676
└── utils
7777
├── base64 — "Base64 Encoding and Decoding Functions"
7878
├── batch_distributor — "Batch Sending Both Native and ERC-20 Tokens"
79+
├── block_hash — "Utility Functions to Access Historical Block Hashes"
7980
├── create_address — "`CREATE` EVM Opcode Utility Function for Address Calculation"
8081
├── create2_address — "`CREATE2` EVM Opcode Utility Functions for Address Calculations"
8182
├── ecdsa — "Elliptic Curve Digital Signature Algorithm (ECDSA) Secp256k1-Based Functions"
@@ -93,6 +94,7 @@ src
9394
└── mocks
9495
├── base64_mock — "`base64` Module Reference Implementation"
9596
├── batch_distributor_mock — "`batch_distributor` Module Reference Implementation"
97+
├── block_hash_mock — "`block_hash` Module Reference Implementation"
9698
├── create_address_mock — "`create_address` Module Reference Implementation"
9799
├── create2_address_mock — "`create2_address` Module Reference Implementation"
98100
├── ecdsa_mock — "`ecdsa` Module Reference Implementation"
@@ -186,6 +188,7 @@ This repository contains [Foundry](https://github.com/foundry-rs/foundry)-based
186188
| `erc1155` ||||
187189
| `base64` ||||
188190
| `batch_distributor` ||||
191+
| `block_hash` ||||
189192
| `create_address` ||||
190193
| `create2_address` ||||
191194
| `ecdsa` ||||

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"bugs": {
2222
"url": "https://github.com/pcaversaccio/snekmate/issues"
2323
},
24-
"packageManager": "pnpm@10.9.0",
24+
"packageManager": "pnpm@10.10.0",
2525
"scripts": {
2626
"prettier:check": "npx prettier -c \"**/*.{md,sol,js,json,yml,yaml,sh}\"",
2727
"prettier:fix": "npx prettier -w \"**/*.{md,sol,js,json,yml,yaml,sh}\"",
@@ -42,12 +42,12 @@
4242
"@openzeppelin/merkle-tree": "^1.0.8",
4343
"eslint": "^9.25.1",
4444
"eslint-config-prettier": "^10.1.2",
45-
"ethers": "^6.13.5",
45+
"ethers": "^6.13.7",
4646
"keccak256": "^1.0.6",
4747
"merkletreejs": "^0.5.2",
4848
"prettier": "^3.5.3",
4949
"prettier-plugin-sh": "^0.17.2",
50-
"prettier-plugin-solidity": "^1.4.2",
50+
"prettier-plugin-solidity": "^1.4.3",
5151
"solhint": "^5.0.5"
5252
},
5353
"pnpm": {

pnpm-lock.yaml

Lines changed: 51 additions & 52 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)