Skip to content

Better MEV shield errors#23

Open
l0r1s wants to merge 6 commits into
polkadot-stable2506-2-otf-patchesfrom
polkadot-stable2506-2-otf-patches-better-errors-mev
Open

Better MEV shield errors#23
l0r1s wants to merge 6 commits into
polkadot-stable2506-2-otf-patchesfrom
polkadot-stable2506-2-otf-patches-better-errors-mev

Conversation

@l0r1s

@l0r1s l0r1s commented Apr 2, 2026

Copy link
Copy Markdown

Shield error propagation

When a shielded transaction fails (decryption failure, inner tx decode error, inner tx validation failure), the proposer now includes an error extrinsic in the block alongside the wrapper. This gives SDK and wallet developers on-chain feedback about what went wrong, instead of silently dropping the inner transaction.

What changed

  • New ShieldError type hierarchy with sub-enums: ParsingError, WrapperExtrinsicError, DecryptionError, InnerExtrinsicError with human-readable error messages.
  • Runtime API versioned (#[api_version(2)]) so new nodes work with both old and new runtimes
  • New make_shield_error_extrinsic runtime API for the proposer to build error extrinsics
  • Proposer pushes report_shield_error into the block when the shielded transaction fails
  • ShieldedTransaction::parse returns Result with specific parsing errors instead of Option

On-chain outcomes for a shielded tx

Block contents Meaning
Wrapper + inner tx Success
Wrapper + ShieldedTxFailed event Inner failed — error says why
Nothing Wrapper expired or wrong public key (see below)

Errors that cannot be propagated on-chain

Two failure cases can't produce an on-chain error because the wrapper itself never gets included:

  1. Wrapper era expired — the wrapper's mortality period has passed, so the block builder rejects it. This is the expected timeout mechanism for key mismatch (era of 8 blocks).
  2. Invalid public key hash — the wrapper was encrypted with the wrong key, so the proposer skips it (it might be for a different block author). The tx stays in pool until its era expires.

If a user's submit_encrypted wrapper never appears on-chain, it's one of these two cases.

Upgrade path

  1. Deploy new node binary (rolling, no downtime) — falls back to v1 API on old runtime
  2. Deploy new runtime via setCode — node detects v2 and enables error reporting

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.

2 participants