feat(revm-inspectors): upgrade to upstream v0.39.0 for Mantle Elysium#9
Merged
Conversation
bump patch
## Motivation <!-- Explain the context and why you're making that change. What is the problem you're trying to solve? In some cases there is not a problem and this can be thought of as being the motivation for your change. --> Per: https://github.com/bluealloy/revm/releases/tag/v100
…z#383) This aims at resolving issues mentioned in paradigmxyz#382 , typically this one : <img width="1818" height="694" alt="image" src="https://github.com/user-attachments/assets/51b82944-c711-421b-8479-05095ae9bbce" /> To fix this , what i did was : - Keep track of addresses that are marked as Create and were truly empty in the database snapshot. Only these addresses are filtered from the prestate diff so prefunded contract deployments remain visible. - Introduce account_was_empty helper to avoid re-computing the emptiness check and add a regression test (prestate_diff_keeps_prefunded_created_accounts) that covers a prefunded creation vs. a true empty-address creation. cc @mattsse Please check it out if it resolves should close this one paradigmxyz/reth#19703 --------- Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
Moves `DebugInspector` from reth to revm-inspectors as requested in paradigmxyz/reth#19932. This was introduced in paradigmxyz/reth#19925 to unify debug tracing across all Geth tracer types.
this fixes an issue where we would return diffs like
```
"post": {
"0x093f6c270ac22ec240f0c6fd7414ea774ca8d3e5": {},
"0x2641c2ded63a0c640629f5edf1189e0f53c06561": {},
```
for `0x91b066df39661db7bcca1cb8bb8afd11816414408d44cbfcf6144f440d5dfe3b`
ref paradigmxyz/reth#19703
however nothing changed in the account here and these should have been
filtered out via:
https://github.com/paradigmxyz/revm-inspectors/blob/f7503520888efc11eac3142fe7d611c519811b25/src/tracing/builder/geth.rs#L349-L349
and cleared from post via:
https://github.com/alloy-rs/alloy/blob/35e20437670d987680a6715bcc173f3d357f8254/crates/rpc-types-trace/src/geth/pre_state.rs#L188-L201
the reason why this didn't work is because:
the code can be None here which would make retain_change not remove the
values
```
"result": {
"post": {
"0x093f6c270ac22ec240f0c6fd7414ea774ca8d3e5": {},
"0x2641c2ded63a0c640629f5edf1189e0f53c06561": {},
"0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5": {
"balance": "0xc87826afc2b88254"
},
"0xbf5495efe5db9ce00f80364c8b423567e58d2110": {
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000035": "0x000000000000000000000000000000000000000000004b7b53b759cac06bc3b2",
"0xec8c572bc2e66bfe14376dece39002d6d97d311020c59bc23a93016013e92439": "0x0000000000000000000000000000000000000000000000000f294a8cb09ad9cb"
}
},
"0xbfe474605fb7f1cf3693a3f21af2e329f7222462": {
"balance": "0x269f4a55a240465",
"nonce": 5
},
"0xf2f305d14dcd8aaef887e0428b3c9534795d0d60": {
"balance": "0xe984e9959d534d3cdf"
}
},
"pre": {
"0x093f6c270ac22ec240f0c6fd7414ea774ca8d3e5": {
"balance": "0x1ea3abe47d76b5e00",
"code": "..",
"nonce": 1
},
"0x2641c2ded63a0c640629f5edf1189e0f53c06561": {
"balance": "0x1cb3ca6ff6dc41400",
"code": "..",
"nonce": 1
},
"0x95222290dd7278aa3ddd389cc1e1d165cc4bafe5": {
"balance": "0xc8781d351add1146",
"nonce": 797368
},
"0xbf5495efe5db9ce00f80364c8b423567e58d2110": {
"balance": "0x0",
"code": "...",
"nonce": 1,
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000035": "0x000000000000000000000000000000000000000000004b7b448e0f3e0fd0e9e7"
}
},
"0xbfe474605fb7f1cf3693a3f21af2e329f7222462": {
"balance": "0x11d7cc57700ae2ed",
"nonce": 4
},
"0xf2f305d14dcd8aaef887e0428b3c9534795d0d60": {
"balance": "0xe975a599714e5f3cdf",
"code": "...",
"nonce": 1
}
}
},
```
we can always use the precode here if the hashes match
This aims to resolve this issue : paradigmxyz#391 cc @mattsse
stage latest main commit --------- Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
…race` (paradigmxyz#389) The default tracer for `debug_*` RPC methods was not reporting warmed storage values. This deviates from Get's implementation and—seemingly—the documented expectation: ```rs /// Represents a storage change during execution. /// /// This maps to evm internals: /// [JournalEntry::StorageChanged](revm::JournalEntry::StorageChanged) /// /// It is used to track both storage change and warm load of a storage slot. For warm load in regard /// to EIP-2929 AccessList had_value will be None. #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct StorageChange { /// key of the storage slot pub key: U256, /// Current value of the storage slot pub value: U256, /// The previous value of the storage slot, if any pub had_value: Option<U256>, /// How this storage was accessed pub reason: StorageChangeReason, } ``` In particular, the `SLOAD` for pc `235`, `279`, and `308` are missing `"storage"`. This PR resolves the issue. For reference: [revm-inspectors.json](https://github.com/user-attachments/files/24275105/revm-inspectors.json) [geth.json](https://github.com/user-attachments/files/24275106/geth.json)
Add reusable tooling for debugging RPC tracing using prestate tracer
responses captured from mainnet transactions.
## Changes
- Add `tests/it/repro.rs` with:
- `ReproTestFixture`/`TxData` types for deserializing JSON fixtures
- `spec_id_from_ethereum_hardfork`/`spec_id_from_block` helpers
- `build_db_from_prestate` to populate CacheDB from AccountState
- `ReproContext` builder for easy test setup
- Add `testdata/repro/tx-selfdestruct.json` fixture from reth's e2e test
(mainnet tx 0x391f4b6a...selfdestruct via USDT withdrawal)
- Add `alloy-hardforks` dev dependency for block-to-hardfork mapping
## Usage
```rust
const FIXTURE: &str = include_str!("../../testdata/repro/my-fixture.json");
#[test]
fn test_my_trace() {
let ctx = ReproContext::load(FIXTURE);
let config = PreStateConfig::default();
let mut inspector = TracingInspector::new(
TracingInspectorConfig::from_geth_prestate_config(&config)
);
let db = ctx.db.clone();
let mut evm = Context::mainnet()
.with_db(ctx.db.clone())
.modify_cfg_chained(|cfg| cfg.spec = ctx.spec_id)
.build_mainnet()
.with_inspector(&mut inspector);
let res = evm.inspect_tx(ctx.tx_env()).unwrap();
// ... assertions on trace results
}
```
This enables writing repro tests with the flow:
**raw transaction + prestate JSON → configure tracer → run → assert**
Refs:
https://github.com/paradigmxyz/reth/blob/main/crates/ethereum/node/tests/e2e/prestate.rs
---------
Co-authored-by: Amp <amp@ampcode.com>
…lity (paradigmxyz#401) Use `..Default::default()` pattern to ensure forward compatibility when new fields are added to `TransactionInfo`. This prepares the crate for upcoming changes to add a `block_timestamp` field. Related: ethereum/execution-apis#729 Co-authored-by: Amp <amp@ampcode.com>
Required to be able to recover pre-refund totals from purely just the `CallTrace` for gas introspection in foundry. foundry-rs/foundry#13262
Bump MSRV from 1.86 to 1.91.
Implement `Clone` for `DebugInspector` to enable use with `TxTracer`, which requires `Inspector: Clone`. Non-JS variants clone trivially. The `Js` variant reconstructs the `JsInspector` from its stored `code` and `config` — same approach `fuse()` already uses.
## Summary This PR is part of the **revm release procedure** (`devnet2-revm` chain). It bumps revm-inspectors to revm v35.0.0. ## Changes - Bump `revm` dependency from 34.0.0 to 35.0.0 in `Cargo.toml`. - Adapt to upstream API change: `journal().precompile_addresses()` now returns a type that requires `.iter().copied().collect()` instead of `.clone()`. - Lower `gas_limit` in selfdestruct tests from 100M to 10M to comply with EIP-7825 transaction gas limit cap enforced in revm 35. ## Validation - `cargo check` - `cargo +nightly clippy --workspace --all-targets --all-features` ## Procedure Context This is an intermediate dependency bump in the revm release flow before downstream updates in `alloy-evm` and `reth`.
## Summary - Bump `revm` dependency from 35.0.0 to 36.0.0 ## Test plan - [x] `cargo check` passes - [x] `cargo test` passes (all 37 tests)
## Summary Only include `returnData` in structLog output when the return-data buffer is non-empty, matching geth's behavior. ## Motivation [ethpandaops trace comparison report](https://investigations.ethpandaops.io/2026-01/trace-comparisons/reth/) shows reth emitting `returnData: "0x"` on **every** structLog step (~1.1M occurrences across 500 txs), while geth/erigon/nethermind/besu all omit it. Geth applies two independent gates before including `returnData`: 1. `cfg.EnableReturnData == true` (opt-in config) — we had this 2. `len(ReturnData) > 0` in `toLegacyJSON` — we were missing this ## Changes - `src/tracing/builder/geth.rs`: add `!step.returndata.is_empty()` check alongside the existing `opts.is_return_data_enabled()` gate ## Testing `cargo test --workspace` — all 24 tests pass, clippy clean. Co-Authored-By: Matthias Seitz <19890894+mattsse@users.noreply.github.com> Prompted by: mattsse Co-authored-by: Matthias Seitz <19890894+mattsse@users.noreply.github.com>
…xyz#412) Adds `set_transaction_caller` and `set_transaction_target` to `TracingInspector`, following the same pattern as `set_transaction_gas_used` / `set_transaction_gas_limit`. Custom transaction types (e.g. AA batches) may execute via a multi-call handler where the EVM's `call()` entry point doesn't reflect the actual transaction sender/recipient. This causes `callTracer` to report zeroed `from`/`to` on the root frame. These methods allow the execution layer to correct the root trace after execution. Co-Authored-By: zhygis <5236121+Zygimantass@users.noreply.github.com> Prompted by: zygis --------- Co-authored-by: zhygis <5236121+Zygimantass@users.noreply.github.com> Co-authored-by: Arsenii Kulikov <klkvrr@gmail.com>
…adigmxyz#416) Relax `CTX` bounds on `StorageInspector` `Inspector` impl as it doesn't use `Context`.
CallLog discarded the original Log.address during conversion and geth_empty_call_frame() reconstructed it from execution_address(). This is wrong for any log whose emitter differs from the call frame's execution context — most notably EIP-7708 system-level ETH transfer logs, which are emitted from SYSTEM_ADDRESS (0xfffffffffffffffffffffffffffffffffffffffe) rather than the executing contract. Changes src/tracing/types.rs - Add address: Address field to CallLog to preserve the original log emitter - Update From<Log> to store log.address instead of discarding it - Fix geth_empty_call_frame() to use log.address instead of self.execution_address() tests/it/geth.rs - test_geth_calltracer_logs_eip7708: value-transferring CALL to a precompile under AMSTERDAM — verifies the log address is ETH_TRANSFER_LOG_ADDRESS, not the contract or precompile address - test_geth_calltracer_logs_address_regular: regular LOG0 emission — verifies the log address is the emitting contract - test_geth_calltracer_logs_delegatecall: DELEGATECALL regression — verifies the log address is the proxy (execution context), not the implementation (bytecode) address Breaking CallLog is a public struct with a new address: Address field. Downstream consumers that construct CallLog manually will need to provide this field. Co-authored-by: Kai Yu <kai.yu@Kai-Yu-MacBook-Pro.local>
Bump alloy dependencies to released 2.0.0. No `[patch.crates-io]` needed. Supersedes paradigmxyz#419
## Summary - Update revm rev to `e3223d5b38f7affb901601ed917fa7cdc466be74` (rakita/state-gas branch) for TIP-1016 dual-limit gas accounting ## Test plan - [x] `cargo check` compiles clean - [x] `cargo +nightly clippy` passes - [x] `cargo nextest run` — all 37 tests pass --------- Co-authored-by: Federico Gimenez <federico.gimenez@gmail.com>
TracingInspector creates OpCodes via `new_unchecked` at `start_step` to handle unknown/custom opcodes. In `step_end`, `step.op.outputs()` calls `OpCode::info()` which panics with `"opcode not found"` when the opcode byte has no entry in `OPCODE_INFO`. Guard with `is_valid()` — unknown opcodes default to 0 outputs. Prompted by: Dragan --------- Co-authored-by: rakita <13179220+rakita@users.noreply.github.com> Co-authored-by: rakita <rakita@users.noreply.github.com>
…nfig (paradigmxyz#424) Two fixes based on the [ethpandaops trace comparison](https://investigations.ethpandaops.io/2026-01/trace-comparisons/): 1. Always include the refund counter in struct logs, even when zero. Previously omitted when value was 0, causing missing fields in trace output. 2. Wire `enableReturnData` from `GethDefaultTracingOptions` through to `TracingInspectorConfig::record_returndata_snapshots`. Previously this option was ignored, so returnData was never captured even when explicitly requested. Verified on a live reth archive node: - Refund: 22,476/67,028 steps → **67,028/67,028** steps - returnData with `enableReturnData: true`: 0 steps → **24,537** steps
…z#425) Two fixes to align with the [opcode tracer spec](ethereum/execution-apis#762): 1. Memory chunks now use `0x`-prefixed `bytes32` encoding. Previously `convert_memory()` used bare `hex::encode` without the prefix. 2. `returnData` is now included on every step when `enableReturnData` is true, even when the buffer is empty. Previously skipped when empty. --------- Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
## Summary - Bumps `revm` from `37.0.0` to `38.0.0`. ## Test plan - [ ] `cargo build` passes - [ ] `cargo test` passes - [ ] CI green
chore: Release revm-inspectors version 0.39.0 # -----BEGIN SSH SIGNATURE----- # U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg8rJYpWgyR5I9mnyGaprzVZUI1l # RlDUcbUYxr5WzpvdMAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 # AAAAQDeAVMIEWYNZoBM0xeJbPbtyoEPVbwSaMddKRuX4lX5YtMsvSAuQch6OiNPiNh6ijB # 6006f+Mhh2PHsuPmOydgA= # -----END SSH SIGNATURE----- # gpg verification failed. # Conflicts: # Cargo.toml
… clippy" This reverts commit d7d6d46.
…y clippy" This reverts commit 43a426e.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merge upstream
paradigmxyz/revm-inspectorsfrom v0.32.0 to v0.39.0, upgrading revm dependency from 31.0.0 to 38.0.0 for Mantle Elysium.What changed
revmdependency points tomantle-xyz/revmbranchmantle-elysium(revm 38.0.0)alloy-rpc-types-eth/alloy-rpc-types-traceupgraded from 1.x to 2.0DebugInspector, tracing improvements, bug fixes) includedConflict resolution
Only
Cargo.tomlconflicted — resolved by accepting all upstream changes and pointingrevmtomantle-xyz/revmbranchmantle-elysium.Mantle custom code
Zero. This fork has no Mantle-specific Rust logic — only the
revmdependency pointer differs from upstream.Follow-up
Once
mantle-xyz/revmPR paradigmxyz#26 is merged and tagged, updateCargo.toml:# branch = "mantle-elysium" → tag = "v107-mantle-elysium.1"Test plan
cargo checkpassescargo test— 14 unit tests + 28 integration tests all pass