Skip to content

feat(revm-inspectors): upgrade to upstream v0.39.0 for Mantle Elysium#9

Merged
asdv23 merged 45 commits into
mainfrom
mantle-elysium
May 11, 2026
Merged

feat(revm-inspectors): upgrade to upstream v0.39.0 for Mantle Elysium#9
asdv23 merged 45 commits into
mainfrom
mantle-elysium

Conversation

@asdv23
Copy link
Copy Markdown

@asdv23 asdv23 commented May 11, 2026

Merge upstream paradigmxyz/revm-inspectors from v0.32.0 to v0.39.0, upgrading revm dependency from 31.0.0 to 38.0.0 for Mantle Elysium.

What changed

  • Merged upstream v0.39.0 (7 minor versions: v0.32.0 → v0.39.0)
  • revm dependency points to mantle-xyz/revm branch mantle-elysium (revm 38.0.0)
  • alloy-rpc-types-eth / alloy-rpc-types-trace upgraded from 1.x to 2.0
  • All upstream source changes (new DebugInspector, tracing improvements, bug fixes) included

Conflict resolution

Only Cargo.toml conflicted — resolved by accepting all upstream changes and pointing revm to mantle-xyz/revm branch mantle-elysium.

Mantle custom code

Zero. This fork has no Mantle-specific Rust logic — only the revm dependency pointer differs from upstream.

Follow-up

Once mantle-xyz/revm PR paradigmxyz#26 is merged and tagged, update Cargo.toml:

# branch = "mantle-elysium"  →  tag = "v107-mantle-elysium.1"

Test plan

  • cargo check passes
  • cargo test — 14 unit tests + 28 integration tests all pass

rakita and others added 30 commits November 10, 2025 14:56
## 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
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`.
chihkaiyu and others added 15 commits April 9, 2026 06:36
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
@asdv23 asdv23 merged commit 91196e3 into main May 11, 2026
12 checks passed
@asdv23 asdv23 deleted the mantle-elysium branch May 11, 2026 07:49
@asdv23 asdv23 restored the mantle-elysium branch May 11, 2026 07:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.