0.2.2 also supports a Token 2022 transfer fee on the base mint, and a Token 2022 transfer fee on the quote mint.
On a Token 2022 base mint, DBC initializes metadata.
transfer_fee_parameters adds TransferFeeConfig. The transfer-hook config path adds a transfer hook. Those are the base-mint extensions this program sets up.SPL Token vs Token 2022
Token 2022 Base Tokens
Pool initialization creates the Token 2022 mint and:- Sets decimals from the config.
- Initializes the metadata pointer and token metadata with name, symbol, and URI.
- Sets metadata update authority from
token_update_authority. - Mints the initial base supply into the pool vault.
- Sets or revokes mint authority from
token_update_authority. - Initializes
TransferFeeConfigwhen the config was created withtransfer_fee_parameters.
Base Mint Transfer Fee
A base-mint transfer fee is set on the config, not on each pool. Usecreate_config2 and pass transfer_fee_parameters. Pass none when the base mint should not have a transfer fee.
Passing parameters always initializes TransferFeeConfig on the base mint, including when transfer_fee_basis_points is 0. The base token type must be Token 2022. SPL Token configs are rejected with InvalidTokenType.
0 basis points with Immutable or RevokeZeroFee is rejected with InvalidTransferFeeParameters. A partner withheld authority or a partner migrated authority requires a non-default fee_claimer.
The config stores the choice in transfer_fee_flag (1 when a base transfer fee was configured), transfer_fee_basis_points, transfer_fee_withheld_authority, and migrated_transfer_fee_authority_option.
TypeScript:
transferFeeParameters on client.partner.createConfig2. The other arguments are the config account, feeClaimer, leftoverReceiver, quoteMint, payer, and the buildCurve* result.
Omit transferFeeParameters, or pass null, when there is no base transfer fee. createConfigAndPool and createConfigAndPoolWithFirstBuy call createConfig2. Omitting the field is the same as null.
Supported Quote Tokens
SPL Token quote mints are permissionless. A Token 2022 quote mint is permissionless when every extension is one of:MetadataPointerTokenMetadataTransferFeeConfig, only when the current fee is zero andtransfer_fee_config_authorityis revoked
older_transfer_fee is ignored. A transfer fee is zero when its basis points are 0 or its maximum fee is 0.
DBC stores the quote token program in quote_token_flag. Transfers use transfer_checked. Pass the token program that owns each mint.
Quote Mint Token Badges
A Token 2022 quote mint that is not permissionless needs aTokenBadge before a config or pool can use it. That includes mints with other extensions, such as Permanent Delegate, and mints whose TransferFeeConfig has a non-zero fee or a live transfer fee config authority. The badge is for the quote mint. DBC still creates the base mint.
Token teams must apply for that badge. This application is a public requirement, and every team follows the same process. The request identifies the quote mint and its extensions. It does not announce a launch. A Meteora operator with CreateTokenBadge permission creates the badge after review by calling create_token_badge. That instruction accepts a mint that is not already permissionless, including a non-zero transfer fee. A permissionless mint returns CannotCreateTokenBadgeOnSupportedMint.
Complete the Token 2022 Whitelist Request Form with the quote mint address, the extensions on that mint, a short project description, and contact details. On DBC, a non-zero transfer fee or a live transfer fee config authority still needs a badge. DLMM and DAMM v2 can accept TransferFeeConfig permissionlessly, so include that fee or authority in the form when the quote mint uses it. After you submit, open a ticket in the Meteora Discord so the team can review the request.
After the badge exists, pass it as remaining account index 0 on config and pool creation. Set tokenBadge and the SDK adds that account. deriveTokenBadgeAddress(quoteMint) returns the PDA ["token_badge", quote_mint]. client.state.getTokenBadge(quoteMint) reads the account.
Closing a badge blocks new configs and pools for that mint. Pools that already use the mint keep trading.
A DBC badge is not a DAMM v2 badge. DAMM v2 configs used by DBC migration have CreatePoolWithoutMintValidation, so a badged quote mint can still graduate.
The badge stores the mint address. It does not store the fee. migration_damm_v2 reads the quote mint’s fee for the current epoch.
At config creation, compounding mode checks that the sqrt price implied by the transfer-fee-excluded deposit amounts is within 1% of migration_sqrt_price. The check is abs(migration_sqrt_price - derived_sqrt_price) * 100 <= max(migration_sqrt_price, derived_sqrt_price). A miss returns InvalidCurve. Migration does not run that check again.
A higher quote fee at migration can deposit less liquidity, add the undeposited side to the protocol migration fee, and move the migration price outside that 1% band. If a scaled side rounds to zero, migration returns AmountIsZero.
A quote mint can also gain a TransferFeeConfig after the config exists, including through the mint close authority. migration_damm_v2 then takes the transfer-fee path and runs validate_transfer_fee_restrictions. A config that is not constant supply, has locked vesting, is not Customizable, or is not Compounding fails that check.
Quote Mint Transfer Fee
create_config and create_config_with_transfer_hook reject a quote mint with a non-zero transfer fee or a live transfer fee config authority, even when a badge is supplied. The error is InvalidQuoteMint. Use create_config2.
A missing badge for a mint that is not permissionless is also InvalidQuoteMint. InvalidTokenBadge is returned only when the supplied badge account does not match the quote mint.
The same quote mints are rejected on pool initialization for a legacy config (PoolConfig.version 0) and on every transfer-hook pool initialization. A badged quote mint can still be used with a legacy config when the fee is zero and the transfer fee config authority is revoked.
Config Restrictions
create_config2 applies extra checks when the config has a base transfer fee, or the quote mint has a non-zero transfer fee or a live transfer fee config authority:
Configs created by program
0.2.2 have version 1. version 0 is a legacy config. Legacy configs were not checked against these restrictions, so they stay off this path.
A Token 2022 config whose token_update_authority is PartnerUpdateAuthority or PartnerUpdateAndMintAuthority also needs a non-default fee_claimer. Token 2022 rejects the default pubkey as an authority.
A base transfer hook cannot be combined with a quote mint that has a non-zero transfer fee or a live transfer fee config authority. See DBC Transfer Hook Pools.
Swaps
The curve uses the amount the pool receives after the input mint’s transfer fee.minimum_amount_out is checked against the amount the user receives after the output mint’s transfer fee. maximum_amount_in is checked against the amount the user pays before the input mint’s transfer fee.
EvtSwap3 and EvtSwap3WithTransferHook report included_transfer_fee_amount_in and excluded_transfer_fee_amount_out.
client.pool.swapQuote and client.pool.swapQuote2 return includedTransferFeeAmountIn and excludedTransferFeeAmountOut.
For a Token 2022 quote mint, pass quoteMint and currentEpoch. Without them the SDK throws quoteMint and currentEpoch are required for a Token-2022 quote mint, use getSwapQuoteTransferFees. That helper loads the quote mint when quoteTokenFlag is Token 2022, the base mint when you pass baseMint, and the current epoch.
An existing-pool quote reads the base fee from transferFeeFlag and transferFeeBasisPoints unless you pass baseMint or baseTransferFeeBasisPoints. baseMint reads the mint account. The flag reads the fee stored on the config.
Migration And Leftover
Version1 configs that have a base transfer fee, or a quote mint with a non-zero transfer fee or a live transfer fee config authority, migrate on the transfer-fee path. The details are in DBC Migration and Liquidity.
migration_damm_v2 still rejects a non-zero quote transfer fee for a legacy config (QuoteMintHasNonZeroTransferFee).
withdraw_leftover is permissionless when the transfer fee on the leftover is zero. When that fee is non-zero, leftover_receiver must sign. See DBC Surplus and Leftover.
Token Authority
token_update_authority chooses who can update metadata, and, for transfer-hook configs only, who receives mint authority.
Fixed And Dynamic Supply
A transfer-fee config cannot use dynamic supply. It must be fixed supply with equal pre-migration and post-migration amounts, and it cannot use locked vesting.

