Skip to content

fix(transaction-multi-payment): surface the EVM runner's own error from dispatch_permit - #1517

Open
iamyxsh wants to merge 2 commits into
masterfrom
fix/permit-runner-error-granularity
Open

fix(transaction-multi-payment): surface the EVM runner's own error from dispatch_permit#1517
iamyxsh wants to merge 2 commits into
masterfrom
fix/permit-runner-error-granularity

Conversation

@iamyxsh

@iamyxsh iamyxsh commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Description

dispatch_permit collapsed every Runner::call rejection into a single
EvmPermitRunnerError. A balance rejection, a gas limit above the per-transaction
cap and a gas limit above the block limit were all reported as the same error, so
an integrator could not tell them apart off-chain.

The runner's own error is now returned instead. It reaches callers through
ExtrinsicFailed, so no new event is needed — and on the signed path an event
would not survive anyway, since that path returns Err and everything written
inside it is rolled back.

EvmPermitRunnerError is left defined but unreachable. Removing it would shift
the indices of every later variant in the enum.

Note for reviewers

EvmPermitRunnerError was doing double duty. Besides being the reported error it
was a sentinel that two call sites compared against to decide whether the runner
had rejected the call before charging anything — which controls whether
on_dispatch_permit_error() fires and whether the signed path returns Err or
commits Ok(post_info). Returning a specific error without touching those sites
would have committed a permit nonce that was never consumed.

dispatch_permit has exactly three failure paths:

path nonce consumed error
Runner::call rejected no the runner's own error
nonce invariant violated yes EvmPermitNonceInvariantViolated
exit reason not Succeed yes EvmPermitCallExecutionError

The check is therefore inverted into a closed positive set,
evm_call_was_executed, and both call sites test the negation. A new failure
path that runs after the nonce is consumed must be added to that set
, otherwise
the autopause will fire on it and the signed path will return Err where it
should commit.

Motivation and Context

Integrators building on call permits currently have to guess why a permit was
rejected. The distinction matters operationally: an underfunded fee payer is
fixed by topping up an account, while a gas limit above the per-transaction cap
is fixed by changing the submitted transaction.

How Has This Been Tested?

  • cargo test -p pallet-transaction-multi-payment — 45 passed
  • cargo test -p runtime-integration-tests evm_permit — 44 passed
  • cargo clippy --all-targets and cargo fmt --check clean

Two existing tests now assert the specific error rather than the collapsed one:
a gas limit above the block limit reports GasLimitExceedsBlockLimit, and one
above the per-transaction cap reports TransactionGasLimitExceedsCap.

New test distinct_runner_rejections_should_reach_the_caller_as_distinct_errors
drives both rejections through the same code path and asserts each specific error
plus that the two remain distinguishable.

Checklist:

  • I have updated the documentation if necessary.
  • I have added tests to cover my changes, regression test if fixing an issue.
  • This is a breaking change.

…om dispatch_permit

Return the inner runner error instead of collapsing every rejection into EvmPermitRunnerError, and key the pre-charge check off the two post-charge errors.
@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown

Crate versions that have been updated:

  • runtime-integration-tests: v1.107.1 -> v1.107.2
  • pallet-transaction-multi-payment: v10.6.1 -> v10.7.0
  • hydradx-runtime: v439.0.0 -> v440.0.0

Runtime version has been increased.

@github-actions

Copy link
Copy Markdown

Quick benchmark at commit f6c734d has been executed successfully.
View results

@iamyxsh

iamyxsh commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

@mrq1911 @enthusiastmartin Review please

@iamyxsh
iamyxsh requested review from enthusiastmartin and mrq1911 and removed request for mrq1911 August 21, 2026 14:08
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