-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transfer Hook: Off-chain and on-chain helpers are resolving keys incorrectly #6064
Comments
This PR adds a new offchain helper for adding the necessary account metas for an `ExecuteInstruction` to the SPL Transfer Hook interface, deprecating the old one. As described in #6064, the offchain helper in Token2022 was using the original offchain helper from the SPL Transfer Hook interface incorrectly when resolving extra account metas for a transfer. In order to provide a safer, more robust helper, this new function takes the instruction, fetch account data function, as well as the individual arguments for `instruction::execute(..)`. This will help to ensure Token2022 as well as anyone else using the helpers from the SPL Transfer Hook interface are properly resolving the necessary additional accounts. Note: Although deprecated, the original helper in the SPL Transfer Hook interface is not broken. It's just less safe to use than this new helper, since it can easily be misused.
This PR adds a new offchain helper for creating a `TransferChecked` instruction with the necessary accounts metas for a transfer hook `ExecuteInstruction` to Token2022, deprecating the old one. As described in #6064, the original offchain helper in Token2022 was being used incorrectly to resolve extra account metas. Rather than providing the SPL Transfer Hook interface helper with a valid `ExecuteInstruction`, the original Token2022 helper was actually providing it with a transfer instruction, causing erroneous account resolution. Taking advantage of the more secure SPL Transfer Hook interface offchain helper provided in #6099, this new offchain helper creates a `TransferChecked` instruction and calls `add_extra_account_metas_for_execute(..)`, providing the keys used to build the transfer instruction. Note: unlike the deprecated helper in #6099, the deprecated offchain helper in Token2022 *is* in fact inaccurately resolving account metas for certain use cases, thus it should be vigilantly avoided.
This PR continues the necessary repairs for addressing #6064 by refactoring the Token Client's `transfer(..)` function to use the new offchain transfer hook helpers. If transfer hook accounts are provided, in either case they're appended to the instruction like before. If no transfer hook accounts are provided: - If decimals are provided, Token2022's offchain helper `create_transfer_checked_instruction_with_extra_metas(..)` is used. - If decimals are not provided, SPL Transfer Hook interface's `add_extra_account_metas_for_execute(..)` is used. In either case where no transfer hook accounts are provided, the new, non-deprecated helpers are used.
As another step for solving #6064, the onchain helpers now need to be replaced. This PR makes that change in the SPL Transfer Hook interface. Specifically, this commit adds a new `add_extra_accounts_for_execute_cpi(..)` helper and deprecates the old one. Like its offchain counterpart, this new helper requires the arguments for `instruction::execute(..)` in order to validate that a proper `ExecuteInstruction` is being resolved, thus ensuring proper account resolution. This function, like its now-deprecated sibling, is designed specifically to add extra accounts to an `ExecuteInstruction` CPI instruction. It's expected that the instruction being provided is a CPI instruction for another program, and that program will CPI to the transfer hook program in question. Details about this have been added to the helper's documentation.
This is the final PR to round off the changes required to fix #6064. Previously, the offchain helpers for adding extra metas to instructions have been replaced with new ones in the SPL Transfer Hook interface and Token2022. This PR follows suit and adds a new helper to SPL Token JS. The new helper, `addExtraAccountMetasForExecute(..)`, mirrors the Rust helper in SPL Transfer Hook interface, requiring the parameters for an `ExecuteInstruction` to be passed into the function directly. This change also adds a public function for creating an `ExecuteInstruction`, in case developers wish to create such an instruction for directly sending instructions to their transfer hook program. These existing functions have been updated to use the new helper: - `createTransferCheckedWithTransferHookInstruction(..)` - `createTransferCheckedWithFeeAndTransferHookInstruction(..)` Closes #6064
Is there a timeline for publishing v0.3.12? Currently facing |
https://github.com/solana-labs/solana-program-library/releases/tag/token-js-v0.4.0 |
Love it sir 😎🫡 my tx is still failing with 0x7dc8348c but at least the new package is out :) Time to go debug more... |
Any luck solving : 0x7dc8348c? |
Problem
Token2022's off-chain and on-chain helpers for adding the necessary extra account metas for a transfer instruction that requires a transfer hook are missing a crucial step.
Note: This crucial step is missing only from the helpers, thus the on-chain program itself needs no change.
At the bottom of this issue is a test. In it, we're going to build instructions with extra account metas in three ways:
TransferChecked
instruction using the Token2022 off-chain helperExecute
instruction using the TLV Account Resolution library'sadd_to_instruction
Execute
CPI instruction using the TLV Account Resolution library'sadd_to_cpi_instruction
As you can probably infer, the issue is that we are adding the extra metas to a transfer instruction, rather than an
Execute
instruction.Consider the instruction keys for
TransferChecked
(simplified):Now consider the instruction keys as defined in the SPL Transfer Hook Interface's
Execute
instruction:As you can see,
Execute
requires the validation (extra metas) account, whileTransferChecked
does not.When extra account metas are hard-coded addresses, ie.
ExtraAccountMeta::new_with_pubkey(..)
, this is not an issue. However, once any extra account meta uses seed configurations that point to other account keys in the list, this difference in account keys bungles the whole resolution.The problem here is that, at the time of account resolution, the list of account keys for a transfer instruction and the list of account keys for an
Execute
instruction will yield entirely different resolutions.For example, if I have a PDA that's based off of the account at index 4, that will be two different accounts depending on the instruction. No bueno.
Consider the test.
Proposed Solution
We should be able to insert a few lines of code into the helpers that simply converts a transfer instruction into an
Execute
instruction before resolving the extra account metas.Since anyone storing extra account meta configs should be considering the list of accounts as it will arrive in their Transfer Hook program's
Execute
instruction, it makes sense to resolve forExecute
.After all, the main problem we have here is that we're asking TLV Account Resolution to resolve the extra account metas for an
Execute
instruction, but we're not actually feeding it a validExecute
instruction.The text was updated successfully, but these errors were encountered: