Skip to content

fix(sdk-coin-polyx): forward decoded specVersion to v8 transfer builders in tryGetV8Builder - #9328

Merged
nvrakesh06 merged 1 commit into
masterfrom
nvrakeshreddy/polyx-v8-token-withdrawal-routing
Jul 22, 2026
Merged

fix(sdk-coin-polyx): forward decoded specVersion to v8 transfer builders in tryGetV8Builder#9328
nvrakesh06 merged 1 commit into
masterfrom
nvrakeshreddy/polyx-v8-token-withdrawal-routing

Conversation

@nvrakesh06

Copy link
Copy Markdown
Contributor

Problem

tryGetV8Builder() in TransactionBuilderFactory hardcodes utils.getV8Material() (static specVersion: 8000000) on all returned v8 builders. The live Polymesh chain is at specVersion: 8000020. createBaseTxInfo() reads specVersion from this._material and encodes it in the signing payload's additional bytes — so any builder returned by tryGetV8Builder without a material override produces a rebuilt payload with wrong additional bytes, causing verifySignature to fail even though the TSS signature is cryptographically valid.

Root Cause

tryGetV8Builder decoded the transaction against v8 metadata correctly, but then created builders without forwarding the decoded specVersion — always defaulting to the static placeholder. The analogous fix for getV8BatchStakingBuilder was done in SI-1034 on the decode-success path in getBuilder(), but the four v8 transfer builders in tryGetV8Builder were missed.

Fix

Build v8MaterialWithDecodedSpec from the decoded transaction bytes:

const v8MaterialWithDecodedSpec = {
  ...v8Material,
  specVersion: decodedTxn.specVersion ?? v8Material.specVersion,
  txVersion: decodedTxn.transactionVersion ?? v8Material.txVersion,
} as Interface.Material;
  • decodedTxn.specVersion is populated for signing payloads (unsigned txs) — the production path used by getSignedTx/verifySignature
  • Falls back to v8Material.specVersion for signed extrinsics where decodeSignedTx doesn't return specVersion, so validateBaseFields doesn't throw

All four v8 transfer builders now receive .material(v8MaterialWithDecodedSpec):

  • V8TransferBuilder
  • V8HexTransferBuilder
  • V8TokenTransferBuilder
  • V8HexTokenTransferBuilder

Relationship to wallet-platform fix

A defensive wallet-platform fix (re-applying .material(material) after factory.from() in getSignedTx) is tracked in bitgo-microservices PR #61275. Both fixes arrive at the correct specVersion independently — having both is defense-in-depth with no conflict.

Tests

Added regression test in transactionBuilderFactory.ts that:

  1. Builds an unsigned v8 token transfer with live specVersion: 8000020
  2. Decodes it via TransactionBuilderFactory.from() with the same live material
  3. Asserts signablePayload byte-matches the original

All 252 existing unit tests pass.

References: SI-1034

@linear-code

linear-code Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

SI-1034

…ers in tryGetV8Builder

tryGetV8Builder() now builds v8MaterialWithDecodedSpec from the decoded
transaction bytes instead of using the static placeholder (specVersion
8000000). All four v8 transfer paths — V8TransferBuilder,
V8HexTransferBuilder, V8TokenTransferBuilder, V8HexTokenTransferBuilder
— receive .material(v8MaterialWithDecodedSpec) so createBaseTxInfo()
encodes the live chain specVersion (e.g. 8000020) in the rebuilt signing
payload. Without this fix verifySignature fails for any chain specVersion
above 8000000 because the additional bytes in the rebuilt payload differ
from the bytes the HSM signed. Adds a regression test that asserts
signablePayload round-trips correctly when the factory is given a live
material with specVersion 8000020.

specVersion is present in signing payloads (unsigned) but not in signed
extrinsics — falls back to v8Material.specVersion for signed txes so
validateBaseFields does not throw.

References: SI-1034

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@nvrakesh06
nvrakesh06 force-pushed the nvrakeshreddy/polyx-v8-token-withdrawal-routing branch from c563e44 to f2dc0ee Compare July 22, 2026 15:45
@nvrakesh06
nvrakesh06 marked this pull request as ready for review July 22, 2026 16:13
@nvrakesh06
nvrakesh06 requested a review from a team as a code owner July 22, 2026 16:13
@nvrakesh06
nvrakesh06 merged commit 6f9080b into master Jul 22, 2026
25 checks passed
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