Skip to content

fix(sdk-core): allow ERC-7984 PA rebuild without recipients (CHALO-1957) - #10063

Merged
0xPrabh merged 1 commit into
masterfrom
prabhsharansingh/chalo-1957-sdk-server-leg-pa-approve-recipients-deny
Oct 26, 2026
Merged

0xPrabh merged 1 commit into
masterfrom
prabhsharansingh/chalo-1957-sdk-server-leg-pa-approve-recipients-deny

Conversation

@0xPrabh

@0xPrabh 0xPrabh commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Part 2 of CHALO-1957, stacked on #10067 (the ETH-ecosystem verify change). Retarget to master once #10067 merges.

pendingApproval.approve() on a custodial multi-sig ERC-7984 leg PA merges the PA's stored info.transactionRequest.recipients into the prebuild params. The prebuildAndSignTransaction no-recipients guard then throws cannot provide recipients for transaction type wrap before any network call.

Fix

recreateAndSignTransaction strips recipients for the four ERC-7984 intent types (wrapApprove | wrap | unwrap | finalizeUnwrap) before prebuilding. The stored recipients are display-only for the approval UI. The /tx/build PA-rebuild carve-out re-derives the real inputs server-side from the pendingApprovalId that approve() already injects.

  • Other PA types forward their stored recipients unchanged.
  • The guard still rejects direct sendMany/prebuild calls with no pendingApprovalId.
  • iPendingApproval.ts: the buildParams.type union now lists the four intent types.

Tests

  • Approve-level tests for wrap and finalizeUnwrap PAs, plus a transfer-type regression that checks recipients are still forwarded.
  • Approve tests for all three legs (wrap, finalizeUnwrap, unwrap) through the real prebuildAndSignTransaction and verifyTransaction, with only the signing seams stubbed. This needs the verify path from fix(abstract-eth): verify ERC-7984 wrap/unwrap/finalizeUnwrap on multisig (CHALO-1957) #10067.
  • A negative case: a wrap rebuilt to mint to a non-base address is rejected.
  • A guard regression: prebuildAndSignTransaction with recipients and wrapApprove and no pendingApprovalId still throws.

Ticket: CHALO-1957

@0xPrabh
0xPrabh requested review from a team as code owners October 26, 2026 10:01
claude[bot]

This comment was marked as outdated.

@linear-code

linear-code Bot commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

CHALO-1957

@0xPrabh
0xPrabh force-pushed the prabhsharansingh/chalo-1957-sdk-server-leg-pa-approve-recipients-deny branch from c386135 to 4d1c4ba Compare October 26, 2026 10:16
@github-actions

This comment was marked as outdated.

@github-actions

This comment was marked as outdated.

Comment thread modules/sdk-core/src/bitgo/pendingApproval/pendingApproval.ts
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ Unit tests are failing on Node 26.x (Current release line, non-blocking). This is not an LTS version yet, so it does not block merge, but it signals an incompatibility to fix before Node 26.x becomes LTS.

View run

@0xPrabh
0xPrabh force-pushed the prabhsharansingh/chalo-1957-sdk-server-leg-pa-approve-recipients-deny branch from 4d1c4ba to b132bfe Compare October 26, 2026 10:38
@github-actions

This comment was marked as outdated.

@0xPrabh
0xPrabh force-pushed the prabhsharansingh/chalo-1957-sdk-server-leg-pa-approve-recipients-deny branch from b132bfe to e39b794 Compare October 26, 2026 10:48
@github-actions

This comment was marked as outdated.

Comment thread modules/abstract-eth/src/abstractEthLikeNewCoins.ts Outdated
Comment thread modules/abstract-eth/src/abstractEthLikeNewCoins.ts Outdated
@0xPrabh
0xPrabh force-pushed the prabhsharansingh/chalo-1957-sdk-server-leg-pa-approve-recipients-deny branch 3 times, most recently from 0184457 to 833ad17 Compare October 26, 2026 11:10
@0xPrabh

0xPrabh commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

@claude review

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Claude encountered an error —— View job


I'll analyze this and get back to you.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latest commit covers the three issues I raised earlier, and this pass found no new bugs. This code verifies multisig transactions before signing, so a human should still look at it.

What was reviewed:

  • The non-TSS verifyTransaction path for wrap, unwrap and finalizeUnwrap. These no longer need recipients, and the new PA tests run the real prebuildAndSignTransaction.
  • getErc7984WrappersForNetwork, which wrap, unwrap and finalizeUnwrap now all use to look up wrappers on this coin's network only.
  • assertPrebuildRecipientMirrorsSendMultiSig, which requires exactly one recipient whose address, amount and data all match. wrapApprove and the new intents both use it.
  • The recreateAndSignTransaction strip, which only applies to the four ERC-7984 types, so transfer PAs still forward their stored recipients.
Extended reasoning...

The change adds content-based verification of ERC-7984 wrap, unwrap and finalizeUnwrap transactions for onchain multisig ETH wallets in abstract-eth. It also stops PA rebuilds in sdk-core from forwarding stored recipients for those intent types. This is the check that runs before a user key signs a sendMultiSig operation hash, so mistakes here could approve the wrong transfers. The new commit plausibly addresses the earlier inline threads. Those threads were resolved only by the PR author, and this signing-critical logic (about 300 lines) warrants a human review rather than an automated approval.

pendingApproval.approve() on a custodial multi-sig ERC-7984 leg PA
(wrapApprove/wrap/unwrap user legs, wrap/finalizeUnwrap server-originated
legs) merges the PA's stored info.transactionRequest.recipients into the
prebuild params, tripping the prebuildAndSignTransaction no-recipients
guard before any network call.

recreateAndSignTransaction now strips recipients for the four ERC-7984
intent types before prebuilding: stored recipients are display-only for
the approval UI, and the /tx/build PA-rebuild carve-out (CHALO-1954)
re-derives the real intent inputs server-side from the pendingApprovalId
approve() injects. Other PA types forward recipients unchanged, and the
guard still rejects direct sendMany/prebuild calls without a
pendingApprovalId.

Stacked on the abstract-eth multisig verify change, which the approve
path needs once recipients are stripped.

Ticket: CHALO-1957
@0xPrabh
0xPrabh force-pushed the prabhsharansingh/chalo-1957-sdk-server-leg-pa-approve-recipients-deny branch from 833ad17 to d41e6e8 Compare October 26, 2026 13:57
@0xPrabh
0xPrabh changed the base branch from master to prabhsharansingh/chalo-1957-eth-erc7984-intent-verify October 26, 2026 13:57
@0xPrabh
0xPrabh changed the base branch from prabhsharansingh/chalo-1957-eth-erc7984-intent-verify to master October 26, 2026 16:12
@0xPrabh
0xPrabh merged commit 2a724e7 into master Oct 26, 2026
28 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