diff --git a/tokens/transfer-tokens/native/program/src/instructions/transfer.rs b/tokens/transfer-tokens/native/program/src/instructions/transfer.rs index 9d265b941..7de3ca2c5 100644 --- a/tokens/transfer-tokens/native/program/src/instructions/transfer.rs +++ b/tokens/transfer-tokens/native/program/src/instructions/transfer.rs @@ -62,7 +62,11 @@ pub fn transfer_tokens(accounts: &[AccountInfo], args: TransferTokensArgs) -> Pr from_associated_token_account.key, to_associated_token_account.key, owner.key, - &[owner.key, recipient.key], + // Empty: `owner` is a plain wallet authority, not a multisig account. + // A non-empty list here marks `owner` as non-signer and instead + // requires each listed pubkey to co-sign as a multisig member — which + // wrongly forced the recipient to sign just to receive tokens. + &[], args.quantity, )?, &[ diff --git a/tokens/transfer-tokens/native/tests/test.ts b/tokens/transfer-tokens/native/tests/test.ts index de2704d44..5a2ae99ce 100644 --- a/tokens/transfer-tokens/native/tests/test.ts +++ b/tokens/transfer-tokens/native/tests/test.ts @@ -216,7 +216,7 @@ describe('Transferring Tokens', () => { await findAssociatedTokenAddress(mint, payer.address), await findAssociatedTokenAddress(mint, recipientWallet.address), payer, - recipientWallet, + recipientWallet.address, payer, programId, quantity, diff --git a/tokens/transfer-tokens/native/ts/instructions/transfer.ts b/tokens/transfer-tokens/native/ts/instructions/transfer.ts index 8b60694f3..56c8e1f79 100644 --- a/tokens/transfer-tokens/native/ts/instructions/transfer.ts +++ b/tokens/transfer-tokens/native/ts/instructions/transfer.ts @@ -21,7 +21,7 @@ export function createTransferTokensInstruction( fromAssociatedTokenAccount: Address, toAssociatedTokenAccount: Address, owner: TransactionSigner, - recipient: TransactionSigner, + recipient: Address, payer: TransactionSigner, programId: Address, quantity: bigint, @@ -33,7 +33,9 @@ export function createTransferTokensInstruction( { address: fromAssociatedTokenAccount, role: AccountRole.WRITABLE }, { address: toAssociatedTokenAccount, role: AccountRole.WRITABLE }, { address: owner.address, role: AccountRole.WRITABLE_SIGNER, signer: owner }, - { address: recipient.address, role: AccountRole.WRITABLE_SIGNER, signer: recipient }, + // Recipient just needs to be named, not to sign — receiving tokens + // must never require the recipient's approval. + { address: recipient, role: AccountRole.READONLY }, { address: payer.address, role: AccountRole.WRITABLE_SIGNER, signer: payer }, { address: SYSTEM_PROGRAM_ADDRESS, role: AccountRole.READONLY }, { address: TOKEN_PROGRAM_ADDRESS, role: AccountRole.READONLY },