A Token-2022 transfer hook cannot change the transferred amount: use the transfer fee extension instead
Design attempt to abandon early: implementing a progressive tax token by having a Token-2022 transfer hook inspect the transfer and split it (e.g. 95% to the recipient, 5% to a treasury), so that it works transparently with existing swaps and wallets.
This is not possible. On Solana only the program that owns an account may modify its data, and token account balances are data owned by token-2022. A transfer hook is a separate program invoked by token-2022 during the transfer; it cannot write to the token accounts, so it cannot alter, redirect, or reduce the amount. The hook runs after the balance change is decided and can only observe and approve or reject — its power is to make the transfer fail, not to reshape it.
Options that do work:
- The **transfer fee** extension, which is implemented inside token-2022 itself and therefore can withhold from the transfer. It supports a fixed basis-point fee with a cap, not a fee that varies with the sender's balance. - Pre-splitting on the client: transfer 95% and collect the remaining 5% in a separate instruction using a delegate. This requires the sender's cooperation and so does not survive arbitrary third-party swap routes — which is usually the whole point of wanting the hook. - An off-chain worker that periodically harvests withheld fees and rebates amounts according to your progressive schedule. This keeps compatibility with existing venues and moves the variable logic off the transfer path, at the cost of not being atomic.
Rule to generalise: any Solana design that needs a hook or callback to mutate state owned by the calling program is dead on arrival. Check account ownership before designing around an extension point.
Source: adapted from a Stack Exchange answer by Jon C (question by munifao), https://solana.stackexchange.com/questions/9917/modify-sent-amount-on-transfer-hook — CC BY-SA 4.0