As far as I understand from documentation all the Token-2022 extensions should be backwards compatible with normal transfers from spl-token standard. However when testing Transfer Hooks I was only able to create the token untransferable by common wallets (I tried Phantom, Solflare, Backpack) but the token was transferable by CLI.

When trying to transfer with wallet I get the error message Error processing Instruction 0: custom program error: 0x7dc8348c which translates to Incorrect account provided error. This does not happen if I create ATA account prior to transfer and initiate transfer with CLI.

My guess is that CLI transfer uses TransferChecked function and fetches / appends ExtraAccoountMetaList accounts automatically while wallets do not have this functionality, failing to append meta accounts resulting in wrong payload.

In my case I did not even need meta accounts at all but it looks like transaction needs at least some data to succeed, even if they are blank data.

I tried to ditch all the meta-related code from example program I deployed but had no luck with bypassing this functionality. Maybe I am just missing something?

1 Answer 1


You've noticed the problem perfectly -- the normal instruction creators will not check for a transfer hook and add the required accounts. The CLI does all of this for you through the spl-token-client crate in Rust.

In JS, you can use the createTransferCheckedWithTransferHookInstruction helper at https://github.com/solana-labs/solana-program-library/blob/5a1a2b2a8010b3e34fa6ef70b4ae15aebbd3ceb6/token/js/src/extensions/transferHook/instructions.ts#L317C23-L317C71

It takes all of the same parameters as normal transferChecked instruction:

let instruction = await createTransferCheckedWithTransferHookInstruction(

Eventually, all wallets and dapps need to switch to using this creator if they want to support mints with a transfer hook

  • Thank you for your answer.I noticed there is also createTransferCheckedWithFeeAndTransferHookInstruction in the ts file you provided. I needed both fees and transfer hooks in my token. I think it will be impossible for dapp to know which function to use even in the future. For now those tokens are unusable in a state like that - untransferrable, untradable. I hope they learn in Solana to do things properly in the future.
    – LubWn
    Commented Jan 14 at 13:32
  • You don't need to use transferCheckedWithFeeAndTransferHookInstruction if your token has a transfer fee. The WithFee part just allows you to specify the expected fee to be paid so you don't get rugged. A normal transferChecked works just fine otherwise.
    – Jon C
    Commented Jan 14 at 16:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.