Skip to content

Transfer hook support #64

@syaringan357

Description

@syaringan357

https://github.com/raydium-io/raydium-cp-swap/blob/master/programs/cp-swap/src/utils/token.rs

pub fn is_supported_mint(mint_account: &InterfaceAccount<Mint>) -> Result<bool> {
    let mint_info = mint_account.to_account_info();
    if *mint_info.owner == Token::id() {
        return Ok(true);
    }
    let mint_whitelist: HashSet<&str> = MINT_WHITELIST.into_iter().collect();
    if mint_whitelist.contains(mint_account.key().to_string().as_str()) {
        return Ok(true);
    }
    let mint_data = mint_info.try_borrow_data()?;
    let mint = StateWithExtensions::<spl_token_2022::state::Mint>::unpack(&mint_data)?;
    let extensions = mint.get_extension_types()?;
    for e in extensions {
        if e != ExtensionType::TransferFeeConfig
            && e != ExtensionType::MetadataPointer
            && e != ExtensionType::TokenMetadata
            && e != ExtensionType::InterestBearingConfig
            && e != ExtensionType::ScaledUiAmount
        {
            return Ok(false);
        }
    }
    Ok(true)
}

In this code, tokens using the Token2022 standard with transfer hooks will not be supported. However, if I wanted to develop a launch platform and restrict users from creating liquidity pools with the tokens before migration, I would use a transfer hook. Then, I would set the transfer hook to "none" during the migration. But this approach will not be supported on Raydium. But some other AMMs do it this way.

pub fn is_supported_mint(mint_account: &InterfaceAccount<Mint>) -> Result<bool> {
    let mint_info = mint_account.to_account_info();
    if *mint_info.owner == Token::id() {
        return Ok(true);
    }

    if spl_token_2022::native_mint::check_id(&mint_account.key()) {
        return Err(PoolError::UnsupportNativeMintToken2022.into());
    }

    let mint_data = mint_info.try_borrow_data()?;
    let mint = StateWithExtensions::<spl_token_2022::state::Mint>::unpack(&mint_data)?;
    let extensions = mint.get_extension_types()?;

    for e in extensions {
        match e {
            ExtensionType::TransferFeeConfig
            | ExtensionType::MetadataPointer
            | ExtensionType::TokenMetadata => {
                // permissionless supported
            }
            ExtensionType::TransferHook => {
                if let Ok(transfer_hook) =
                    mint.get_extension::<extension::transfer_hook::TransferHook>()
                {
                    let transfer_hook_program_id = Option::<Pubkey>::from(transfer_hook.program_id);
                    let transfer_hook_authority = Option::<Pubkey>::from(transfer_hook.authority);
                    if transfer_hook_program_id.is_some() || transfer_hook_authority.is_some() {
                        return Ok(false);
                    }
                } else {
                    return Ok(false);
                }
            }

            _ => return Ok(false),
        }
    }
    Ok(true)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions