case file · Solana · Token-2022

you can only buy
if you're infected.

$VIRUS enforces one rule on-chain: no buying unless you already hold it. Someone has to infect you first — send you a little. Then you can buy, and infect others. 🦠

Infected — $VIRUS
transmission

how the infection spreads

  1. 1
    🩸

    get infected

    A clean wallet can't buy. An existing holder has to send you $VIRUS first — that's your infection.

  2. 2
    🧪

    now you can buy

    The instant you hold a balance, the chain lets you buy more — on Jupiter, normally.

  3. 3
    🦠

    infect others

    Send $VIRUS to fresh wallets to infect them. Each new host can buy and spread it further.

documentation

transfer-hook docs

Exactly how the on-chain rule works — read it and verify it yourself.

01

the transfer hook

The infection rule is a Token-2022 transfer hook — a small Solana program that Token-2022 calls on every transfer of $VIRUS. It reads the transfer and can reject it. That's the whole enforcement mechanism: the token polices itself, so no interface, aggregator, or RPC can route around it.

program
2hdbA2wNSqCDg3RLSd4Gm1TTzbBAHCvhnrrKR8bqR7xk
framework
Anchor 0.31 · Rust
interface
spl-transfer-hook-interface 0.9
source
MIT · open & verifiable
02

the rule

On every transfer the hook looks at where the tokens are going and where they came from, and decides:

conditionresult
recipient is whitelistedallow
destination is a pool vaultallow
source is a pool vaultinfected only
anything elseallow

The only gated case is a buy — tokens leaving a pool vault to a normal wallet. That wallet must have been already infected (held a balance before this transfer), or it reverts with NotInfected.

03

detecting a buy

A buy is simply a transfer whose source is owned by a pool-vault authority. Meteora's vaults are owned by known program addresses, baked in as constants, so the hook tells pool↔wallet flows from wallet↔wallet flows with no extra data:

DBC      pool authority  FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM
DAMM v2  pool authority  HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC
DAMM v1  pool authority  CuVzw6GRdU44uPaeoNiGBFe2BpfyeAMd5iwGKuwCYRkh

Source is one of these → tokens are leaving a pool → a buy. Destination is one of these → tokens are entering a pool → a sell (always allowed).

04

Execute logic

Token-2022 passes the post-transfer state, so the recipient's balance already includes the incoming amount. The balance before the transfer is therefore destination.amount − amount — if that's zero, they had nothing and aren't infected.

#[interface(spl_transfer_hook_interface::execute)]
pub fn transfer_hook(ctx, amount: u64) -> Result<()> {
    let dst = ctx.accounts.destination_token.owner;
    let src = ctx.accounts.source_token.owner;

    if config.whitelist.contains(&dst)  { return Ok(()); }  // patient zero
    if POOL_AUTHORITIES.contains(&dst)  { return Ok(()); }  // sell / migration

    if POOL_AUTHORITIES.contains(&src) {                    // a BUY…
        let prior = destination.amount.checked_sub(amount)?;
        require!(prior > 0, InfectionError::NotInfected);   // …infected only
        return Ok(());
    }
    Ok(())                                                  // peer transfer = spread
}
05

accounts & PDAs

Two PDAs per mint. The ExtraAccountMetaList tells Token-2022 which extra accounts to hand to Execute; the HookConfig holds the per-mint whitelist.

ExtraAccountMetaList   seeds = ["extra-account-metas", mint]
                       declares 1 extra account → the HookConfig PDA

HookConfig             seeds = ["config", mint]
  authority: Pubkey      // may edit the whitelist
  mint:      Pubkey
  whitelist: Vec<Pubkey> // exempt wallets (max 16), seeded with the creator

Execute receives the standard transfer-hook accounts, in order: source, mint, destination, owner, the meta-list, and the config (resolved from its seeds automatically).

06

instructions

initialize_extra_account_meta_list(creator)setup

Creates the mint's meta-list + config PDAs and whitelists the creator (patient zero). Once per mint.

add_to_whitelist(address)authority

Exempt another wallet so it can buy without being infected.

remove_from_whitelist(address)authority

Remove an exemption.

transfer_hook(amount)Token-2022

The Execute entrypoint enforcing the rule, called by Token-2022 on every transfer.

errors · NotInfected · AlreadyWhitelisted · WhitelistFull · Unauthorized · MathOverflow

07

properties

  • The rule is fixed in the program; only the per-mint whitelist is mutable, and only by its authority.
  • Selling is never blocked — a pool vault is always a valid destination.
  • Sell to zero and you're cured — you'd need to get infected again to buy.
  • Peer transfers are unrestricted, including to brand-new wallets — that's the infection vector.
  • The rule never lifts: $VIRUS stays on its bonding curve, so the hook is never revoked.
  • No frontend bypass — the check runs inside the Token-2022 transfer, so every wallet, swap and route obeys it.
08

verified on-chain

Tested end-to-end against the live program:

  • creator buys at zero balance (whitelisted)
  • fresh wallet buy → rejected (NotInfected)
  • holder sends it tokens → infected
  • now-infected wallet buys → allowed
  • it infects another wallet → that wallet can buy
  • never-infected wallet → rejected
questions

faq

You can only buy if you're already infected — i.e. you already hold some $VIRUS. So step one is to get infected: have an existing holder send you a little $VIRUS. The moment your wallet holds a balance, you can buy more — on Jupiter like any normal token.