fix: mark fee payer as signer in accounts list before hash computation#114
Merged
tracy-codes merged 1 commit intomainfrom Mar 2, 2026
Merged
Conversation
1fdcf96 to
9dc6587
Compare
…p256r1/k1 When the fee payer appears as a destination in inner instructions (e.g., transferring SOL back to the payer), it gets added to the accounts list with is_signer=false. However, the Solana runtime always marks the fee payer as is_signer=true on all AccountInfos. This caused a message hash mismatch (error 0xbd2 / PermissionDeniedSecp256r1InvalidMessageHash). The fix adds a payer field to InstructionDataOptions (which already flows from SwigOptions through the call chain) and uses it in the signV2Instruction methods of secp256r1.ts and secp256k1.ts to mark the payer as signer in the account metas after compactInstructions() returns, before the hash is computed. Fixes: #107
9dc6587 to
11b4abf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #107 — Transaction simulation fails with
custom program error: 0xbd2(PermissionDeniedSecp256r1InvalidMessageHash) when a secp256r1/secp256k1-signed Swig wallet transaction includes transfer instructions where one sends SOL back to the fee payer.Root Cause
The Solana runtime always marks the transaction fee payer as
is_signer=trueon allAccountInfos in every instruction. When the fee payer appears as a destination in inner instructions (e.g.,system_instruction::transferback to the payer),compactInstructions()adds it to the accounts list withis_signer=false(since it's just a recipient). The on-chain program then computes the message hash withis_signer=truefor the payer, but the client computed it withis_signer=false, causing the keccak256 hash to differ.Fix
The
payerpublic key already flows fromSwigOptionsthrough the call chain to the secp256r1/secp256k1 signing functions viaInstructionDataOptions. The fix:payeronInstructionDataOptionsso it can be accessed type-safely in the signing functionssecp256r1.tsandsecp256k1.tssignV2Instruction: aftercompactInstructions()returns and before hash computation, finds the payer in the account metas and marks it asisSigner=trueThis is the minimal-surface fix — only 3 source files changed, no modifications to
compactInstructions,swig/index.ts, token authority classes, or any other shared code.Usage
No code changes are required for users of
getSignInstructionContextorgetSignInstructions. Thepayeroption was already part ofSwigOptionsand already being passed through the call chain — this fix simply makes the signing functions aware of it.The following pattern that previously failed with
0xbd2now works correctly:For users of the lower-level
Secp256r1Instruction.signV2InstructionorSecp256k1Instruction.signV2Instructiondirectly, passpayerin theoptionsparameter:Files Changed
packages/lib/src/authority/instructions/interface.tspayertoInstructionDataOptionstypepackages/lib/src/authority/instructions/secp256r1.tscompactInstructions(), before hashpackages/lib/src/authority/instructions/secp256k1.tspackages/lib/tests/instructions/sign.test.tsTesting
signs multi-transfer with fee payer as destination (issue #107)for both secp256r1 and secp256k1 authorities