├── .config
├── nextest.toml
└── zepter.yaml
├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── BUG-FORM.yml
│ ├── FEATURE-FORM.yml
│ └── config.yml
├── PULL_REQUEST_TEMPLATE.md
├── scripts
│ └── install_test_binaries.sh
└── workflows
│ └── ci.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── cliff.toml
├── clippy.toml
├── crates
├── evm
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── block
│ │ ├── calc.rs
│ │ ├── error.rs
│ │ ├── mod.rs
│ │ ├── state_changes.rs
│ │ ├── state_hook.rs
│ │ └── system_calls
│ │ │ ├── eip2935.rs
│ │ │ ├── eip4788.rs
│ │ │ ├── eip7002.rs
│ │ │ ├── eip7251.rs
│ │ │ └── mod.rs
│ │ ├── either.rs
│ │ ├── env.rs
│ │ ├── error.rs
│ │ ├── eth
│ │ ├── block.rs
│ │ ├── dao_fork.rs
│ │ ├── eip6110.rs
│ │ ├── mod.rs
│ │ ├── receipt_builder.rs
│ │ └── spec.rs
│ │ ├── evm.rs
│ │ ├── lib.rs
│ │ ├── precompiles.rs
│ │ └── tx.rs
└── op-evm
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ ├── block
│ ├── canyon.rs
│ ├── mod.rs
│ └── receipt_builder.rs
│ └── lib.rs
├── deny.toml
├── release.toml
├── rustfmt.toml
└── scripts
├── changelog.sh
└── check_no_std.sh
/.config/nextest.toml:
--------------------------------------------------------------------------------
1 | [profile.default]
2 | retries = { backoff = "exponential", count = 2, delay = "2s", jitter = true }
3 | slow-timeout = { period = "30s", terminate-after = 4 }
4 |
--------------------------------------------------------------------------------
/.config/zepter.yaml:
--------------------------------------------------------------------------------
1 | version:
2 | format: 1
3 | # Minimum zepter version that is expected to work. This is just for printing a nice error
4 | # message when someone tries to use an older version.
5 | binary: 0.13.2
6 |
7 | # The examples in the following comments assume crate `A` to have a dependency on crate `B`.
8 | workflows:
9 | check:
10 | - [
11 | "lint",
12 | # Check that `A` activates the features of `B`.
13 | "propagate-feature",
14 | # These are the features to check:
15 | "--features=std",
16 | # Do not try to add a new section into `[features]` of `A` only because `B` expose that feature. There are edge-cases where this is still needed, but we can add them manually.
17 | "--left-side-feature-missing=ignore",
18 | # Ignore the case that `A` it outside of the workspace. Otherwise it will report errors in external dependencies that we have no influence on.
19 | "--left-side-outside-workspace=ignore",
20 | # limit to the workspace
21 | "--show-path",
22 | "--quiet",
23 | ]
24 | default:
25 | # Running `zepter` with no subcommand will check & fix.
26 | - [$check.0, "--fix"]
27 |
28 | # Will be displayed when any workflow fails:
29 | help:
30 | text: |
31 | Alloy uses the Zepter CLI to detect abnormalities in Cargo features, e.g. missing propagation.
32 |
33 | It looks like one more checks failed; please check the console output.
34 |
35 | You can try to automatically address them by installing zepter (`cargo install zepter --locked`) and simply running `zepter` in the workspace root.
36 | links:
37 | - "https://github.com/ggwpez/zepter"
38 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @mattsse @klkvr
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/BUG-FORM.yml:
--------------------------------------------------------------------------------
1 | name: Bug report
2 | description: File a bug report
3 | labels: ["bug"]
4 | title: "[Bug] "
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | Please ensure that the bug has not already been filed in the issue tracker.
10 |
11 | Thanks for taking the time to report this bug!
12 | - type: input
13 | attributes:
14 | label: What version of Alloy are you on?
15 | placeholder: "Run `cargo tree | grep alloy` and paste the output here"
16 | - type: textarea
17 | attributes:
18 | label: Describe the bug
19 | description: Please include code snippets as well if relevant.
20 | validations:
21 | required: true
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/FEATURE-FORM.yml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Suggest a feature
3 | labels: ["enhancement"]
4 | title: "[Feature] "
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | Please ensure that the feature has not already been requested in the issue tracker.
10 | - type: textarea
11 | attributes:
12 | label: Describe the feature you would like
13 | description:
14 | Please also describe your goals for the feature. What problems it solves, how it would be
15 | used, etc.
16 | validations:
17 | required: true
18 | - type: textarea
19 | attributes:
20 | label: Additional context
21 | description: Add any other context to the feature (like screenshots, resources)
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: true
2 | contact_links:
3 | - name: Support
4 | url: https://t.me/ethers_rs
5 | about: This issue tracker is only for bugs and feature requests. Support is available on Telegram!
6 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 | ## Motivation
16 |
17 |
22 |
23 | ## Solution
24 |
25 |
29 |
30 | ## PR Checklist
31 |
32 | - [ ] Added Tests
33 | - [ ] Added Documentation
34 | - [ ] Breaking changes
35 |
--------------------------------------------------------------------------------
/.github/scripts/install_test_binaries.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Installs Geth binary
3 | # Note: intended for use only with CI (x86_64 Ubuntu, MacOS or Windows)
4 | set -e
5 |
6 | GETH_BUILD=${GETH_BUILD:-"1.14.8-a9523b64"}
7 | RETH_BUILD=${RETH_BUILD:-"1.0.6"}
8 |
9 | BIN_DIR=${BIN_DIR:-"$HOME/bin"}
10 |
11 | PLATFORM="$(uname -s | awk '{print tolower($0)}')"
12 |
13 | main() {
14 | mkdir -p "$BIN_DIR"
15 | cd "$BIN_DIR"
16 | export PATH="$BIN_DIR:$PATH"
17 | if [ "$GITHUB_PATH" ]; then
18 | echo "$BIN_DIR" >> "$GITHUB_PATH"
19 | fi
20 |
21 | install_geth &
22 | install_reth &
23 |
24 | wait
25 | }
26 |
27 | # Installs geth from https://geth.ethereum.org/downloads
28 | install_geth() {
29 | case "$PLATFORM" in
30 | linux)
31 | NAME="geth-$PLATFORM-amd64-$GETH_BUILD"
32 | curl -sL "https://gethstore.blob.core.windows.net/builds/$NAME.tar.gz" | tar -xzf -
33 | mv -f "$NAME/geth" ./
34 | rm -rf "$NAME"
35 | chmod +x geth
36 | ;;
37 | *)
38 | NAME="geth-windows-amd64-$GETH_BUILD"
39 | curl -so $NAME.zip "https://gethstore.blob.core.windows.net/builds/$NAME.zip"
40 | unzip $NAME.zip
41 | mv -f "$NAME/geth.exe" ./
42 | rm -rf "$NAME" "$NAME.zip"
43 | ;;
44 | esac
45 |
46 | echo ""
47 | echo "Installed Geth:"
48 | geth version
49 | }
50 |
51 | # Install reth from https://github.com/paradigmxyz/reth/releases
52 | install_reth() {
53 | case "$PLATFORM" in
54 | linux)
55 | NAME="reth-v$RETH_BUILD-x86_64-unknown-linux-gnu"
56 | curl -sL "https://github.com/paradigmxyz/reth/releases/download/v$RETH_BUILD/$NAME.tar.gz" | tar -xzf -
57 | chmod +x reth
58 |
59 | echo ""
60 | echo "Installed Reth:"
61 | reth --version
62 | ;;
63 | esac
64 | }
65 |
66 | main
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 |
8 | env:
9 | CARGO_TERM_COLOR: always
10 |
11 | concurrency:
12 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
13 | cancel-in-progress: true
14 |
15 | jobs:
16 | test:
17 | name: test ${{ matrix.os }} ${{ matrix.rust }} ${{ matrix.flags }}
18 | timeout-minutes: 30
19 | runs-on: ${{ matrix.os }}
20 | strategy:
21 | fail-fast: false
22 | matrix:
23 | os: ["ubuntu-latest", "windows-latest"]
24 | rust:
25 | - "stable"
26 | - "nightly"
27 | - "1.85" # MSRV
28 | flags:
29 | # No features
30 | - "--no-default-features"
31 | # Default features
32 | - ""
33 | # All features
34 | - "--all-features"
35 | exclude:
36 | # All features on MSRV
37 | - rust: "1.85" # MSRV
38 | flags: "--all-features"
39 | steps:
40 | - uses: actions/checkout@v4
41 | - uses: dtolnay/rust-toolchain@master
42 | with:
43 | toolchain: ${{ matrix.rust }}
44 | - name: Install Anvil
45 | uses: foundry-rs/foundry-toolchain@v1
46 | with:
47 | version: nightly
48 | - name: Install test binaries
49 | shell: bash
50 | run: ./.github/scripts/install_test_binaries.sh
51 | - uses: Swatinem/rust-cache@v2
52 | with:
53 | cache-on-failure: true
54 | # Only run tests on latest stable and above
55 | - name: Install cargo-nextest
56 | if: ${{ matrix.rust != '1.85' }} # MSRV
57 | uses: taiki-e/install-action@nextest
58 | - name: build
59 | if: ${{ matrix.rust == '1.85' }} # MSRV
60 | run: cargo build --workspace ${{ matrix.flags }}
61 | - name: test
62 | shell: bash
63 | if: ${{ matrix.rust != '1.85' }} # MSRV
64 | run: cargo nextest run --workspace ${{ matrix.flags }}
65 |
66 | doctest:
67 | runs-on: ubuntu-latest
68 | timeout-minutes: 30
69 | steps:
70 | - uses: actions/checkout@v4
71 | - uses: dtolnay/rust-toolchain@stable
72 | - uses: Swatinem/rust-cache@v2
73 | with:
74 | cache-on-failure: true
75 | - run: cargo test --workspace --doc
76 | - run: cargo test --all-features --workspace --doc
77 |
78 | wasm-unknown:
79 | runs-on: ubuntu-latest
80 | timeout-minutes: 30
81 | steps:
82 | - uses: actions/checkout@v4
83 | - uses: dtolnay/rust-toolchain@stable
84 | with:
85 | target: wasm32-unknown-unknown
86 | - uses: taiki-e/install-action@cargo-hack
87 | - uses: Swatinem/rust-cache@v2
88 | with:
89 | cache-on-failure: true
90 | - name: cargo hack
91 | run: |
92 | cargo hack build --workspace --ignore-unknown-features --features ws --target wasm32-unknown-unknown --no-default-features
93 |
94 | wasm-wasi:
95 | runs-on: ubuntu-latest
96 | timeout-minutes: 30
97 | steps:
98 | - uses: actions/checkout@v4
99 | - uses: dtolnay/rust-toolchain@stable
100 | with:
101 | target: wasm32-wasip1
102 | - uses: taiki-e/install-action@cargo-hack
103 | - uses: Swatinem/rust-cache@v2
104 | with:
105 | cache-on-failure: true
106 | - name: cargo hack
107 | run: |
108 | cargo hack build --workspace --target wasm32-wasip1
109 |
110 | feature-checks:
111 | runs-on: ubuntu-latest
112 | timeout-minutes: 30
113 | steps:
114 | - uses: actions/checkout@v4
115 | - uses: dtolnay/rust-toolchain@stable
116 | - uses: taiki-e/install-action@cargo-hack
117 | - uses: Swatinem/rust-cache@v2
118 | with:
119 | cache-on-failure: true
120 | - name: cargo hack
121 | run: cargo hack check --feature-powerset --depth 1
122 |
123 | check-no-std:
124 | name: check no_std ${{ matrix.features }}
125 | runs-on: ubuntu-latest
126 | timeout-minutes: 30
127 | steps:
128 | - uses: actions/checkout@v4
129 | - uses: dtolnay/rust-toolchain@stable
130 | with:
131 | targets: riscv32imac-unknown-none-elf
132 | - uses: taiki-e/install-action@cargo-hack
133 | - uses: Swatinem/rust-cache@v2
134 | with:
135 | cache-on-failure: true
136 | - run: ./scripts/check_no_std.sh
137 |
138 | clippy:
139 | runs-on: ubuntu-latest
140 | timeout-minutes: 30
141 | steps:
142 | - uses: actions/checkout@v4
143 | - uses: dtolnay/rust-toolchain@master
144 | with:
145 | toolchain: nightly
146 | components: clippy
147 | - uses: Swatinem/rust-cache@v2
148 | with:
149 | cache-on-failure: true
150 | - run: cargo +nightly clippy --workspace --all-targets --all-features
151 | env:
152 | RUSTFLAGS: -Dwarnings
153 |
154 | docs:
155 | runs-on: ubuntu-latest
156 | timeout-minutes: 30
157 | steps:
158 | - uses: actions/checkout@v4
159 | - uses: dtolnay/rust-toolchain@nightly
160 | - uses: Swatinem/rust-cache@v2
161 | with:
162 | cache-on-failure: true
163 | - name: Build documentation
164 | run: cargo doc --workspace --all-features --no-deps --document-private-items
165 | env:
166 | RUSTDOCFLAGS: --cfg docsrs -D warnings --show-type-layout --generate-link-to-definition -Zunstable-options
167 |
168 | fmt:
169 | runs-on: ubuntu-latest
170 | timeout-minutes: 30
171 | steps:
172 | - uses: actions/checkout@v4
173 | - uses: dtolnay/rust-toolchain@nightly
174 | with:
175 | components: rustfmt
176 | - run: cargo fmt --all --check
177 |
178 | deny:
179 | uses: ithacaxyz/ci/.github/workflows/deny.yml@main
180 |
181 | ci-success:
182 | name: ci success
183 | runs-on: ubuntu-latest
184 | if: always()
185 | needs:
186 | - test
187 | - doctest
188 | - wasm-unknown
189 | - wasm-wasi
190 | - feature-checks
191 | - check-no-std
192 | - clippy
193 | - docs
194 | - fmt
195 | - deny
196 | steps:
197 | - name: Decide whether the needed jobs succeeded or failed
198 | uses: re-actors/alls-green@release/v1
199 | with:
200 | jobs: ${{ toJSON(needs) }}
201 |
202 | # Check crates correctly propagate features
203 | feature-propagation:
204 | runs-on: ubuntu-latest
205 | timeout-minutes: 20
206 | steps:
207 | - uses: actions/checkout@v4
208 | - name: run zepter
209 | run: |
210 | cargo install zepter -f --locked
211 | zepter --version
212 | time zepter run check
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /Cargo.lock
3 | .vscode
4 | .idea
5 | .env
6 | .DS_Store
7 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [0.10.0](https://github.com/alloy-rs/evm/releases/tag/v0.10.0) - 2025-05-23
9 |
10 | ### Dependencies
11 |
12 | - [`deps`] Bump revm to `24.0.0` and op-revm to `5.0.0` ([#98](https://github.com/alloy-rs/evm/issues/98))
13 |
14 | ### Features
15 |
16 | - Implement from_recovered_tx for txDeposit nativel ([#96](https://github.com/alloy-rs/evm/issues/96))
17 |
18 | ### Miscellaneous Tasks
19 |
20 | - Preparing for mint nonoptional in reth ([#91](https://github.com/alloy-rs/evm/issues/91))
21 |
22 | ## [0.9.1](https://github.com/alloy-rs/evm/releases/tag/v0.9.1) - 2025-05-20
23 |
24 | ### Features
25 |
26 | - Implement `FromTxWithEncoded` and `FromRecoveredTx` from `OpTxEnvelope` for `TxEnv` ([#94](https://github.com/alloy-rs/evm/issues/94))
27 |
28 | ### Miscellaneous Tasks
29 |
30 | - Release 0.9.1
31 |
32 | ## [0.9.0](https://github.com/alloy-rs/evm/releases/tag/v0.9.0) - 2025-05-20
33 |
34 | ### Features
35 |
36 | - Add non-mutable getters for `inspector` and `precompiles` ([#93](https://github.com/alloy-rs/evm/issues/93))
37 | - `BlockExecutor::execute_transaction_with_commit_condition` ([#92](https://github.com/alloy-rs/evm/issues/92))
38 |
39 | ### Miscellaneous Tasks
40 |
41 | - Release 0.9.0
42 |
43 | ## [0.8.1](https://github.com/alloy-rs/evm/releases/tag/v0.8.1) - 2025-05-16
44 |
45 | ### Features
46 |
47 | - Extend Evm::Spec bounds with Hash and PartialEq ([#88](https://github.com/alloy-rs/evm/issues/88))
48 |
49 | ### Miscellaneous Tasks
50 |
51 | - Release 0.8.1
52 |
53 | ## [0.8.0](https://github.com/alloy-rs/evm/releases/tag/v0.8.0) - 2025-05-13
54 |
55 | ### Dependencies
56 |
57 | - Bump alloy 1.0.0 ([#87](https://github.com/alloy-rs/evm/issues/87))
58 |
59 | ### Miscellaneous Tasks
60 |
61 | - Release 0.8.0
62 |
63 | ## [0.7.2](https://github.com/alloy-rs/evm/releases/tag/v0.7.2) - 2025-05-12
64 |
65 | ### Bug Fixes
66 |
67 | - `r.as_ref()` the trait `AsRef<[_; 0]>` is not implemented for `[u8]` ([#86](https://github.com/alloy-rs/evm/issues/86))
68 |
69 | ### Miscellaneous Tasks
70 |
71 | - Release 0.7.2
72 |
73 | ### Styling
74 |
75 | - Impl Evm for Either ([#84](https://github.com/alloy-rs/evm/issues/84))
76 |
77 | ## [0.7.1](https://github.com/alloy-rs/evm/releases/tag/v0.7.1) - 2025-05-09
78 |
79 | ### Dependencies
80 |
81 | - Bump op-revm ([#85](https://github.com/alloy-rs/evm/issues/85))
82 |
83 | ### Miscellaneous Tasks
84 |
85 | - Release 0.7.1
86 |
87 | ## [0.7.0](https://github.com/alloy-rs/evm/releases/tag/v0.7.0) - 2025-05-08
88 |
89 | ### Bug Fixes
90 |
91 | - Use HashMap::with_capacity_and_hasher ([#83](https://github.com/alloy-rs/evm/issues/83))
92 |
93 | ### Dependencies
94 |
95 | - Bump op-revm ([#79](https://github.com/alloy-rs/evm/issues/79))
96 |
97 | ### Features
98 |
99 | - Expose Inspector on Evm ([#81](https://github.com/alloy-rs/evm/issues/81))
100 | - [eip7702] Delegate signer recovery to `alloy-consensus::crypto` ([#82](https://github.com/alloy-rs/evm/issues/82))
101 | - Bump revm ([#74](https://github.com/alloy-rs/evm/issues/74))
102 | - Include Precompiles associated type in Evm trait ([#73](https://github.com/alloy-rs/evm/issues/73))
103 | - Add SpecPrecompiles ([#71](https://github.com/alloy-rs/evm/issues/71))
104 |
105 | ### Miscellaneous Tasks
106 |
107 | - Release 0.7.0
108 | - Use as_ref ([#80](https://github.com/alloy-rs/evm/issues/80))
109 |
110 | ### Styling
111 |
112 | - Re-export revm & op-revm ([#77](https://github.com/alloy-rs/evm/issues/77))
113 |
114 | ## [0.6.0](https://github.com/alloy-rs/evm/releases/tag/v0.6.0) - 2025-04-23
115 |
116 | ### Dependencies
117 |
118 | - Bump alloy 0.15 ([#72](https://github.com/alloy-rs/evm/issues/72))
119 |
120 | ### Miscellaneous Tasks
121 |
122 | - Release 0.6.0
123 |
124 | ## [0.5.0](https://github.com/alloy-rs/evm/releases/tag/v0.5.0) - 2025-04-15
125 |
126 | ### Dependencies
127 |
128 | - Bump `op-alloy-consensus` ([#66](https://github.com/alloy-rs/evm/issues/66))
129 | - Bump `op-revm` to `3.0.1` ([#65](https://github.com/alloy-rs/evm/issues/65))
130 |
131 | ### Features
132 |
133 | - Added method to get chain id ([#62](https://github.com/alloy-rs/evm/issues/62))
134 |
135 | ### Miscellaneous Tasks
136 |
137 | - Release 0.5.0
138 |
139 | ## [0.4.0](https://github.com/alloy-rs/evm/releases/tag/v0.4.0) - 2025-04-09
140 |
141 | ### Dependencies
142 |
143 | - Alloy 0.14 ([#63](https://github.com/alloy-rs/evm/issues/63))
144 |
145 | ### Miscellaneous Tasks
146 |
147 | - Release 0.4.0
148 |
149 | ## [0.3.2](https://github.com/alloy-rs/evm/releases/tag/v0.3.2) - 2025-04-08
150 |
151 | ### Features
152 |
153 | - Add fn evm(&self) ([#60](https://github.com/alloy-rs/evm/issues/60))
154 |
155 | ### Miscellaneous Tasks
156 |
157 | - Release 0.3.2
158 |
159 | ## [0.3.1](https://github.com/alloy-rs/evm/releases/tag/v0.3.1) - 2025-04-02
160 |
161 | ### Features
162 |
163 | - Add missing trait impls for ref types ([#58](https://github.com/alloy-rs/evm/issues/58))
164 |
165 | ### Miscellaneous Tasks
166 |
167 | - Release 0.3.1
168 |
169 | ## [0.3.0](https://github.com/alloy-rs/evm/releases/tag/v0.3.0) - 2025-04-02
170 |
171 | ### Features
172 |
173 | - [tx] Add `FromTxWithEncoded` bound to `BlockExecutor` transaction ([#54](https://github.com/alloy-rs/evm/issues/54))
174 | - [tx] Relax bounds on `TxEip4844` for `EthereumTxEnvelope` ([#57](https://github.com/alloy-rs/evm/issues/57))
175 | - [tx] Implement `FromTxWithEncoded` and `FromRecoveredTx` for `EthereumTxEnvelope` ([#56](https://github.com/alloy-rs/evm/issues/56))
176 |
177 | ### Miscellaneous Tasks
178 |
179 | - Release 0.3.0
180 |
181 | ### Other
182 |
183 | - Rm precise pin ([#55](https://github.com/alloy-rs/evm/issues/55))
184 | - Added execute_block ([#50](https://github.com/alloy-rs/evm/issues/50))
185 |
186 | ## [0.2.0](https://github.com/alloy-rs/evm/releases/tag/v0.2.0) - 2025-03-28
187 |
188 | ### Dependencies
189 |
190 | - Bump deps revm alloy ([#48](https://github.com/alloy-rs/evm/issues/48))
191 |
192 | ### Features
193 |
194 | - Add helper trait for deriving `TxEnv` from `WithEncoded` ([#42](https://github.com/alloy-rs/evm/issues/42))
195 | - [op-receipt-builder] Add Debug trait to OpReceiptBuilder. ([#47](https://github.com/alloy-rs/evm/issues/47))
196 |
197 | ### Miscellaneous Tasks
198 |
199 | - Release 0.2.0
200 |
201 |
202 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Alloy
2 |
3 | :balloon: Thanks for your help improving the project! We are so happy to have
4 | you!
5 |
6 | There are opportunities to contribute to Alloy at any level. It doesn't
7 | matter if you are just getting started with Rust or are the most weathered
8 | expert, we can use your help.
9 |
10 | **No contribution is too small and all contributions are valued.**
11 |
12 | This guide will help you get started. **Do not let this guide intimidate you**.
13 | It should be considered a map to help you navigate the process.
14 |
15 | The [dev channel][dev] is available for any concerns not covered in this guide,
16 | please join us!
17 |
18 | [dev]: https://t.me/ethers_rs
19 |
20 | ## Conduct
21 |
22 | The Alloy project adheres to the [Rust Code of Conduct][coc]. This describes
23 | the _minimum_ behavior expected from all contributors.
24 |
25 | [coc]: https://www.rust-lang.org/policies/code-of-conduct
26 |
27 | ## Contributing in Issues
28 |
29 | For any issue, there are fundamentally three ways an individual can contribute:
30 |
31 | 1. By opening the issue for discussion: For instance, if you believe that you
32 | have uncovered a bug in Alloy, creating a new issue in the Alloy
33 | issue tracker is the way to report it.
34 |
35 | 2. By helping to triage the issue: This can be done by providing
36 | supporting details (a test case that demonstrates a bug), providing
37 | suggestions on how to address the issue, or ensuring that the issue is tagged
38 | correctly.
39 |
40 | 3. By helping to resolve the issue: Typically this is done either in the form of
41 | demonstrating that the issue reported is not a problem after all, or more
42 | often, by opening a Pull Request that changes some bit of something in
43 | Alloy in a concrete and reviewable manner.
44 |
45 | **Anybody can participate in any stage of contribution**. We urge you to
46 | participate in the discussion around bugs and participate in reviewing PRs.
47 |
48 | ### Asking for General Help
49 |
50 | If you have reviewed existing documentation and still have questions or are
51 | having problems, you can open an issue asking for help.
52 |
53 | In exchange for receiving help, we ask that you contribute back a documentation
54 | PR that helps others avoid the problems that you encountered.
55 |
56 | ### Submitting a Bug Report
57 |
58 | When opening a new issue in the Alloy issue tracker, users will be presented
59 | with a [basic template][template] that should be filled in. If you believe that
60 | you have uncovered a bug, please fill out this form, following the template to
61 | the best of your ability. Do not worry if you cannot answer every detail, just
62 | fill in what you can.
63 |
64 | The two most important pieces of information we need in order to properly
65 | evaluate the report is a description of the behavior you are seeing and a simple
66 | test case we can use to recreate the problem on our own. If we cannot recreate
67 | the issue, it becomes impossible for us to fix.
68 |
69 | In order to rule out the possibility of bugs introduced by userland code, test
70 | cases should be limited, as much as possible, to using only Alloy APIs.
71 |
72 | See [How to create a Minimal, Complete, and Verifiable example][mcve].
73 |
74 | [mcve]: https://stackoverflow.com/help/mcve
75 | [template]: .github/PULL_REQUEST_TEMPLATE.md
76 |
77 | ### Triaging a Bug Report
78 |
79 | Once an issue has been opened, it is not uncommon for there to be discussion
80 | around it. Some contributors may have differing opinions about the issue,
81 | including whether the behavior being seen is a bug or a feature. This discussion
82 | is part of the process and should be kept focused, helpful, and professional.
83 |
84 | Short, clipped responses—that provide neither additional context nor supporting
85 | detail—are not helpful or professional. To many, such responses are simply
86 | annoying and unfriendly.
87 |
88 | Contributors are encouraged to help one another make forward progress as much as
89 | possible, empowering one another to solve issues collaboratively. If you choose
90 | to comment on an issue that you feel either is not a problem that needs to be
91 | fixed, or if you encounter information in an issue that you feel is incorrect,
92 | explain why you feel that way with additional supporting context, and be willing
93 | to be convinced that you may be wrong. By doing so, we can often reach the
94 | correct outcome much faster.
95 |
96 | ### Resolving a Bug Report
97 |
98 | In the majority of cases, issues are resolved by opening a Pull Request. The
99 | process for opening and reviewing a Pull Request is similar to that of opening
100 | and triaging issues, but carries with it a necessary review and approval
101 | workflow that ensures that the proposed changes meet the minimal quality and
102 | functional guidelines of the Alloy project.
103 |
104 | ## Pull Requests
105 |
106 | Pull Requests are the way concrete changes are made to the code, documentation,
107 | and dependencies in the Alloy repository.
108 |
109 | Even tiny pull requests (e.g., one character pull request fixing a typo in API
110 | documentation) are greatly appreciated. Before making a large change, it is
111 | usually a good idea to first open an issue describing the change to solicit
112 | feedback and guidance. This will increase the likelihood of the PR getting
113 | merged.
114 |
115 | When opening a PR **please select the "Allow Edits From Maintainers" option**.
116 | Alloy maintains strict standards for code quality and style, as well as
117 | commit signing. This option allows us to make small changes to your PR to bring
118 | it in line with these standards. It helps us get your PR in faster, and with
119 | less work from you.
120 |
121 | ### Contributions Related to Spelling and Grammar
122 |
123 | At this time, we will not be accepting contributions that only fix spelling or grammatical errors in documentation, code or
124 | elsewhere.
125 |
126 | ### Cargo Commands
127 |
128 | This section lists some commonly needed commands.
129 |
130 | ```sh
131 | cargo check --all-features
132 | cargo +nightly fmt --all
133 | cargo build --all-features
134 | cargo test --all-features
135 | cargo test --no-default-features
136 | cargo +nightly clippy --all-features
137 | ```
138 |
139 | ### Tests
140 |
141 | If the change being proposed alters code (as opposed to only documentation for
142 | example), it is either adding new functionality to Alloy or it is fixing
143 | existing, broken functionality. In both of these cases, the pull request should
144 | include one or more tests to ensure that Alloy does not regress in the
145 | future.
146 |
147 | #### Unit Tests
148 |
149 | Functions which have very specific tasks should be unit tested. We encourage
150 | using table tests to cover a large number of cases in a succinct readable
151 | manner.
152 |
153 | #### Integration tests
154 |
155 | Integration tests go in the same crate as the code they are testing, in the
156 | `tests/` directory.
157 |
158 | The best strategy for writing a new integration test is to look at existing
159 | integration tests in the crate and follow the style.
160 |
161 | #### Documentation tests
162 |
163 | Ideally, every API has at least one [documentation test] that demonstrates how
164 | to use the API. Documentation tests are run with `cargo test --doc`. This
165 | ensures that the example is correct and provides additional test coverage.
166 |
167 | The trick to documentation tests is striking a balance between being succinct
168 | for a reader to understand and actually testing the API.
169 |
170 | Lines that start with `/// #` are removed when the documentation is generated.
171 | They are only there to get the test to run. Use this trick to keep your example
172 | succinct in the user-facing tests :)
173 |
174 | ### Commits
175 |
176 | It is a recommended best practice to keep your changes as logically grouped as
177 | possible within individual commits. There is no limit to the number of commits
178 | any single Pull Request may have, and many contributors find it easier to review
179 | changes that are split across multiple commits.
180 |
181 | That said, if you have a number of commits that are "checkpoints" and don't
182 | represent a single logical change, please squash those together.
183 |
184 | Note that multiple commits often get squashed when they are landed (see the
185 | notes about [commit squashing](#commit-squashing)).
186 |
187 | #### Commit message guidelines
188 |
189 | Commit messages should follow the
190 | [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
191 | specification.
192 |
193 | Here's a few examples from the master branch's commit log:
194 |
195 | - feat(abigen): support empty events
196 | - chore: bump crypto deps
197 | - test: simplify test cleanup
198 | - fmt: run rustfmt
199 |
200 | ### Opening the Pull Request
201 |
202 | From within GitHub, opening a new Pull Request will present you with a
203 | [template] that should be filled out. Please try to do your best at filling out
204 | the details, but feel free to skip parts if you're not sure what to put.
205 |
206 | [template]: .github/PULL_REQUEST_TEMPLATE.md
207 |
208 | ### Discuss and update
209 |
210 | You will probably get feedback or requests for changes to your Pull Request.
211 | This is a big part of the submission process so don't be discouraged! Some
212 | contributors may sign off on the Pull Request right away, others may have
213 | more detailed comments or feedback. This is a necessary part of the process
214 | in order to evaluate whether the changes are correct and necessary.
215 |
216 | **Any community member can review a PR and you might get conflicting feedback**.
217 | Keep an eye out for comments from code owners to provide guidance on conflicting
218 | feedback.
219 |
220 | **Once the PR is open, do not rebase the commits**. See
221 | [Commit Squashing](#commit-squashing) for more details.
222 |
223 | ### Commit Squashing
224 |
225 | In most cases, **do not squash commits that you add to your Pull Request during
226 | the review process**. When the commits in your Pull Request land, they may be
227 | squashed into one commit per logical change. Metadata will be added to the
228 | commit message (including links to the Pull Request, links to relevant issues,
229 | and the names of the reviewers). The commit history of your Pull Request,
230 | however, will stay intact on the Pull Request page.
231 |
232 | ## Reviewing Pull Requests
233 |
234 | **Any Alloy community member is welcome to review any pull request**.
235 |
236 | All Alloy contributors who choose to review and provide feedback on Pull
237 | Requests have a responsibility to both the project and the individual making the
238 | contribution. Reviews and feedback must be helpful, insightful, and geared
239 | towards improving the contribution as opposed to simply blocking it. If there
240 | are reasons why you feel the PR should not land, explain what those are. Do not
241 | expect to be able to block a Pull Request from advancing simply because you say
242 | "No" without giving an explanation. Be open to having your mind changed. Be open
243 | to working with the contributor to make the Pull Request better.
244 |
245 | Reviews that are dismissive or disrespectful of the contributor or any other
246 | reviewers are strictly counter to the Code of Conduct.
247 |
248 | When reviewing a Pull Request, the primary goals are for the codebase to improve
249 | and for the person submitting the request to succeed. **Even if a Pull Request
250 | does not land, the submitters should come away from the experience feeling like
251 | their effort was not wasted or unappreciated**. Every Pull Request from a new
252 | contributor is an opportunity to grow the community.
253 |
254 | ### Review a bit at a time.
255 |
256 | Do not overwhelm new contributors.
257 |
258 | It is tempting to micro-optimize and make everything about relative performance,
259 | perfect grammar, or exact style matches. Do not succumb to that temptation.
260 |
261 | Focus first on the most significant aspects of the change:
262 |
263 | 1. Does this change make sense for Alloy?
264 | 2. Does this change make Alloy better, even if only incrementally?
265 | 3. Are there clear bugs or larger scale issues that need attending to?
266 | 4. Is the commit message readable and correct? If it contains a breaking change
267 | is it clear enough?
268 |
269 | Note that only **incremental** improvement is needed to land a PR. This means
270 | that the PR does not need to be perfect, only better than the status quo. Follow
271 | up PRs may be opened to continue iterating.
272 |
273 | When changes are necessary, _request_ them, do not _demand_ them, and **do not
274 | assume that the submitter already knows how to add a test or run a benchmark**.
275 |
276 | Specific performance optimization techniques, coding styles and conventions
277 | change over time. The first impression you give to a new contributor never does.
278 |
279 | Nits (requests for small changes that are not essential) are fine, but try to
280 | avoid stalling the Pull Request. Most nits can typically be fixed by the
281 | Alloy Collaborator landing the Pull Request but they can also be an
282 | opportunity for the contributor to learn a bit more about the project.
283 |
284 | It is always good to clearly indicate nits when you comment: e.g.
285 | `Nit: change foo() to bar(). But this is not blocking.`
286 |
287 | If your comments were addressed but were not folded automatically after new
288 | commits or if they proved to be mistaken, please, [hide them][hiding-a-comment]
289 | with the appropriate reason to keep the conversation flow concise and relevant.
290 |
291 | ### Be aware of the person behind the code
292 |
293 | Be aware that _how_ you communicate requests and reviews in your feedback can
294 | have a significant impact on the success of the Pull Request. Yes, we may land
295 | a particular change that makes Alloy better, but the individual might just
296 | not want to have anything to do with Alloy ever again. The goal is not just
297 | having good code.
298 |
299 | ### Abandoned or Stalled Pull Requests
300 |
301 | If a Pull Request appears to be abandoned or stalled, it is polite to first
302 | check with the contributor to see if they intend to continue the work before
303 | checking if they would mind if you took it over (especially if it just has nits
304 | left). When doing so, it is courteous to give the original contributor credit
305 | for the work they started (either by preserving their name and email address in
306 | the commit log, or by using an `Author: ` meta-data tag in the commit.
307 |
308 | _Adapted from the [Tokio contributing guide]_.
309 |
310 | [hiding-a-comment]: https://help.github.com/articles/managing-disruptive-comments/#hiding-a-comment
311 | [documentation test]: https://doc.rust-lang.org/rustdoc/documentation-tests.html
312 | [Tokio contributing guide]: https://github.com/tokio-rs/tokio/blob/master/CONTRIBUTING.md
313 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = ["crates/*"]
3 | resolver = "2"
4 |
5 | [workspace.package]
6 | version = "0.10.0"
7 | edition = "2021"
8 | rust-version = "1.85"
9 | authors = ["Alloy Contributors"]
10 | license = "MIT OR Apache-2.0"
11 | homepage = "https://github.com/alloy-rs/alloy-evm"
12 | repository = "https://github.com/alloy-rs/alloy-evm"
13 | exclude = ["benches/", "tests/"]
14 |
15 | [workspace.lints.rustdoc]
16 | all = "warn"
17 |
18 | [workspace.lints.rust]
19 | missing-debug-implementations = "warn"
20 | missing-docs = "warn"
21 | unreachable-pub = "warn"
22 | unused-must-use = "deny"
23 | rust-2018-idioms = "deny"
24 | unnameable-types = "warn"
25 |
26 | [workspace.lints.clippy]
27 | all = { level = "warn", priority = -1 }
28 | missing-const-for-fn = "allow" # TODO: https://github.com/rust-lang/rust-clippy/issues/14020
29 | use-self = "warn"
30 | option-if-let-else = "warn"
31 | redundant-clone = "warn"
32 |
33 | [workspace.metadata.docs.rs]
34 | all-features = true
35 | rustdoc-args = ["--cfg", "docsrs"]
36 |
37 | [workspace.dependencies]
38 | alloy-evm = { version = "0.10.0", path = "crates/evm", default-features = false }
39 | alloy-op-evm = { version = "0.10.0", path = "crates/op-evm", default-features = false }
40 |
41 | # alloy
42 | alloy-eip2124 = { version = "0.2", default-features = false }
43 | alloy-chains = { version = "0.2.0", default-features = false }
44 | alloy-eips = { version = "1.0", default-features = false }
45 | alloy-consensus = { version = "1.0.0", default-features = false }
46 | alloy-primitives = { version = "1.0.0", default-features = false }
47 | alloy-sol-types = { version = "1.0.0", default-features = false }
48 | alloy-hardforks = { version = "0.2" }
49 |
50 | # op-alloy
51 | alloy-op-hardforks = { version = "0.2" }
52 | op-alloy-consensus = { version = "0.17", default-features = false }
53 |
54 | # revm
55 | revm = { version = "24.0.0", default-features = false }
56 | op-revm = { version = "5.0.0", default-features = false }
57 |
58 | # misc
59 | auto_impl = "1"
60 | derive_more = { version = "2", default-features = false, features = ["full"] }
61 | serde = { version = "1", default-features = false, features = ["derive"] }
62 | thiserror = { version = "2.0.0", default-features = false }
63 | serde_json = "1"
64 |
--------------------------------------------------------------------------------
/LICENSE-APACHE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Permission is hereby granted, free of charge, to any
2 | person obtaining a copy of this software and associated
3 | documentation files (the "Software"), to deal in the
4 | Software without restriction, including without
5 | limitation the rights to use, copy, modify, merge,
6 | publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software
8 | is furnished to do so, subject to the following
9 | conditions:
10 |
11 | The above copyright notice and this permission notice
12 | shall be included in all copies or substantial portions
13 | of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # :construction: This repository is a work in progress.
2 |
3 | # Alloy-EVM
4 |
5 | ## Overview
6 |
7 | `alloy-evm` is an abstraction layer on top of [revm](https://github.com/bluealloy/revm) providing common implementations of EVMs. Currently, alloy-evm is only used in Reth but is designed to be consumed by any project that needs to execute/trace transactions or blocks on EVM compatible chains.
8 |
9 | `alloy-evm` is compatible with no_std and riscv targets.
10 |
11 | #### License
12 |
13 |
14 | Licensed under either of Apache License, Version
15 | 2.0 or MIT license at your option.
16 |
17 |
18 |
19 |
20 |
21 | Unless you explicitly state otherwise, any contribution intentionally submitted
22 | for inclusion in these crates by you, as defined in the Apache-2.0 license,
23 | shall be dual licensed as above, without any additional terms or conditions.
24 |
25 |
--------------------------------------------------------------------------------
/cliff.toml:
--------------------------------------------------------------------------------
1 | # Configuration file for [`git-cliff`](https://github.com/orhun/git-cliff)
2 | # See https://git-cliff.org/docs/configuration
3 |
4 | [changelog]
5 | header = """
6 | # Changelog
7 |
8 | All notable changes to this project will be documented in this file.
9 |
10 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
11 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n
12 | """
13 | # https://tera.netlify.app/docs/#introduction
14 | body = """
15 | {% if version %}\
16 | ## [{{ version | trim_start_matches(pat="v") }}](https://github.com/alloy-rs/evm/releases/tag/v{{ version | trim_start_matches(pat="v") }}) - {{ timestamp | date(format="%Y-%m-%d") }}
17 | {% endif %}\
18 | {% for group, commits in commits | group_by(attribute="group") %}
19 | ### {{ group | title }}
20 | {% for commit in commits %}
21 | - {% if commit.scope %}[{{ commit.scope }}] {% endif %}{{ commit.message | upper_first | split(pat="\\n") | first }}\
22 | {% endfor %}
23 | {% endfor %}\n
24 | """
25 | trim = true
26 | footer = ""
27 |
28 | [git]
29 | conventional_commits = true
30 | filter_unconventional = false
31 | commit_preprocessors = [
32 | { pattern = '#(\d+)', replace = "[#$1](https://github.com/alloy-rs/evm/issues/$1)" },
33 | ]
34 | commit_parsers = [
35 | { message = "^[Ff]eat", group = "Features" },
36 | { message = "^[Ff]ix", group = "Bug Fixes" },
37 | { message = "^[Dd]oc", group = "Documentation" },
38 | { message = ".*\\b([Dd]eps|[Dd]ependencies|[Bb]ump)\\b", group = "Dependencies" },
39 | { message = "^[Pp]erf", group = "Performance" },
40 | { message = "^[Rr]efactor", group = "Refactor" },
41 | { message = ".*\\b([Ss]tyle|[Ff]mt|[Ff]ormat)\\b", group = "Styling" },
42 | { message = "^[Tt]est", group = "Testing" },
43 | { message = "^[Cc]hore", group = "Miscellaneous Tasks" },
44 |
45 | { message = ".*", group = "Other" },
46 | ]
47 | protect_breaking_commits = false
48 | filter_commits = false
49 | tag_pattern = "v[0-9]*"
50 | skip_tags = "beta|alpha"
51 | ignore_tags = "rc"
52 | sort_commits = "newest"
53 |
--------------------------------------------------------------------------------
/clippy.toml:
--------------------------------------------------------------------------------
1 | msrv = "1.85"
2 |
--------------------------------------------------------------------------------
/crates/evm/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "alloy-evm"
3 | description = "EVM abstraction for Alloy"
4 |
5 | version.workspace = true
6 | edition.workspace = true
7 | rust-version.workspace = true
8 | authors.workspace = true
9 | license.workspace = true
10 | homepage.workspace = true
11 | repository.workspace = true
12 |
13 | [lints]
14 | workspace = true
15 |
16 | [dependencies]
17 | alloy-consensus = { workspace = true, features = ["k256"] }
18 | alloy-primitives.workspace = true
19 | alloy-sol-types.workspace = true
20 | alloy-eips.workspace = true
21 | alloy-hardforks.workspace = true
22 |
23 | revm.workspace = true
24 | op-revm = { workspace = true, optional = true }
25 | op-alloy-consensus = { workspace = true, optional = true }
26 |
27 | auto_impl.workspace = true
28 | derive_more.workspace = true
29 | thiserror.workspace = true
30 |
31 | [dev-dependencies]
32 | alloy-primitives = { workspace = true, features = ["serde"] }
33 | serde_json.workspace = true
34 |
35 | [features]
36 | default = ["std"]
37 | secp256k1 = [
38 | "std",
39 | "alloy-consensus/secp256k1",
40 | ]
41 | std = [
42 | "alloy-primitives/std",
43 | "revm/std",
44 | "alloy-consensus/std",
45 | "alloy-eips/std",
46 | "alloy-sol-types/std",
47 | "derive_more/std",
48 | "op-revm?/std",
49 | "thiserror/std",
50 | "op-alloy-consensus?/std"
51 | ]
52 | op = ["op-revm", "op-alloy-consensus"]
53 |
--------------------------------------------------------------------------------
/crates/evm/README.md:
--------------------------------------------------------------------------------
1 | # alloy-evm
2 |
3 | EVM interface.
4 |
5 | This crate contains constants, types, and functions for interacting with the Ethereum Virtual Machine (EVM).
6 | It is compatible with the types from the [alloy](https://crates.io/crates/alloy) ecosystem and comes with batteries included for [revm](https://crates.io/crates/revm)
7 |
8 |
--------------------------------------------------------------------------------
/crates/evm/src/block/calc.rs:
--------------------------------------------------------------------------------
1 | //! Helpers to perform common calculations.
2 |
3 | use alloy_consensus::constants::ETH_TO_WEI;
4 | use alloy_hardforks::EthereumHardforks;
5 | use alloy_primitives::BlockNumber;
6 |
7 | /// Calculates the base block reward.
8 | ///
9 | /// The base block reward is defined as:
10 | ///
11 | /// - For Paris and later: `None`
12 | /// - For Petersburg and later: `Some(2 ETH)`
13 | /// - For Byzantium and later: `Some(3 ETH)`
14 | /// - Otherwise: `Some(5 ETH)`
15 | ///
16 | /// # Note
17 | ///
18 | /// This does not include the reward for including ommers. To calculate the full block reward, see
19 | /// [`block_reward`].
20 | ///
21 | /// # References
22 | ///
23 | /// - Definition: [Yellow Paper][yp] (page 15, 11.3)
24 | ///
25 | /// [yp]: https://ethereum.github.io/yellowpaper/paper.pdf
26 | pub fn base_block_reward(spec: impl EthereumHardforks, block_number: BlockNumber) -> Option {
27 | if spec.is_paris_active_at_block(block_number) {
28 | None
29 | } else {
30 | Some(base_block_reward_pre_merge(spec, block_number))
31 | }
32 | }
33 |
34 | /// Calculates the base block reward __before__ the merge (Paris hardfork).
35 | ///
36 | /// Caution: The caller must ensure that the block number is before the merge.
37 | pub fn base_block_reward_pre_merge(
38 | spec: impl EthereumHardforks,
39 | block_number: BlockNumber,
40 | ) -> u128 {
41 | if spec.is_constantinople_active_at_block(block_number) {
42 | ETH_TO_WEI * 2
43 | } else if spec.is_byzantium_active_at_block(block_number) {
44 | ETH_TO_WEI * 3
45 | } else {
46 | ETH_TO_WEI * 5
47 | }
48 | }
49 |
50 | /// Calculates the reward for a block, including the reward for ommer inclusion.
51 | ///
52 | /// The base reward should be calculated using [`base_block_reward`]. `ommers` represents the number
53 | /// of ommers included in the block.
54 | ///
55 | /// # Examples
56 | ///
57 | /// ```
58 | /// # use alloy_hardforks::EthereumChainHardforks;
59 | /// # use alloy_evm::block::calc::{base_block_reward, block_reward};
60 | /// # use alloy_consensus::constants::ETH_TO_WEI;
61 | /// # use alloy_primitives::U256;
62 | /// #
63 | /// // This is block 126 on mainnet.
64 | /// let block_number = 126;
65 | /// let number_of_ommers = 1;
66 | ///
67 | /// let reward = base_block_reward(EthereumChainHardforks::mainnet(), block_number)
68 | /// .map(|reward| block_reward(reward, 1));
69 | ///
70 | /// // The base block reward is 5 ETH, and the ommer inclusion reward is 1/32th of 5 ETH.
71 | /// assert_eq!(reward.unwrap(), ETH_TO_WEI * 5 + ((ETH_TO_WEI * 5) >> 5));
72 | /// ```
73 | ///
74 | /// # References
75 | ///
76 | /// - Definition: [Yellow Paper][yp] (page 15, 11.3)
77 | ///
78 | /// [yp]: https://ethereum.github.io/yellowpaper/paper.pdf
79 | pub const fn block_reward(base_block_reward: u128, ommers: usize) -> u128 {
80 | base_block_reward + (base_block_reward >> 5) * ommers as u128
81 | }
82 |
83 | /// Calculate the reward for an ommer.
84 | ///
85 | /// # Application
86 | ///
87 | /// Rewards are accumulative, so they should be added to the beneficiary addresses in addition to
88 | /// any other rewards from the same block.
89 | ///
90 | /// From the yellow paper (page 15):
91 | ///
92 | /// > If there are collisions of the beneficiary addresses between ommers and the block (i.e. two
93 | /// > ommers with the same beneficiary address or an ommer with the same beneficiary address as the
94 | /// > present block), additions are applied cumulatively.
95 | ///
96 | /// # References
97 | ///
98 | /// - Implementation: [OpenEthereum][oe]
99 | /// - Definition: [Yellow Paper][yp] (page 15, 11.3)
100 | ///
101 | /// [oe]: https://github.com/openethereum/openethereum/blob/6c2d392d867b058ff867c4373e40850ca3f96969/crates/ethcore/src/ethereum/ethash.rs#L319-L333
102 | /// [yp]: https://ethereum.github.io/yellowpaper/paper.pdf
103 | pub const fn ommer_reward(
104 | base_block_reward: u128,
105 | block_number: BlockNumber,
106 | ommer_block_number: BlockNumber,
107 | ) -> u128 {
108 | ((8 + ommer_block_number - block_number) as u128 * base_block_reward) >> 3
109 | }
110 |
111 | #[cfg(test)]
112 | mod tests {
113 | use super::*;
114 | use alloy_hardforks::EthereumChainHardforks;
115 | use alloy_primitives::U256;
116 |
117 | #[test]
118 | fn calc_base_block_reward() {
119 | // ((block number, td), reward)
120 | let cases = [
121 | // Pre-byzantium
122 | ((0, U256::ZERO), Some(ETH_TO_WEI * 5)),
123 | // Byzantium
124 | ((4370000, U256::ZERO), Some(ETH_TO_WEI * 3)),
125 | // Petersburg
126 | ((7280000, U256::ZERO), Some(ETH_TO_WEI * 2)),
127 | // Merge
128 | ((15537394, U256::from(58_750_000_000_000_000_000_000_u128)), None),
129 | ];
130 |
131 | for ((block_number, _td), expected_reward) in cases {
132 | assert_eq!(
133 | base_block_reward(EthereumChainHardforks::mainnet(), block_number),
134 | expected_reward
135 | );
136 | }
137 | }
138 |
139 | #[test]
140 | fn calc_full_block_reward() {
141 | let base_reward = ETH_TO_WEI;
142 | let one_thirty_twoth_reward = base_reward >> 5;
143 |
144 | // (num_ommers, reward)
145 | let cases = [
146 | (0, base_reward),
147 | (1, base_reward + one_thirty_twoth_reward),
148 | (2, base_reward + one_thirty_twoth_reward * 2),
149 | ];
150 |
151 | for (num_ommers, expected_reward) in cases {
152 | assert_eq!(block_reward(base_reward, num_ommers), expected_reward);
153 | }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/crates/evm/src/block/error.rs:
--------------------------------------------------------------------------------
1 | use crate::{EvmError, InvalidTxError};
2 | use alloc::{
3 | boxed::Box,
4 | string::{String, ToString},
5 | };
6 | use alloy_primitives::B256;
7 |
8 | /// Block validation error.
9 | #[derive(Debug, thiserror::Error)]
10 | pub enum BlockValidationError {
11 | /// EVM error with transaction hash and message
12 | #[error("EVM reported invalid transaction ({hash}): {error}")]
13 | InvalidTx {
14 | /// The hash of the transaction
15 | hash: B256,
16 | /// The EVM error.
17 | error: Box,
18 | },
19 | /// Error when incrementing balance in post execution
20 | #[error("incrementing balance in post execution failed")]
21 | IncrementBalanceFailed,
22 | /// Error when transaction gas limit exceeds available block gas
23 | #[error(
24 | "transaction gas limit {transaction_gas_limit} is more than blocks available gas {block_available_gas}"
25 | )]
26 | TransactionGasLimitMoreThanAvailableBlockGas {
27 | /// The transaction's gas limit
28 | transaction_gas_limit: u64,
29 | /// The available block gas
30 | block_available_gas: u64,
31 | },
32 | /// Error for EIP-4788 when parent beacon block root is missing
33 | #[error("EIP-4788 parent beacon block root missing for active Cancun block")]
34 | MissingParentBeaconBlockRoot,
35 | /// Error for Cancun genesis block when parent beacon block root is not zero
36 | #[error(
37 | "the parent beacon block root is not zero for Cancun genesis block: {parent_beacon_block_root}"
38 | )]
39 | CancunGenesisParentBeaconBlockRootNotZero {
40 | /// The beacon block root
41 | parent_beacon_block_root: B256,
42 | },
43 | /// EVM error during [EIP-4788] beacon root contract call.
44 | ///
45 | /// [EIP-4788]: https://eips.ethereum.org/EIPS/eip-4788
46 | #[error("failed to apply beacon root contract call at {parent_beacon_block_root}: {message}")]
47 | BeaconRootContractCall {
48 | /// The beacon block root
49 | parent_beacon_block_root: Box,
50 | /// The error message.
51 | message: String,
52 | },
53 | /// EVM error during [EIP-2935] blockhash contract call.
54 | ///
55 | /// [EIP-2935]: https://eips.ethereum.org/EIPS/eip-2935
56 | #[error("failed to apply blockhash contract call: {message}")]
57 | BlockHashContractCall {
58 | /// The error message.
59 | message: String,
60 | },
61 | /// EVM error during withdrawal requests contract call [EIP-7002]
62 | ///
63 | /// [EIP-7002]: https://eips.ethereum.org/EIPS/eip-7002
64 | #[error("failed to apply withdrawal requests contract call: {message}")]
65 | WithdrawalRequestsContractCall {
66 | /// The error message.
67 | message: String,
68 | },
69 | /// EVM error during consolidation requests contract call [EIP-7251]
70 | ///
71 | /// [EIP-7251]: https://eips.ethereum.org/EIPS/eip-7251
72 | #[error("failed to apply consolidation requests contract call: {message}")]
73 | ConsolidationRequestsContractCall {
74 | /// The error message.
75 | message: String,
76 | },
77 | /// Error when decoding deposit requests from receipts [EIP-6110]
78 | ///
79 | /// [EIP-6110]: https://eips.ethereum.org/EIPS/eip-6110
80 | #[error("failed to decode deposit requests from receipts: {_0}")]
81 | DepositRequestDecode(String),
82 | }
83 |
84 | /// `BlockExecutor` Errors
85 | #[derive(Debug, thiserror::Error)]
86 | pub enum BlockExecutionError {
87 | /// Validation error, transparently wrapping [`BlockValidationError`]
88 | #[error(transparent)]
89 | Validation(#[from] BlockValidationError),
90 | /// Internal, i.e. non consensus or validation related Block Executor Errors
91 | #[error(transparent)]
92 | Internal(#[from] InternalBlockExecutionError),
93 | }
94 |
95 | impl BlockExecutionError {
96 | /// Create a new [`BlockExecutionError::Internal`] variant, containing a
97 | /// [`InternalBlockExecutionError::Other`] error.
98 | pub fn other(error: E) -> Self
99 | where
100 | E: core::error::Error + Send + Sync + 'static,
101 | {
102 | Self::Internal(InternalBlockExecutionError::other(error))
103 | }
104 |
105 | /// Create a new [`BlockExecutionError::Internal`] variant, containing a
106 | /// [`InternalBlockExecutionError::Other`] error with the given message.
107 | pub fn msg(msg: impl core::fmt::Display) -> Self {
108 | Self::Internal(InternalBlockExecutionError::msg(msg))
109 | }
110 |
111 | /// Returns the inner `BlockValidationError` if the error is a validation error.
112 | pub const fn as_validation(&self) -> Option<&BlockValidationError> {
113 | match self {
114 | Self::Validation(err) => Some(err),
115 | _ => None,
116 | }
117 | }
118 |
119 | /// Handles an EVM error occurred when executing a transaction.
120 | ///
121 | /// If an error matches [`EvmError::InvalidTransaction`], it will be wrapped into
122 | /// [`BlockValidationError::InvalidTx`], otherwise into [`InternalBlockExecutionError::EVM`].
123 | pub fn evm(error: E, hash: B256) -> Self {
124 | match error.try_into_invalid_tx_err() {
125 | Ok(err) => {
126 | Self::Validation(BlockValidationError::InvalidTx { hash, error: Box::new(err) })
127 | }
128 | Err(err) => {
129 | Self::Internal(InternalBlockExecutionError::EVM { hash, error: Box::new(err) })
130 | }
131 | }
132 | }
133 | }
134 |
135 | /// Internal (i.e., not validation or consensus related) `BlockExecutor` Errors
136 | #[derive(Debug, thiserror::Error)]
137 | pub enum InternalBlockExecutionError {
138 | /// EVM error occurred when executing transaction. This is different from
139 | /// [`BlockValidationError::InvalidTx`] because it will only contain EVM errors which are not
140 | /// transaction validation errors and are assumed to be fatal.
141 | #[error("internal EVM error occurred when executing transaction {hash}: {error}")]
142 | EVM {
143 | /// The hash of the transaction
144 | hash: B256,
145 | /// The EVM error.
146 | error: Box,
147 | },
148 | /// Arbitrary Block Executor Errors
149 | #[error(transparent)]
150 | Other(Box),
151 | }
152 |
153 | impl InternalBlockExecutionError {
154 | /// Create a new [`InternalBlockExecutionError::Other`] variant.
155 | pub fn other(error: E) -> Self
156 | where
157 | E: core::error::Error + Send + Sync + 'static,
158 | {
159 | Self::Other(Box::new(error))
160 | }
161 |
162 | /// Create a new [`InternalBlockExecutionError::Other`] from a given message.
163 | pub fn msg(msg: impl core::fmt::Display) -> Self {
164 | Self::Other(msg.to_string().into())
165 | }
166 |
167 | /// Returns the arbitrary error if it is [`InternalBlockExecutionError::Other`]
168 | pub fn as_other(&self) -> Option<&(dyn core::error::Error + Send + Sync + 'static)> {
169 | match self {
170 | Self::Other(err) => Some(&**err),
171 | _ => None,
172 | }
173 | }
174 |
175 | /// Attempts to downcast the [`InternalBlockExecutionError::Other`] variant to a concrete type
176 | pub fn downcast(self) -> Result, Self> {
177 | match self {
178 | Self::Other(err) => err.downcast().map_err(Self::Other),
179 | err => Err(err),
180 | }
181 | }
182 |
183 | /// Returns a reference to the [`InternalBlockExecutionError::Other`] value if this type is a
184 | /// [`InternalBlockExecutionError::Other`] of that type. Returns None otherwise.
185 | pub fn downcast_other(&self) -> Option<&T> {
186 | let other = self.as_other()?;
187 | other.downcast_ref()
188 | }
189 |
190 | /// Returns true if the this type is a [`InternalBlockExecutionError::Other`] of that error
191 | /// type. Returns false otherwise.
192 | pub fn is_other(&self) -> bool {
193 | self.as_other().map(|err| err.is::()).unwrap_or(false)
194 | }
195 | }
196 |
197 | #[cfg(test)]
198 | mod tests {
199 | use super::*;
200 |
201 | #[derive(thiserror::Error, Debug)]
202 | #[error("err")]
203 | struct E;
204 |
205 | #[test]
206 | fn other_downcast() {
207 | let err = InternalBlockExecutionError::other(E);
208 | assert!(err.is_other::());
209 |
210 | assert!(err.downcast_other::().is_some());
211 | assert!(err.downcast::().is_ok());
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/crates/evm/src/block/mod.rs:
--------------------------------------------------------------------------------
1 | //! Block execution abstraction.
2 |
3 | use crate::{
4 | Database, Evm, EvmFactory, FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, RecoveredTx,
5 | };
6 | use alloc::{boxed::Box, vec::Vec};
7 | use alloy_eips::eip7685::Requests;
8 | use revm::{
9 | context::result::ExecutionResult, database::State, inspector::NoOpInspector, Inspector,
10 | };
11 |
12 | mod error;
13 | pub use error::*;
14 |
15 | mod state_hook;
16 | pub use state_hook::*;
17 |
18 | pub mod system_calls;
19 | pub use system_calls::*;
20 |
21 | pub mod state_changes;
22 |
23 | pub mod calc;
24 |
25 | /// The result of executing a block.
26 | #[derive(Debug, Clone, Default, PartialEq, Eq)]
27 | pub struct BlockExecutionResult {
28 | /// All the receipts of the transactions in the block.
29 | pub receipts: Vec,
30 | /// All the EIP-7685 requests in the block.
31 | pub requests: Requests,
32 | /// The total gas used by the block.
33 | pub gas_used: u64,
34 | }
35 |
36 | /// Helper trait to encapsulate requirements for a type to be used as input for [`BlockExecutor`].
37 | pub trait ExecutableTx:
38 | IntoTxEnv<::Tx> + RecoveredTx + Copy
39 | {
40 | }
41 | impl ExecutableTx for T where
42 | T: IntoTxEnv<::Tx> + RecoveredTx + Copy
43 | {
44 | }
45 |
46 | /// Marks whether transaction should be commited into block executor's state.
47 | #[derive(Debug, Clone, Copy, PartialEq, Eq)]
48 | #[must_use]
49 | pub enum CommitChanges {
50 | /// Transaction should be commited into block executor's state.
51 | Yes,
52 | /// Transaction should not be commited.
53 | No,
54 | }
55 |
56 | impl CommitChanges {
57 | /// Returns `true` if transaction should be commited into block executor's state.
58 | pub fn should_commit(self) -> bool {
59 | matches!(self, Self::Yes)
60 | }
61 | }
62 |
63 | /// A type that knows how to execute a single block.
64 | ///
65 | /// The current abstraction assumes that block execution consists of the following steps:
66 | /// 1. Apply pre-execution changes. Those might include system calls, irregular state transitions
67 | /// (DAO fork), etc.
68 | /// 2. Apply block transactions to the state.
69 | /// 3. Apply post-execution changes and finalize the state. This might include other system calls,
70 | /// block rewards, etc.
71 | ///
72 | /// The output of [`BlockExecutor::finish`] is a [`BlockExecutionResult`] which contains all
73 | /// relevant information about the block execution.
74 | pub trait BlockExecutor {
75 | /// Input transaction type.
76 | type Transaction;
77 | /// Receipt type this executor produces.
78 | type Receipt;
79 | /// EVM used by the executor.
80 | type Evm: Evm + FromTxWithEncoded>;
81 |
82 | /// Applies any necessary changes before executing the block's transactions.
83 | fn apply_pre_execution_changes(&mut self) -> Result<(), BlockExecutionError>;
84 |
85 | /// Executes a single transaction and applies execution result to internal state.
86 | ///
87 | /// Returns the gas used by the transaction.
88 | fn execute_transaction(
89 | &mut self,
90 | tx: impl ExecutableTx,
91 | ) -> Result {
92 | self.execute_transaction_with_result_closure(tx, |_| ())
93 | }
94 |
95 | /// Executes a single transaction and applies execution result to internal state. Invokes the
96 | /// given closure with an internal [`ExecutionResult`] produced by the EVM.
97 | fn execute_transaction_with_result_closure(
98 | &mut self,
99 | tx: impl ExecutableTx,
100 | f: impl FnOnce(&ExecutionResult<::HaltReason>),
101 | ) -> Result {
102 | self.execute_transaction_with_commit_condition(tx, |res| {
103 | f(res);
104 | CommitChanges::Yes
105 | })
106 | .map(Option::unwrap_or_default)
107 | }
108 |
109 | /// Executes a single transaction and applies execution result to internal state. Invokes the
110 | /// given closure with an internal [`ExecutionResult`] produced by the EVM, and commits the
111 | /// transaction to the state on [`CommitChanges::Yes`].
112 | ///
113 | /// Returns [`None`] if transaction was skipped via [`CommitChanges::No`].
114 | fn execute_transaction_with_commit_condition(
115 | &mut self,
116 | tx: impl ExecutableTx,
117 | f: impl FnOnce(&ExecutionResult<::HaltReason>) -> CommitChanges,
118 | ) -> Result