Skip to content

namay10/Whitelisted_vault_Transfer_hook

Repository files navigation

Week 1 Challenge — Transfer Hook Vault

A Solana program (Anchor) that implements a whitelist-gated vault using SPL Token-2022 and the transfer hook extension. Only whitelisted users can receive or send the vault’s token via the hook.


Challenge Summary

  • Goal: Build a vault that holds Token-2022 tokens and only allows transfers involving whitelisted users.
  • Mechanism: Use the Token-2022 transfer hook so that every transfer is validated by our program; the hook checks a per-user whitelist PDA before allowing the transfer.
  • Flow: Users are added to a whitelist → a Token-2022 mint is created with the transfer hook pointing to our program → an ExtraAccountMetaList PDA (per mint) is initialized with the whitelist and other accounts → a single vault PDA holds tokens; deposit (user → vault) and withdraw (vault → user) go through our program via CPI to Token-2022, which invokes the hook.


What We Implemented

On-chain (program)

  1. Whitelist

    • initialize_whitelist: create a PDA per user (seeds = [b"whitelist", user_key]).
    • add_to_whitelist / remove_from_whitelist: manage who is allowed to use the vault/hook.
  2. Token-2022 mint with transfer hook

    • init_mint_token (TokenFactory): create a mint with extensions::transfer_hook (authority = user, program_id = our program). Requires an existing whitelist PDA for the user and an ExtraAccountMetaList PDA (created later).
  3. ExtraAccountMetaList (per mint)

    • initialize_transfer_hook (InitializeExtraAccountMetaList): create PDA [b"extra-account-metas", mint] and write the list of extra accounts the hook needs (e.g. whitelist PDA via seeds). Token-2022 uses this when invoking the hook.
  4. Vault

    • initialize_vault: create vault PDA (seeds = [b"vault"]) and set mint + bump; vault ATA must already exist (created by client with Token-2022).
  5. Deposit & withdraw

    • deposit: user signs; CPI transfer_checked from user_ata → vault_ata (Token-2022 runs the transfer hook).
    • withdraw: vault PDA as signer via CPI; CPI transfer_checked from vault_ata → user_ata. Both use Token-2022 and the same hook.
  6. Transfer hook

    • transfer_hook: invoked by Token-2022 on every transfer of this mint. Validates that the source token owner has a whitelist PDA and that it matches the account list (e.g. whitelist from seeds [b"whitelist", owner.key()]). Rejects if not whitelisted.

Brief Explanation of the Solution

  • Single vault: One global vault PDA per program; vault ATA holds the Token-2022 tokens.
  • Whitelist: One whitelist PDA per user; the transfer hook only allows transfers if the source owner’s whitelist exists and is passed in the hook’s extra accounts.
  • Token-2022 transfer hook: The mint is created with transfer_hook::program_id = our_program. On any transfer, Token-2022 CPIs into our transfer_hook with the extra accounts from the ExtraAccountMetaList; we check the owner’s whitelist and allow or deny.
  • Deposit/withdraw: Implemented as CPIs to Token-2022’s transfer_checked (deposit: user → vault; withdraw: vault → user with vault PDA signer). The same hook runs on those transfers, so only whitelisted users can participate.

How to Build & Test

anchor build anchor test # runs: cargo test -- --nocapture

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors