Skip to content

test(evm-core): fix stale delegation.rs test module - #405

Open
manuelmauro wants to merge 1 commit into
rust-ethereum:v0.xfrom
moonbeam-foundation:fix/delegation-test-compile
Open

test(evm-core): fix stale delegation.rs test module#405
manuelmauro wants to merge 1 commit into
rust-ethereum:v0.xfrom
moonbeam-foundation:fix/delegation-test-compile

Conversation

@manuelmauro

Copy link
Copy Markdown
Contributor

Problem

evm-core's core/src/delegation.rs has a #[cfg(test)] mod tests that does not compile:

  • Delegation::try_from(&bytes) is called with bytes: Vec<u8> (so the argument is &Vec<u8>), but the impl is TryFrom<&[u8]> — trait selection does not deref-coerce &Vec<u8> to &[u8].
  • The assertions compare against Some(..) / None, but try_from returns Result<Delegation, DelegationError>.

The module has been broken since #367 first added the file — the test was written against an Option-returning draft of the Delegation API, while the merged impl returns Result via TryFrom.

Why CI didn't catch it

The root Cargo.toml is both a [package] (evm) and a [workspace], with no default-members. Per Cargo's rules, commands run from the root then default to the root package only — so cargo test (the workflow's only test step) never descends into evm-core, and cargo build compiles evm-core only as a dependency (a dependency's #[cfg(test)] modules are never built). cargo clippy --all lints lib/bin targets but not test targets.

It surfaces with:

cargo check --workspace --tests

Fix

  • Pass a &[u8] (bytes.as_slice()) so the TryFrom<&[u8]> impl is selected.
  • Compare against Ok(..) / Err(DelegationError::InvalidFormat).

Test-only change; no library code is touched.

Optional follow-up

Adding --workspace to the cargo test step in .github/workflows/rust.yml would catch this whole class of never-compiled test code across core/gasometer/runtime/fuzzer.

The `Delegation` API was refactored from an `Option`-returning conversion
to a `Result`-based `TryFrom<&[u8]>`, but the test module was never
updated to match:

- `try_from` was called with `&Vec<u8>`; the impl is `TryFrom<&[u8]>`,
  and trait selection does not deref-coerce `&Vec<u8>` to `&[u8]`. Pass
  `bytes.as_slice()` instead.
- assertions compared against `Some(..)`/`None`; `try_from` returns
  `Result`. Compare against `Ok(..)`/`Err(DelegationError::InvalidFormat)`.

The library itself compiles regardless, so `cargo check` without
`--tests` never caught this. Surfaced by `cargo check --workspace
--tests`.
manuelmauro added a commit to moonbeam-foundation/moonbeam that referenced this pull request May 18, 2026
- Add an evm row for the `delegation.rs` test-module fix
  (moonbeam-foundation/evm@a122857), upstreamed as rust-ethereum/evm#405.
- Correct the EIP-7939 row: PR #400 merged into `rust-ethereum/evm:v0.x`,
  so it is inherited from the upstream base, not a moonbeam cherry-pick
  (`Included` -> `Dropped`). Fix the matching "v1.0 only" claim in the
  Phase 1.2 plan.
manuelmauro added a commit to Moonsong-Labs/knowledge-work-plugins that referenced this pull request May 18, 2026
…k verification (#52)

## What

Adds a **"Verify the branch compiles"** step to the `qa-cherry-picks`
skill's `verify-cherry-picks.md`, requiring `cargo check --workspace
--tests` during fork-branch QA.

## Why

The verification flow confirmed cherry-picks via git but never checked
that the fork branch still built. Plain `cargo check --workspace` skips
`#[cfg(test)]` modules and integration tests, so a cherry-pick — or an
upstream refactor it lands on top of — can leave a test module that no
longer compiles while the check still reports success.

This was hit during the stable2603 cycle: evm's `evm-core`
`delegation.rs` test module had been broken since an `Option`→`Result`
API refactor, and a `--tests`-less check let it ride along undetected
from one stable branch to the next. (Since fixed upstream:
rust-ethereum/evm#405.)

---------

Co-authored-by: Rodrigo Quelhas <22591718+RomarQ@users.noreply.github.com>
manuelmauro added a commit to moonbeam-foundation/moonbeam that referenced this pull request Jul 9, 2026
* docs: add stable2603 cherry-pick tracker and upgrade plan

Draft tracker carries forward Included rows from stable2512 with TBD
commit hashes; rows whose upstream PR is expected to be in stable2603
are pre-marked Dropped pending merge-base verification. UPGRADE doc is
a temporary checklist covering forks, moonbeam Cargo.toml swap,
benchmarks, bridge regen, migrations, and verification.

* docs: record stable2603 Phase 0 findings

Resolved upstream bases for polkadot-sdk, evm, ethereum. Two new
blockers: polkadot-evm/frontier has not branched stable2603 yet, and
Moonsong-Labs/moonkit has no stable2603 base-bump PR. Also noted
frontier #1856 is now in upstream/master (tracker said "PR not
merged"); needs correction during verification.

* docs: own the stable2603 base-bump for frontier and moonkit

We will author the upstream base-bump PRs ourselves rather than wait
on polkadot-evm/frontier and Moonsong-Labs/moonkit. Adds Phase 1.4a
(moonkit) and Phase 1.5a (frontier) covering the upstream branches we
own, and notes the rebase plan once polkadot-evm cuts an official
frontier stable2603.

* docs: mark stable2603 Phase 1.1 polkadot-sdk done

Branch moonbeam-polkadot-stable2603 pushed with 4 cherry-picks on top
of polkadot-stable2603-1. Three previously-Included rows were verified
to be in stable2603 upstream and are now Dropped in the tracker:
charge_transaction_payment benchmark fix (#10444), storage benchmark
--keys-limit, and pallet-revive removal from pallet-xcm.

PrecompileWasmCmd needed an adaptation for stable2603's
BackendRuntimeCode::new(state, TryPendingCode) signature change.

* docs(cherry-picks): add Phase 0.5 audit step to stable2603 plan

The tracker `polkadot-sdk-stable2603.md` was assembled from the prior
cycle's tracker plus known deltas — it is not guaranteed to capture
every cherry-pick that has actually landed on each fork's
`moonbeam-polkadot-stable2512` branch.

Insert a pre-Phase-1 audit that enumerates every commit unique to
`origin/moonbeam-polkadot-stable2512` for each fork (polkadot-sdk,
frontier, evm, ethereum, moonkit) and reconciles it against the
tracker, so undocumented cherry-picks surface and get rows added
before re-application starts. Parallelizable via one sub-agent per
fork.

* docs(cherry-picks): record Phase 0.5 audit findings for stable2603

Run the Phase 0.5 audit against `origin/moonbeam-polkadot-stable2512`
on each fork using PR-number set-difference — raw SHA-diff is
misleading because both we and upstream apply the same backport PRs
under different SHAs.

Findings per fork:

* polkadot-sdk — 106 of 108 PR refs on our fork are also on
  upstream/stable2512 (they will inherit on rebase). Three new rows
  for the genuinely moonbeam-only commits: weight reclaim log
  improvements, an xcm-emulator BlockProducer trait override for
  Nimbus, and a bridges GRANDPA-justification experiment plus its
  revert.

* frontier — upstream/stable2512 has been frozen since 2026-01-13,
  so all 35 fork-only commits are moonbeam-authored. Six new rows
  (#1881 logs journal memory bound, #247 CI triggers, canonical
  hash mapping repair, Saturate U256, configurable tx gas-limit cap,
  MBF ethereum fork pin) and three tracker corrections: row #1820
  flipped from `Applied: No` to `Yes` (commit IS on the branch);
  rows previously listing PRs #1794 and #1787 corrected to #1824
  and #1862 (the PR numbers were typos for what is actually on the
  branch).

* evm — one moonbeam-authored commit (MBF ethereum fork dependency
  pin) added as a row.

* moonkit — one row for upstream PR #94 (relay offset dynamic);
  revisit during Phase 1.4 once the moonkit base-bump lands.

UPGRADE-stable2603.md gets the methodology note explaining why we
use PR-number set-difference, a per-fork results table, and a Phase
2 follow-up list for rows still TBD on Included vs Dropped.

* docs(cherry-picks): drop stale Backport PR rows from trackers

Sixteen rows in the stable2603 and stable2512 trackers carried no
commit SHA and described upstream PRs that landed on our fork via
merging upstream/stable2512, not via moonbeam cherry-picks. The
Phase 0.5 PR-number set-difference confirmed every one of them is
also on upstream/stable2512 — they do not belong in a cherry-pick
tracker.

stable2506 keeps its rows for the same PR numbers because there
every row carries a real moonbeam-foundation commit SHA and
`Cherry pick: Included` — those were genuine cherry-picks of that
release cycle, not upstream content carried over.

* docs(cherry-picks): refresh stable2603 SHAs after rebase + cherry-picks

Operational changes on the polkadot-sdk fork branch:

1. Rebase `moonbeam-polkadot-stable2603` from the
   `polkadot-stable2603-1` tag onto `upstream/stable2603` head
   (`afb51b7a8c6`), absorbing four upstream backports past the tag
   (#11964, #11856, #11987, #12017).

2. Cherry-pick the two Phase 0.5 finds that were missing from the
   branch:
   - `improve weight reclaim logs (call metadata, warn level)` →
     `161cd252773`.
   - `xcm-emulator: make slot/digest producer overridable for
     non-Aura parachains` → `beaf6b6c50a`. Trivial additive conflict
     with stable2603's `native_total_supply_tracker` macro arm,
     resolved by keeping both arms.

Doc updates:

- Refresh the six polkadot-sdk row commit hashes in
  `polkadot-sdk-stable2603.md` to match the post-rebase SHAs.
- Extend the Phase 1.1 checklist in `UPGRADE-stable2603.md` with the
  two new cherry-picks plus an explicit `Drop` for the bridges
  GRANDPA retry experiment that was reverted on stable2512.

* docs(cherry-picks): refresh polkadot-sdk SHAs after commit-message rewrite

Rewrote the commit messages of all six cherry-picks on
`moonbeam-foundation/polkadot-sdk:moonbeam-polkadot-stable2603` to
explain *why* each cherry-pick exists, not just *what* it does. In
particular, the auto-generated "Merge pull request #8" subject was
replaced with a real description of the pallet-parameters benchmark
fix. Each rewritten message now mirrors the context that lived only
in the moonbeam tracker, so the polkadot-sdk fork is self-explanatory
to anyone reading `git log` without the tracker open.

The rewrite changed all six SHAs. Update the tracker's commit links
and the Phase 1.1 checklist in `UPGRADE-stable2603.md` to point at
the new SHAs.

* docs(cherry-picks): drop ParachainTracingExecuteBlock row from stable2603

The row in `polkadot-sdk-stable2603.md` claimed `Applied: Yes` and
`Dropped but needs refactoring` against `paritytech/polkadot-sdk#9214`,
but that PR was never cherry-picked — the stable2506 tracker noted
"Not found on the branch — may not have been carried over". The
relevant code (`ParachainTracingExecuteBlock`) reaches stable2603 via
upstream's own backport of `#9871`, which superseded `#9214` (the
prdoc shipping at `prdoc/stable2509-2/pr_9871.prdoc` is upstream's
own metadata). It is pure upstream content, not a moonbeam
cherry-pick, so it does not belong in the active-cycle cherry-pick
tracker.

The moonbeam-side follow-up — wiring
`Some(Arc::new(ParachainTracingExecuteBlock::new(...)))` into the
parachain service — is already captured in the Phase 3 checklist of
UPGRADE-stable2603.md, so no information is lost.

The matching row in `polkadot-sdk-stable2512.md` is preserved for
historical reasons: it documents `moonbeam-foundation/polkadot-sdk#20`,
the attempted cherry-pick of `#9214` that was eventually superseded
by upstream's `#9871`. Same policy as the named cherry-pick rows in
`polkadot-sdk-stable2506.md`.

* docs(cherry-picks): mark Phase 1.3 ethereum done and fill in SHA

Created `moonbeam-polkadot-stable2603` on
`moonbeam-foundation/ethereum`. Since `rust-ethereum/ethereum`'s
master has not advanced past the merge-base with our
`moonbeam-polkadot-stable2512` branch (`d7bdf2888253a30f160d434688e378636e253870`,
which is also master's head), the new branch shares the same tip SHA
as stable2512 (`58a5a8a`) — the only commit ahead of upstream is the
unmerged rust-ethereum/ethereum#77 cherry-pick, which is preserved
as-is.

Tick Phase 1.3 boxes in UPGRADE-stable2603.md and replace the `TBD`
placeholder in the ethereum row of `polkadot-sdk-stable2603.md` with
the actual commit link.

* docs(cherry-picks): mark Phase 1.2 evm done and fill in EIP-7939 SHA

Created `moonbeam-polkadot-stable2603` on `moonbeam-foundation/evm`.
Upstream `rust-ethereum/evm` has moved to v1.0; the moonbeam fork
stays on the 0.43.x line and there is no new upstream commit to
pull. The new branch shares the same tip SHA as stable2512
(`bb9cdde4`) so both moonbeam-only commits — `a656db90` (the
EIP-7939 CLZ-opcode cherry-pick of rust-ethereum/evm#400, which was
merged upstream only on v1.0) and `bb9cdde4` (the MBF ethereum fork
dep pin discovered in Phase 0.5) — are inherited as-is.

Tick Phase 1.2 boxes in UPGRADE-stable2603.md and replace the `TBD`
placeholder in the EIP-7939 row of `polkadot-sdk-stable2603.md` with
the actual commit link.

* docs(cherry-picks): drop rust-ethereum/ethereum#75 row from stable2603 and stable2512

The "Refactor transaction signature validation" row referenced
rust-ethereum/ethereum#75, which is merged into upstream master at
`d7bdf28` — exactly the merge-base for our `moonbeam-polkadot-stable2603`
and `moonbeam-polkadot-stable2512` branches. The change is therefore
on our branches via upstream, not via cherry-pick.

The row carried no commit SHA and no moonbeam-side PR link, and the
`Applied` field disagreed across cycles (`No` in stable2603, `Yes` in
stable2512). It was not documenting a moonbeam cherry-pick action, so
it does not belong in either active or recent cherry-pick tracker —
same policy as the bulk of the upstream-only Backport PR rows we
removed earlier.

stable2506 keeps its version of the row because there it carries a
real `[moonbeam-foundation/ethereum@933ccae]` commit reference: that
documents the actual moonbeam-side work — a fork commit was
prepared, never applied (Applied: No, Cherry pick: Included), and
the PR was eventually merged upstream, making the cherry-pick moot.
That is the historically meaningful record; the 2512/2603 copies had
lost the SHA and only kept a now-redundant pointer to the upstream
PR.

* docs(cherry-picks): mark Phase 1.5 frontier done

Created `moonbeam-foundation/frontier:moonbeam-polkadot-stable2603`
on top of `upstream/stable2603` (`baf505d8f`) with 12 cherry-picks
and one manual `Cargo.toml` dep-redirect commit:

- Cherry-picks (#247 CI triggers, #1546 withdraw-ability, #1547
  ethereum execution info, #203 dispatch-error decoding,
  #1564+#224 squashed tx-size, #244 POV underestimations,
  #1568 lru_cache, #252 parity-db migration, frame-metadata,
  #254 validate tx size, Saturate U256, canonical hash mapping
  repair).
- One conflict on POV Underestimations (resolved by keeping
  stable2603's `match` block while adding `mut`); one trivial
  conflict on parity-db migration (kept upstream's deref form).
- Manual dep-redirect commit replaces the prior cycle's two
  cherry-picks (CI branch ref + MBF ethereum fork pin), pointing
  polkadot-sdk, ethereum, and evm at moonbeam-foundation forks on
  the `moonbeam-polkadot-stable2603` branch.

Phase 0.5 follow-ups resolved:
- 17 frontier PRs were inherited from `upstream/stable2603` (it
  was cut from the same master commit that absorbed our
  Phase 1.5a base-bump as PR#1892); their tracker rows are now
  confirmed `Dropped, PR Upstream Merged`.
- Three Phase 0.5–added rows flipped from TBD/TBD to Dropped:
  #1881 logs journal memory, #1856 latest-on-pruned, and the
  no-PR "Make tx gas limit cap configurable" (upstreamed as
  `b2088f29b`).

Side effect: `moonbeam-foundation/evm:moonbeam-polkadot-stable2603`
bumped to `7dd6ecc6` so its `ethereum` dep points at the stable2603
branch (was stable2512). Without this, cargo pulls in two distinct
versions of the `ethereum` crate when frontier consumes both.

Phase 1.5a is also marked complete because upstream merged our DIY
base-bump as polkadot-evm/frontier#1892 and cut `stable2603` from
the resulting master commit; our local `mb/polkadot-sdk-stable2603`
branch was redundant and has been dropped.

`cargo check --workspace` on the new frontier branch is clean (one
harmless unused-const warning from the dispatch-error cherry-pick).

* docs(cherry-picks): record evm delegation test-fix, correct EIP-7939 row

- Add an evm row for the `delegation.rs` test-module fix
  (moonbeam-foundation/evm@a122857), upstreamed as rust-ethereum/evm#405.
- Correct the EIP-7939 row: PR #400 merged into `rust-ethereum/evm:v0.x`,
  so it is inherited from the upstream base, not a moonbeam cherry-pick
  (`Included` -> `Dropped`). Fix the matching "v1.0 only" claim in the
  Phase 1.2 plan.

* docs(cherry-picks): mark Phase 1.4a moonkit PR open and awaiting merge

* docs(cherry-picks): cut interim moonkit stable2603 branch; resolve #94

Create moonbeam-polkadot-stable2603 off the open base-bump PR head
(mb/polkadot-sdk-stable2603, PR #95) to unblock moonbeam Phase 3 while
the upstream review is pending. PR #95 is linearly main + base-bump, so
the release branch already equals what it would be cut from the merge
commit; reconcile once #95 lands in main.

Verified the moonkit cherry-pick table: #92 (using_fake_author) and #94
(make relay offset dynamic) are both inherited from main, so no extra
cherry-picks are needed. Flip the #94 TBD row to Dropped/PR Merged and
add the #95 link to the base-bump row.

* chore(stable2603): swap fork branches, refresh lockfile, fix mechanical drift

Phase 3 of the polkadot-sdk stable2512 -> stable2603 upgrade.

- Cargo.toml: repoint all 180 fork deps to the moonbeam-polkadot-stable2603
  branches (polkadot-sdk, frontier, evm, ethereum, moonkit).
- Cargo.lock: re-resolved to stable2603. moonkit bumped to ba06fb0 (which
  redirects its polkadot-sdk/frontier deps to the moonbeam-foundation forks),
  unifying the tree on a single SDK source and eliminating a duplicate
  polkadot-sdk (canonical paritytech alongside the fork) that caused E0221/
  E0308 ambiguous-associated-type errors.
- Drop removed crate cumulus-client-consensus-proposer (upstream PR #9947 folded
  it into sp-consensus/sc-basic-authorship); it was an unused dependency.
- Bump num_enum to 0.7.6 to satisfy frontier fp-evm's new ^0.7.6 requirement.
- RuntimeDebug -> Debug across 51 sites / 14 files (upstream PR #10582 removed
  RuntimeDebug from sp_core/sp_runtime/frame_support; it is now plain Debug).
- pallet_evm Runner::call: add the new state_override argument (8 call sites).

Known remaining: erc20-xcm-bridge and moonbeam-foreign-assets need migrating to
the credit-based AssetsInHolding model (stable2603 XCM redesign); tracked
separately.

* wip(stable2603): stub design-blocked XCM holding methods to map scope

Scope-mapping checkpoint. stable2603 reworked AssetsInHolding to hold
fungible::Credit imbalances instead of Asset descriptors; the WeightTrader,
TransactAsset and FeeManager trait surfaces moved with it.

Mechanical fixes applied:
- TransactAsset::internal_transfer_asset now returns Result<Asset> (was
  Result<AssetsInHolding>); drop the .into().
- FeeManager::handle_fee now takes AssetsInHolding (was Assets).

todo!()-stubbed pending the real credit-based migration (tracked):
- erc20-xcm-bridge / moonbeam-foreign-assets: deposit_asset, withdraw_asset.
- xcm-weight-trader: buy_weight, refund_weight, and the Drop fee re-deposit.

These stubs let the compile-fix loop proceed past the XCM pallets to reveal
the runtime-layer drift. DO NOT SHIP without completing the migration.

* fix(stable2603): runtime API, weight, and XCM-config drift

Runtime-integration fixes that get all three runtimes compiling.

B — signature drift in the shared runtime macros (runtime/common):
- pallet_evm Runner::call gained a state_override (Geth-style) argument; thread
  it through apis.rs (API call + tracing call) and impl_xcm_evm_runner.rs.
- fp_rpc EthereumRuntimeRPCApi::call gained a state_override parameter.
- SessionKeys::generate_session_keys now takes an owner and returns
  OpaqueGeneratedSessionKeys (V2).

C — cumulus_pallet_parachain_system::WeightInfo gained three methods
  (block_weight_tx_extension_{max_weight,stays_fraction_of_core,full_core});
  add them (Weight::zero, matching upstream) to all three runtime weight files.

XCM Config — stable2603 merged asset claiming into the trap config: AssetClaims
  was removed from xcm_executor::Config and AssetTrap must now also implement
  ClaimAssets. Implement ClaimAssets for AssetTrapWrapper (delegates to the inner
  claimer; erc20 assets are filtered on drop so plain delegation is correct) and
  drop the now-invalid type AssetClaims from each runtime's xcm_config.

* fix(stable2603): node/service client-side drift (default-features green)

Gets moonbeam-service compiling; with this, cargo check --workspace passes
on default features.

- sc_service/cumulus BuildNetworkParams gained spawn_essential_handle.
- new_full_parts_record_import gained a pruning_filters argument.
- sc_client_api::CallExecutor::runtime_version gained a call_context param;
  Backend::set_block_data gained a register_as_leaf param (lazy-loading impls).
- moonkit: NimbusManualSealConsensusDataProvider dropped its _phantom field;
  MockValidationDataInherentDataProvider gained relay_parent_offset.
- Proof-recording refactor (upstream #9947): sp_consensus::Proposer lost its
  Proof associated type and Proposal lost its proof field. Rewrite the
  lazy-loading manual-seal (run_manual_seal/seal_block) to mirror upstream:
  drop the P generic, record the storage proof via a ProofRecorder wired into
  the proposal extensions, and drain it after proposing.

* feat(stable2603): migrate XCM impls to credit-based AssetsInHolding

Replaces the scope-mapping stubs with real implementations of the stable2603
credit-based holding model (AssetsInHolding now carries fungible::Credit
imbalances rather than Asset descriptors).

erc20 tokens are EVM-side balances, not a Substrate fungible, so they have no
real Credit. Introduce a notional (amount-only) ImbalanceAccounting credit
(mirroring the executor's MockCredit) to represent erc20 amounts in holding;
the real token movement still happens via EVM calls.

- erc20-xcm-bridge & moonbeam-foreign-assets: real deposit_asset/withdraw_asset.
  withdraw returns AssetsInHolding::new_from_fungible_credit(id, NotionalImbalance);
  deposit iterates the holding's fungible assets (collected first so the holding
  can be returned unspent on error) and performs the EVM transfer/mint, or
  records a pending deposit when frozen.
- xcm-weight-trader: real buy_weight/refund_weight. The Trader now holds the
  withheld fee as an AssetsInHolding (was Option<Asset>): buy_weight try_take()s
  the fee from payment and subsumes it; refund_weight splits the refund back out;
  Drop deposits the remainder to the fees account via the new deposit_asset.

cargo check --workspace is green on default features.

* fix(stable2603): runtime-benchmarks drift + weight-reclaim fork fix

- Cargo.lock: bump moonbeam-foundation/polkadot-sdk to ddba2453, which adds the
  missing GetCallMetadata bound to the cumulus-pallet-weight-reclaim benchmark
  (the weight-reclaim logging cherry-pick changed the TransactionExtension impl
  bound but not the benchmark where-clause, breaking runtime-benchmarks builds).
- apis.rs: pallet_transaction_payment::benchmarking is now private; reference the
  benchmark via pallet_transaction_payment::Pallet and the re-exported
  BenchmarkConfig.
- apis.rs: XcmBenchmarks worst_case_holding now returns AssetsInHolding. Build it
  with the canonical pallet_xcm_benchmarks::generate_holding_assets helper and
  register the held assets for the weight trader as before.

* test,docs(stable2603): update foreign-assets TransactAsset tests; record Phase 3

- moonbeam-foreign-assets tests: deposit_asset now takes an owned AssetsInHolding
  and returns Result<(), (AssetsInHolding, XcmError)>. Add a holding() helper that
  wraps a single asset in a notional-credit holding, and map the error tuple back
  to XcmError in the error-path assertions. 17/17 tests pass.
- UPGRADE-stable2603.md: mark Phase 3 done across the realistic feature matrix
  (default / runtime-benchmarks / try-runtime), document the drift handled, the
  XCM credit-holding migration, the fork-side fixes (moonkit ba06fb0, sdk
  ddba2453), and why blanket --all-features is invalid (disable-genesis-builder).

* style(stable2603): cargo fmt

* fix(stable2603): implement TransactAsset::mint_asset; fix Rust tests

Production fix:
- moonbeam-foreign-assets: implement the new TransactAsset::mint_asset. stable2603
  added mint_asset, which the XCM executor calls for ReserveAssetDeposited and
  ReceiveTeleportedAsset to put incoming assets into holding (the default is
  Unimplemented). Without it, every reserve transfer into the chain failed
  (assets never entered holding), which broke ~all XCM cross-chain tests. erc20
  has no real fungible::Credit, so mint_asset returns a notional-credit holding
  (mirroring withdraw_asset without the burn); the actual erc20 mint stays in
  deposit_asset. erc20-xcm-bridge keeps the Unimplemented default (local erc20s
  use the trace/deposit path, and the tuple transactor falls through on it).

Test fixes (TransactAsset/WeightTrader signature changes + AssetsInHolding):
- precompile/pallet mocks (xcm-utils, xcm-transactor, gmp, relay-encoder,
  xtokens, weight-trader): update deposit_asset/withdraw_asset/buy_weight to the
  new signatures; AssetsInHolding::default() -> ::new(); migrate the real
  checked_sub trader to try_take.
- drop the removed type AssetClaims from all xcm_mock/test runtime configs.
- xcm-weight-trader tests: add a notional test credit + holding() builders, map
  the (AssetsInHolding, XcmError) error tuple for assertions.
- runtime_apis tests (x3): pass the new state_override arg to EthereumRPCApi::call.

cargo test --workspace --no-fail-fast is green (previously 81 XCM tests failed).

* chore(stable2603): regenerate TypeScript API types

Regenerate the polkadot.js typegen bindings (api-augment) for all three runtimes
from the stable2603 runtime metadata.

- New cumulus types: CumulusPalletParachainSystemBlockWeightBlockWeightMode,
  CumulusPalletParachainSystemPoVMessages, CumulusPalletXcmpQueueOutboundChannelFlags.
- New parachain-system storage (blockWeightMode, poVMessagesTracker, etc.).
- Drop the SessionKeys runtime-API V1 binding (the API moved to V2 with the
  owner/OpaqueGeneratedSessionKeys change; polkadot.js typegen only ships the V1
  definition).
- Various upstream doc-comment updates.

tsc typechecks clean for moonbase/moonbeam/moonriver.

* test(stable2603): update dev fixtures for relay + credit-model XCM events

dev_moonbase/moonbeam/moonriver TypeScript suites now pass (previously 4 unique
failing files).

- test-block-mocked-relay / test-precompile-relay-verifier: stable2603 routes the
  relay-parent offset through the cumulus mock's dedicated relay_parent_offset
  (async-backing descendants) instead of folding it into relay_offset, so the dev
  relayParentNumber is the un-shifted parent (0, 1) and latestRelayBlockNumber is 1.
  This matches the relay offset not being applied to relay_offset (reverted in
  production). Note: relay_parent_offset must stay = the runtime value in the dev
  service — zeroing it makes async-backing panic ("Relay slot to exist").

- test-transactional-outcomes: stable2603's credit-based asset model moves native
  value via Withdraw/Deposit events rather than minting (no balances.Minted), so the
  execution fee is now derived from the treasury Deposit. Behaviour is unchanged:
  the sovereign is debited the full DEPOSIT and Baltathar receives DEPOSIT minus the
  fee even though the erc20 leg of the multi-asset DepositAsset fails.

test-delegate-with-auto-compound7 passes unchanged once the runtime wasm is present;
its earlier ENOENT was a local debug-build artifact (compact.compressed.wasm is only
emitted by release builds), not a code/fixture regression.

* fix(stable2603): drop unused XcmResult import in moonbeam-foreign-assets

* fix(stable2603): migrate BlockLength off deprecated max_with_normal_ratio

CI builds with -D warnings, which promotes the stable2603 deprecation of
frame_system::limits::BlockLength::max_with_normal_ratio to a hard error.
The recommended BlockLength::builder().normal_ratio(..) helper is not yet
present in the pinned polkadot-sdk fork, so reproduce the same limits with
the builder + modify_max_length_for_class (Normal = ratio * max, other
classes = max). Behavior is unchanged.

* fix(stable2603): use ProposerFactory::new over deprecated with_proof_recording

stable2603 removed the proof-recording type marker from ProposerFactory;
with_proof_recording is now a deprecated shim that forwards to new(), so the
two are behaviorally identical (proof recording is handled at the propose
layer). CI builds with -D warnings, which turned the deprecation into a hard
error in moonbeam-service. Swap the 3 collator call sites to new().

* fix(stable2603): drop unused XcmResult import in xcm-transactor mock

* style(stable2603): cargo fmt xcm-transactor mock import

* docs(stable2603): resolve cherry-pick tracker inconsistencies

- evm 'Fix stale evm-core delegation.rs test module': set Applied=Yes to match
  Cherry pick=Included and the listed commit a122857 (the fix is in the fork).
- Phase 6 checklist: replace 'cargo check --workspace --all-features' (which the
  Phase 3 note flags as invalid for moonbeam) with the realistic feature matrix
  (default / runtime-benchmarks / try-runtime).

* refactor(stable2603): import Encode from parity_scale_codec in manual_sealing

Avoid the brittle frame_benchmarking::__private::codec re-export; parity-scale-codec
is already a direct dependency of node/service.

* fix(stable2603): make deposit_asset atomic over the whole holding

The stable2603 TransactAsset signature change widened deposit_asset's input
from a single `&Asset` to a multi-asset `AssetsInHolding` and added the
`(unspent_assets, error)` contract. The rewritten loops mutated state per asset
but returned the full original `what` on a later-asset failure, so an
already-credited asset could be reported as unspent. The executor only ever
calls deposit_asset per single asset (deposit_assets_with_retry +
transactional_process), so this isn't reachable today, but the loops accept a
batch and were only correct for one.

Wrap each per-asset loop in a single with_storage_layer so any failure rolls
back the mints/pending-writes/transfers already applied, making the unspent
contract honest for any batch size. XcmError isn't From<DispatchError>, so the
real error is carried out via `captured` and a dummy DispatchError triggers the
rollback. Success and single-asset paths are unchanged (pallet tests pass).

* refactor(stable2603): align deposit_asset with SDK reference adapters

Replace the self-contained per-asset storage-layer loop with the pattern the
SDK's own TransactAsset adapters (e.g. fungibles_adapter) use: assert the
single-asset invariant with defensive_assert!(what.len() == 1) and process that
one asset, relying on the runtime's TransactionalProcessor for cross-asset
rollback. All three runtimes configure FrameTransactionalProcessor, which wraps
the whole DepositAsset instruction in a frame transactional layer, and the
executor only ever deposits one fungible per call (deposit_assets_with_retry),
so the previous custom with_storage_layer was redundant and non-idiomatic.

Net change vs master is now just the forced signature update (&Asset ->
AssetsInHolding, (unspent, error) return) plus the single-asset extraction and
defensive assert. Pallet tests pass (erc20 9/9, foreign-assets 17/17).

* style(stable2603): cargo fmt deposit_asset and manual_sealing import order

* docs(stable2603): align release date and mark TS-fixture status done

Resolves two CodeRabbit notes on UPGRADE-stable2603.md:
- use 2026-05-01 for polkadot-stable2603-1 consistently (was 2026-05-04
  on the Context line, 2026-05-01 on the resolved-bases row).
- the TS fixtures (typescript-api types + dev block/XCM/relay-verifier
  fixtures) are updated in this PR; only running them needs a built
  binary, which is already tracked under Phase 6.

* test(stable2603): assert single-asset invariant in xcm-weight-trader mock

MockAssetTransactor::deposit_asset previously read only the first
fungible and silently ignored any extras. Mirror the production
adapters (moonbeam-foreign-assets / erc20-xcm-bridge) with a
defensive_assert!(what.len() == 1) so the mock makes the same
single-asset invariant explicit. Addresses CodeRabbit review.

* chore(stable2603): apply missed cherry-picks and reconcile trackers

Source-of-truth audit against the moonbeam-polkadot-stable2512 fork branches surfaced cherry-picks present on 2512 but missing from 2603. Apply them: frontier #1895 (index tx hashes when digest/storage block hashes disagree), and three polkadot-sdk node patches (DNS multiaddr filtering, txpool hard-timeout during block authorship, --force-empty-blocks emergency flag).

Bump Cargo.lock to the new frontier (ed750e05) and polkadot-sdk (11a87af6) fork tips; add futures-timer to sc-basic-authorship.

Reconcile the stable2512/stable2603 cherry-pick trackers: correct the effective-gas row (#224 -> upstream #1622), drop the #203 Upstream-PR column misuse, backfill the inherited #1882 row, and document the three applied polkadot-sdk cherry-picks on both cycles.

* style(stable2603): pass Default::default() for pruning_filters

Mirror the upstream parachain node references (parachain template,
polkadot-omni-node, cumulus-test-service), which all pass
Default::default() for the new new_full_parts_record_import
pruning_filters arg. Functionally identical to Vec::new() (empty Vec);
no custom block-retention rules, default pruning preserved.

* docs: clarify stable2603 cherry-pick tracker preface

* chore: update copyright on notional xcm helpers

* refactor: consolidate NotionalImbalance into xcm-primitives

The NotionalImbalance fungible imbalance was duplicated verbatim in both
pallet-erc20-xcm-bridge and pallet-moonbeam-foreign-assets. Move it into
the shared xcm-primitives crate and have both pallets import it from there,
generalizing the doc comment from erc20-specific to any externally-accounted
asset.

* style: fix indentation of state_override parameter in apis.rs

* refactor(stable2603): reuse NotionalImbalance in xcm-weight-trader tests

Drop the hand-rolled TestCredit and its three imbalance trait impls in
favor of the production NotionalImbalance type from xcm-primitives, which
is byte-for-byte identical. The test crate already depends on
xcm-primitives, so no manifest change is needed. This removes a third
copy of the notional-credit shim and exercises the same type that
mint_asset uses in production, while still avoiding a dependency on the
SDK's internal test_helpers::MockCredit.

* docs(stable2603): clarify transactional-outcomes test comments

The failure-path XCM test had misleading comments: the "this will fail"
note sat on the notional erc20 WithdrawAsset (which never fails) instead
of the DepositAsset, and the summary claimed the native deposit succeeds
while the erc20 leg fails. In fact the multi-asset DepositAsset fails
atomically and Baltathar is funded via the SetErrorHandler.

Rewrite the comments to describe the real mechanism, add a scenario
header pointing to the happy-path mirror, and rename T01 to state intent.

* chore(stable2603): re-pin moonkit to rebased branch head

moonkit PR #95 (polkadot-sdk stable2603 base bump) merged into main; the
moonbeam-polkadot-stable2603 branch was rebased onto main and is now
main + the dep-redirect commit. Re-pin Cargo.lock ba06fb0 -> 9d71129
(content-identical tree, branch ref unchanged).

* docs(cherry-picks): drop moonkit base-bump rows

The polkadot-sdk base bump is the rebase-onto-upstream act, not a
cherry-pick, and it is not tracked for the other forks (polkadot-sdk,
frontier, evm, ethereum). Remove the moonkit base-bump rows from the
stable2603 (#95) and stable2512 (#89) trackers for consistency.

* docs(cherry-picks): mark moonkit reconciliation complete after #95 merge

moonkit #95 merged to main 2026-06-18 (squash 4088d76); the
moonbeam-polkadot-stable2603 release branch was rebased onto main and
moonbeam re-pinned to it. Tick Phase 1.4/1.4a, resolve the moonkit
risk, and refresh the stale 'awaiting merge' / 'reconcile when' notes.

* docs(cherry-picks): finalize Phase 2 verification

Verified frontier + polkadot-sdk cherry-picks against upstream/stable2603
via parallel sub-agents.

- frontier: all 13 Included SHAs confirmed present + moonbeam-only; all 18
  Dropped/PR-Upstream-Merged 'Verify' rows confirmed in upstream/stable2603;
  **Verify** flags replaced with confirmation notes.
- polkadot-sdk: all 9 Included SHAs confirmed; added the missing ddba2453 row
  (completes the weight-reclaim-logs cherry-pick b0b4fd52a9e by adding the
  GetCallMetadata bound to the benchmark where-clause).
- Fixed frontier #1856 note: cited 54396433 (the stable2512 cherry-pick) instead
  of the upstream/stable2603 commit 46cf7a43e.
- Ticked Phase 0.5 deferrals and Phase 2 checkboxes in the upgrade plan; header
  updated to reflect verification complete.

* docs(cherry-picks): drop spec_version bump from Phase 4

The runtime spec_version bump is a separate release step, not part of the
polkadot-sdk upgrade process. Remove it from the Phase 4 checklist and retitle
the phase (Runtime, weights, migrations).

* docs(cherry-picks): record Phase 6 verification results

Local verification after the moonkit re-pin (2026-06-18):
- cargo check matrix (default / runtime-benchmarks / try-runtime): all clean.
- cargo test --workspace --no-fail-fast: 1347 passed / 0 failed across 134 suites
  (incl. moonbase/moonbeam/moonriver integration_test + xcm_tests).
- TS dev fixtures touched by the upgrade (D010105, D010701, D022749): pass.
- PrecompileWasmCmd subcommand present in the built binary.
Smoke (live endpoints) and full zombienet XCM are flagged CI-only.

* docs(cherry-picks): reconcile upgrade plan with completed phases

Remove now-stale claims after Phases 1-3 and Phase 6 completed:
- Context: starting pin migrated (Phase 3); moonkit #95 merged; all five forks
  now have a moonbeam-polkadot-stable2603 branch.
- Phase 3: drop the 'TS fixtures pending' qualifier; fixtures ran in Phase 6.
- Risks: verification-cost item resolved by Phase 2.

* docs(cherry-picks): record Phase 4 weights + migrations analysis

Weights: only cumulus_pallet_parachain_system gained 3 WeightInfo methods,
added as Weight::zero() stubs; their sole consumer (DynamicMaxBlockWeight
tx-extension) is not wired into moonbeam, so the stubs are safe and no
benchmark run is required. No weight regressions.
Migrations: none added; migrations.rs unchanged, lists empty. SDK-pallet
storage-version validation deferred to the try-runtime step.

* docs(cherry-picks): record lazy-loading live-state check (moonbeam mainnet)

Lazy-loading is moonbeam-only, so it can't target moonbase. Ran it forking
moonbeam mainnet #16090736 with the new runtime override (4500 vs live 4303):
on_runtime_upgrade executed and 15 blocks imported cleanly, no panics. Caveat:
lazy state under-fetch treated many pallets as fresh-init ('new pallet detected')
rather than migrated, so per-pallet migrations weren't fully exercised. The
earlier try-runtime (moonbase) attempt was stopped mid-scrape. Authoritative
migration validation (full try_state) still open.

* docs(cherry-picks): close Phase 4 — defer full try_state to CI

create-snapshot vs moonbase was still enumerating keys after a full 10 min
(phase 1 of 2, never completed) — public-RPC scrape is impractical locally.
Decision: skip the local full try_state, defer to CI. Residual risk low
(weights clean, migration lists empty, lazy-loading upgrade green on live
mainnet state). Phase 4 closed locally.

* fix(runtime): wire cumulus-pallet-xcmp-queue v5->v6 storage migration

stable2603 bumps cumulus-pallet-xcmp-queue STORAGE_VERSION 5 -> 6
(OutboundChannelDetails in OutboundXcmpStatus gains a `flags` field).
MigrateV5ToV6 is a standalone VersionedMigration that the pallet does NOT
auto-run in its hooks; upstream parachain runtimes wire it explicitly.
Moonbeam's migration lists were empty, so on-chain XcmpQueue (v5) would not
migrate and OutboundXcmpStatus would fail to decode against the v6 layout,
breaking outbound XCMP.

Add MigrateV5ToV6 to UnreleasedSingleBlockMigrations (made Runtime-generic so
the single common definition covers moonbeam/moonriver/moonbase). Pulls
cumulus-pallet-xcmp-queue into runtime-common (std/runtime-benchmarks/try-runtime
wired). Self-guarding VersionedMigration<5,6>: no-ops if on-chain isn't v5.
Compiles across default / try-runtime / runtime-benchmarks.

* docs(cherry-picks): record xcmp-queue v6 migration (found via upstream audit + wired)

Upstream-repo STORAGE_VERSION audit found cumulus-pallet-xcmp-queue bumped
5->6 and its VersionedMigration was not wired in moonbeam. Recorded the finding
and the fix (commit 39d47d1) in Phase 4; corrected the stale 'migration
lists empty' conclusion.

* test(runtime): assert xcmp-queue v5->v6 migration is wired and runs

Guards against the migration silently being dropped from the runtime's
single-block migration set: sets XcmpQueue on-chain StorageVersion to 5,
runs the runtime's wired SingleBlockMigrations, and asserts it ends at 6.
Generated for all three runtimes via generate_common_xcm_tests!. Verified
passing on moonbase.

* docs(cherry-picks): record xcmp-queue v6 migration test (3 runtimes green)

* fix(runtime): repair XCM benchmarks for the stable2603 credit model

Under the stable2603 holding/credit model, assets used by the XCM benchmarks
must be mintable by the executor's AssetTransactor and present in the
worst-case holding. Three sites in the shared benchmark config still
referenced the relay token, which is neither registered nor in the generated
holding, so pallet_xcm_benchmarks::{fungible,generic} failed (AssetNotFound,
AssetUnderflow, claim_asset panic):

- worst_case_for_trader: relay token -> native `Here`, the abundant MockCredit
  asset in generate_holding_assets (priced by worst_case_holding).
- claimable_asset: relay token -> native `SelfReserve`, mintable by the real
  AssetTransactor that assets_to_holding uses.
- TrustedReserve: relay token from AssetHub -> native `SelfReserve` from origin
  `Here`, trusted via MultiNativeAsset.

Verified: both XCM benchmark pallets now run on moonbase, moonbeam, moonriver.

* chore(weights): benchmark block_weight_tx_extension for parachain-system

cumulus-pallet-parachain-system gained block_weight_tx_extension_{max_weight,
stays_fraction_of_core,full_core} in stable2603; they were committed as
Weight::zero() placeholders. Replace with benchmarked weights on moonbase,
moonbeam and moonriver.

Note: generated on non-reference hardware; to be regenerated on the reference
machine before release.

* fix(runtime): benchmark reserve_asset_deposited against a foreign asset

The previous fix used the native token for reserve_asset_deposited, whose mint
takes the cheaper Balances path and under-counts the realistic cost of a
reserve deposit (which always involves foreign assets). Register DOT
(RelayLocation) as a foreign asset in the TrustedReserve getter so the
instruction is measured through the EvmForeignAssets mint path, trusted from
Asset Hub via the RelayChainNativeAssetFromAssetHub reserve filter.

On moonbase this raises the measurement from a notional path (proof size 0,
0 reads) to real storage (proof size 3586, 1 read). Verified on moonbase,
moonbeam and moonriver.
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.

1 participant