Files
pezkuwi-wallet-android/feature-account-impl
pezkuwichain 56c37615a0 fix(multisig): approve operations on Pezkuwi chains again by dropping the custom era extension (#16)
* diag: probe both era encodings when building the multisig weight-estimation extrinsic

Approving a multisig operation on Pezkuwi Asset Hub fails with "Failed to encode
extension CheckMortality". The on-device stack puts it in wrapInFakeExtrinsic,
reached only from estimateCallWeight — asMulti needs a max_weight, so a throwaway
signed extrinsic is built to measure the inner call. Plain transfers never reach
that path, which is why sending HEZ works while approving does not.

The same failure on Polkadot Asset Hub was fixed by gating the era encoding on
chain identity, and Pezkuwi Asset Hub satisfies that gate: its genesis hash matches
the constant, so PezkuwiCheckImmortal should already be in use. Reading the code
cannot say which side actually fails.

So build the extrinsic both ways and report each outcome with its full cause chain.
One reproduction then names the encoding the chain accepts, and the permanent fix
follows from that rather than from another guess.

Diagnostic only — the probe and the DIAG constant come out with the real fix.

* style: drop the blank line ktlint flags before the closing brace

* fix(multisig): approve operations on Pezkuwi chains again by dropping the custom era extension

Approving a multisig operation on Pezkuwi Asset Hub failed with "Failed to encode
extension CheckMortality", so no signatory could approve from the wallet — the
bridge treasury included. Initiating an operation worked, which made the break look
narrower than it was.

Only multisig reaches the failing code. asMulti needs a max_weight, so
estimateCallWeight builds a throwaway signed extrinsic to measure the inner call.
Plain transfers never build one, which is why sending HEZ kept working.

PezkuwiCheckImmortal was the cause, not the cure. It passes a raw
DictEnum.Entry("Immortal", null) as the era, and the SDK rejects it:

  EncodeDecodeException: Entry(name=Immortal, value=null) (Entry)
    is not a valid instance of Era (EraType)

The premise it was written on — that Pezkuwi's pezsp_runtime Era breaks the standard
codec — does not hold. Measured on device against Pezkuwi Asset Hub, the standard
CheckMortality(Era.Immortal) encodes without complaint, and ExtrinsicBuilderFactory
has been signing every ordinary transfer through it with a mortal era all along. The
era type resolves from metadata by index, so the renamed module path never mattered.

So the chain gate goes and both custom extensions go with it: PezkuwiCheckImmortal
had one caller, PezkuwiCheckMortality had none. One path for every chain.

Verified on device (Pezkuwi Asset Hub, versionCode 340): a build that tried both
encodings logged the custom one failing and the standard one succeeding, then
carried a real 3-of-5 approval through to MultisigExecuted with the inner call Ok
and 10 HEZ leaving the multisig.
2026-08-03 04:30:27 -07:00
..