Documentation04 / 06

Integration

Program addresses, token identification, the transfer gate, PDAs, instruction and account layouts, and errors for HODL tokens on the bonding curve.

This page is the integration reference for HODL tokens during the bonding phase. After graduation a HODL token is a standard Token-2022 token trading on Meteora DAMM v2, and nothing on this page applies to it.

Programs

ProgramAddress
HODL launchpadHoDLBfygFHh76gjH7tnMxYqLt9VLCR3GgonXsodtfoPR
HODL transfer hookHoDLrkxn9ShXX6Zk7wLVWLtbiAt3RngibB3atKrkBGw9
Meteora Dynamic Bonding Curve (DBC)dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN
Meteora DAMM v2cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG
Token-2022 (base token)TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
SPL Token (quote token)TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Associated Token AccountATokenGPvbdGVxr1b1hFzfegA1Wzh8VbJEFe8oBa2Lz5
ConstantValue
Quote mintWrapped SOL, So11111111111111111111111111111111111111112
Base token supply1,000,000,000, 6 decimals
Fomo signerAgmLJBMDCqWynYnQiPCuj9ewsNNsBJXyzoUhD9LJzN51
Global config7kY1FqUgESxSwuQEN8BZE7qe4rUDXWEMMPXo1nrYcW7d
DBC pool authorityFhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM
DBC event authority8Ks12pbrD6PXxfty1hVQiE9sc289zgU1zHkvXhrSdriF
DAMM v2 migration configA8gMrEPJkacWkcb3DGwtJwTe16HktSEfvwtuDh2MCtck

Identifying a HODL token

HODL pools are DBC pools. Filtering by the DBC program ID alone matches every DBC pool. Use either method below.

MethodCondition
Creating transactionThe transaction's top-level instruction is launchpad create_launch, with the mint at account index 1 and trading_fees at index 4 equal to ["fees", mint] under the launchpad. A CPI into create_launch does not qualify.
Pool stateThe pool's DBC config has fee_claimer equal to ["fees", base_mint] under the launchpad.

Every launch creates its own DBC config. There is no shared HODL config to match against.

Transfer gate

While the hook is attached to the mint, Token-2022 calls the hook on every transfer of the base token. The hook reads the transaction through the instructions sysvar, and the transfer succeeds only if one of the following holds:

ConditionUsed by
The Fomo signer is a signer account of a top-level instruction in the transaction. A signature from a key that no top-level instruction lists is not visible to the hook.Every bonding-phase buy, sell and transfer.
The top-level instruction the transfer runs under belongs to the launchpad.The opening buy inside create_launch.

Any other transfer fails with hook error 6000 UnauthorizedTransfer. The launchpad condition applies only to the instruction it is: a launchpad instruction elsewhere in the transaction does not authorize a transfer under another instruction.

The swap that completes the curve revokes the transfer hook and clears its authority. From then on the token transfers without the hook.

PDAs

AccountProgramSeeds
Global configLaunchpad["global_config"]
Trading feesLaunchpad["fees", base_mint]
Extra account meta listHook["extra-account-metas", base_mint]
DBC poolDBC["pool", dbc_config, larger(base_mint, quote_mint), smaller(base_mint, quote_mint)]
DBC vaultDBC["token_vault", mint, pool]
DBC event authorityDBC["__event_authority"]
DAMM v2 poolDAMM v2["pool", damm_config, larger(base_mint, quote_mint), smaller(base_mint, quote_mint)]

larger and smaller compare the two mints as 32-byte arrays. The extra account meta list resolves one extra account, the instructions sysvar.

Instructions

Launchpad: create_launch

Creates the launch's DBC config, the Token-2022 mint with the hook attached, the DBC pool, the mint's extra account meta list and the trading_fees account, then executes the opening buy. Permissionless. No Fomo signature is required.

Discriminator ef df ff 86 27 79 7f 3e

#AccountWritableSignerAddress or derivation
0creatorYesYesFee payer and buyer
1base_mintYesYesNew keypair
2dbc_configYesYesNew keypair
3global_configNoNo["global_config"], launchpad
4trading_feesYesNo["fees", base_mint], launchpad
5pool_authorityNoNoDBC pool authority
6poolYesNoDBC pool PDA
7base_vaultYesNoDBC vault PDA for base_mint
8quote_vaultYesNoDBC vault PDA for the quote mint
9quote_mintNoNoWrapped SOL
10creator_quote_accountYesNoCreator's WSOL associated token account
11recipient_walletNoNoReceives the opening buy's tokens: the dev's Fomo wallet. Any address except the default pubkey; never signs
12recipient_base_accountYesNorecipient_wallet's Token-2022 associated token account for base_mint, created by the instruction
13extra_account_meta_listYesNo["extra-account-metas", base_mint], hook
14dbc_event_authorityNoNoDBC event authority
15dbc_programNoNoDBC
16hook_programNoNoHook
17instructions_sysvarNoNoSysvar1nstructions1111111111111111111111111
18token_base_programNoNoToken-2022
19token_quote_programNoNoSPL Token
20associated_token_programNoNoAssociated Token Account
21system_programNoNo11111111111111111111111111111111

Changed 2026-09-27. Account 11 was creator_base_account, the creator's own token account, which received the opening buy. The tokens now go to recipient_wallet (11) through its token account (12), and every account after them moved down by one. The creator still pays and spends its own WSOL. Until graduation only a Fomo wallet can sell, because every curve trade needs Fomo's signature; tokens sent to any other wallet cannot be sold before the token graduates.

Arguments: CreateLaunchParams

FieldTypeConstraint
namestring1 to 32 bytes
symbolstring1 to 10 bytes
uristringUp to 200 bytes
tieru80 to 4 (A to E)
trading_fee_bpsu16125 to 500, the fee for the life of the token, before and after graduation
recipientsVec<FeeRecipient>1 to 5, share_bps summing to 10000, no duplicates
buy_amountu64Opening buy in lamports of WSOL, at least global_config.minimum_opening_buy_lamports (500,000,000, 0.5 SOL, when the config is created)
minimum_amount_outu64Minimum base token received, in base units
TierGraduation raiseSupply to the migrated pool
0 (A)125 SOL20%
1 (B)250 SOL12%
2 (C)500 SOL7%
3 (D)1,000 SOL4%
4 (E)2,000 SOL2%

Requirements:

  • Fund and sync creator_quote_account with at least buy_amount WSOL before this instruction.
  • Set a compute unit limit of at least 1,400,000.
  • The creator pays about 0.0087 SOL of rent for the DBC config, which is not recoverable.
  • Send the launch as a v0 transaction over the address lookup table named launchLookupTable in the cluster's manifest (mainnet: GdMdweWebDuHJi4ipAYpUGJM14zr51LeyvyukmCv9LbB). It holds the eleven accounts common to every launch: global_config, pool_authority, quote_mint, dbc_event_authority, dbc_program, hook_program, instructions_sysvar, token_base_program, token_quote_program, associated_token_program, system_program. The largest launch the program accepts (a 32 character name, a 10 character symbol, a 200 character uri, a separate recipient_wallet) is 1,183 bytes this way.
  • This used to say a legacy transaction was enough for up to three or four fee recipients. That was wrong. It was counted with an empty uri. A real metadata URL and a separate recipient_wallet with a single recipient came to 1,241 bytes, over the 1,232 byte limit, and the site's launches failed until they moved to v0.

Launchpad: claim_fees

Claims the launch's accrued DBC trading fees into trading_fees and pays them out in the same transaction: HODL's share to the HODL fee wallet and the remainder to the launch's recipients by share_bps, the last recipient receiving any rounding remainder. Payouts are in SOL. Permissionless: any wallet may crank it and pays only the transaction fee, since the temporary token accounts are closed and their rent returned to it.

Discriminator 52 fb e9 9c 0c 34 b8 ca

#AccountWritableSignerAddress or derivation
0crankerYesYesAny wallet
1global_configNoNo["global_config"], launchpad
2trading_feesYesNo["fees", base_mint], launchpad
3dbc_configNoNoThe launch's DBC config
4pool_authorityNoNoDBC pool authority
5poolYesNoDBC pool PDA
6base_vaultYesNoDBC vault PDA for base_mint
7quote_vaultYesNoDBC vault PDA for the quote mint
8base_mintNoNoThe token
9quote_mintNoNoWrapped SOL
10trading_fees_quote_accountYesNoWSOL associated token account of trading_fees
11trading_fees_base_accountYesNoToken-2022 associated token account of trading_fees for base_mint
12token_base_programNoNoToken-2022
13token_quote_programNoNoSPL Token
14dbc_event_authorityNoNoDBC event authority
15dbc_programNoNoDBC
16associated_token_programNoNoAssociated Token Account
17system_programNoNo11111111111111111111111111111111

Remaining accounts, writable, in order:

#Account
0global_config.hodl_fee_wallet
1 to ntrading_fees.recipients[0..recipient_count].wallet, in stored order

No arguments. Claims apply to fees accrued on the bonding curve. Fees accrued after graduation belong to the DAMM v2 position and are claimed with claim_graduated_fees.

Launchpad: claim_graduated_fees

Claims a graduated launch's fees from its DAMM v2 position and pays them out with the same split as claim_fees. At migration DBC gives the whole position, permanently locked, to trading_fees; the lock prevents withdrawing liquidity, not claiming fees. The migrated pool collects fees in SOL only (DAMM v2 OnlyB, token B being the quote mint), so the claim is SOL and the base account receives nothing. HODL's share is computed from the pool's own protocol_fee_percent. Permissionless, with the temporary token accounts closed and their rent returned to the cranker.

Discriminator d9 fc e2 00 bb 0a ed a3

#AccountWritableSignerAddress or derivation
0crankerYesYesAny wallet
1global_configNoNo["global_config"], launchpad
2trading_feesYesNo["fees", base_mint], launchpad
3dbc_configNoNoThe launch's DBC config; its fee_claimer must be trading_fees
4damm_pool_authorityNoNo["pool_authority"], DAMM v2
5poolNoNoThe migrated DAMM v2 pool; token A base_mint, token B the quote mint
6positionYesNo["position", position_nft_mint], DAMM v2
7position_nft_accountNoNo["position_nft_account", position_nft_mint], DAMM v2, owned by trading_fees
8base_vaultYesNo["token_vault", base_mint, pool], DAMM v2
9quote_vaultYesNo["token_vault", quote_mint, pool], DAMM v2
10base_mintNoNoThe token
11quote_mintNoNoWrapped SOL
12trading_fees_quote_accountYesNoWSOL associated token account of trading_fees
13trading_fees_base_accountYesNoToken-2022 associated token account of trading_fees for base_mint
14token_base_programNoNoToken-2022
15token_quote_programNoNoSPL Token
16damm_event_authorityNoNo["__event_authority"], DAMM v2
17damm_programNoNoDAMM v2
18associated_token_programNoNoAssociated Token Account
19system_programNoNo11111111111111111111111111111111

Remaining accounts are the same as for claim_fees. No arguments. position_nft_mint is the first position NFT mint passed to migration_damm_v2.

DBC: swap2_with_transfer_hook (Fomo)

Buys and sells on the bonding curve are DBC swaps executed by Fomo. The swap itself carries no Fomo account. The Fomo signer authorizes the transfer by being a signer account of another top-level instruction in the same transaction, for example the funding account of the trader's idempotent associated token account creation (see Transfer gate).

Discriminator b7 5d 99 28 18 e6 c2 97

#AccountWritableSignerAddress or derivation
0pool_authorityNoNoDBC pool authority
1configNoNoThe launch's DBC config
2poolYesNoDBC pool PDA
3input_token_accountYesNoTrader's WSOL account (buy) or Token-2022 base account (sell)
4output_token_accountYesNoTrader's Token-2022 base account (buy) or WSOL account (sell)
5base_vaultYesNoDBC vault PDA for base_mint
6quote_vaultYesNoDBC vault PDA for the quote mint
7base_mintYesNoThe token; writable because the completing swap revokes the hook
8quote_mintNoNoWrapped SOL
9payerNoYesTrader
10token_base_programNoNoToken-2022
11token_quote_programNoNoSPL Token
12referral_token_accountYesNoOptional; pass the DBC program ID for none
13event_authorityNoNoDBC event authority
14programNoNoDBC

Remaining accounts, in order:

#AccountSigner
0Instructions sysvarNo
1["extra-account-metas", base_mint], hookNo
2Instructions sysvarNo
3Hook programNo

Arguments

FieldTypeValue
params.amount_0u64Exact in and partial fill: amount in. Exact out: amount out
params.amount_1u64Exact in and partial fill: minimum amount out. Exact out: maximum amount in
params.swap_modeu80 exact in, 1 partial fill, 2 exact out
transfer_hook_accounts_info.slicesVec<RemainingAccountsSlice>One slice: accounts_type TransferHookBase, length 3 (accounts 1 to 3 above)

DBC permits exactly one remaining account ahead of the declared slices, and it must be the instructions sysvar at index 0.

DBC: migration_damm_v2

Migrates a completed curve to DAMM v2. Permissionless and executed by Meteora's keeper on mainnet. Pass A8gMrEPJkacWkcb3DGwtJwTe16HktSEfvwtuDh2MCtck as remaining account 0. The migrated liquidity is permanently locked to the launch's trading_fees account. The migrated pool charges the launch's trading_fee_bps.

Launchpad: administrative

initialize_global_config and update_global_config are signed by the launchpad admin and are not used by integrations. update_global_config sets, among others, minimum_opening_buy_lamports, which must be above 0.

Hook

initialize_extra_account_meta_list is called by create_launch. execute is called by Token-2022 on each transfer. Neither is called directly.

Account layouts

All HODL accounts are Anchor accounts serialized with Borsh: an 8-byte discriminator followed by the fields in order, without padding.

GlobalConfig

Discriminator 95 08 9c ca a0 fc b0 d9, size 561 bytes, Borsh.

OffsetFieldTypeSize
0discriminator[u8; 8]8
8adminpubkey32
40hodl_fee_walletpubkey32
72holder_rewards_walletpubkey32
104tiers[LaunchTier; 5]445
549multiple_fee_recipients_enabledbool1
550holder_rewards_enabledbool1
551allow_stock_tokensbool1
552minimum_opening_buy_lamportsu648
560bumpu81

TradingFees

Discriminator 43 f2 ce 1c 9b 83 9f 8d, size 213 bytes, Borsh.

OffsetFieldTypeSize
0discriminator[u8; 8]8
8base_mintpubkey32
40recipients[FeeRecipient; 5]170
210recipient_countu81
211tieru81
212bumpu81

LaunchTier (89 bytes)

OffsetFieldTypeSize
0migration_quote_thresholdu648
8sqrt_start_priceu12816
24curve[CurvePoint; 2]64
88curve_point_countu81

CurvePoint (32 bytes)

OffsetFieldTypeSize
0sqrt_priceu12816
16liquidityu12816

FeeRecipient (34 bytes)

OffsetFieldTypeSize
0walletpubkey32
32share_bpsu162

Errors

Launchpad errors

CodeNameMessage
6000OpeningBuyBelowMinimumOpening buy is below the global config's minimum
6001InvalidMetadataToken name, symbol or uri is empty or too long
6002UnknownTierTier must be A, B, C, D or E
6003TierNotConfiguredThat tier has not been configured yet
6004FeeOutOfRangeTrading fee must be between 1.25% and 5%
6005NoRecipientsA launch must name at least one fee recipient
6006TooManyRecipientsA launch may name at most five fee recipients
6007RecipientSharesDoNotSumFee recipient shares must total 10000 basis points
6008RecipientShareIsZeroA fee recipient share must be greater than zero
6009InvalidRecipientA fee recipient wallet is the default pubkey
6010DuplicateRecipientThe same wallet is listed as a fee recipient twice
6011MultipleRecipientsDisabledNaming more than one fee recipient is not enabled
6012HolderRewardsDisabledNaming the holder rewards wallet is not enabled
6013NotAdminOnly the admin may change the global config
6014NothingToClaimThere are no fees to claim
6015ClaimPayoutAccountsMismatchPass the HODL fee wallet and then every fee recipient, in the order the launch stored them
6016FeeRateBelowHodlCutThis launch's fee rate is too low to cover HODL's cut
6017RecipientWalletIsDefaultThe recipient wallet is the default pubkey

Hook errors

CodeNameMessage
6000UnauthorizedTransferTransaction is not signed by an authorized operator
6001MalformedInstructionsSysvarInstructions sysvar data is malformed
6002MintHookMismatchMint does not have this program set as its transfer hook
6003NotToken2022MintMint is not a Token-2022 mint
6004MetaListTooSmallExisting extra-account-meta list is too small for the current layout

DBC errors specific to hooked pools

ErrorCause
InvalidRemainingAccountsLengthMore than one remaining account ahead of the declared slices, or the one present is not the instructions sysvar.
PoolTypeMismatchtransfer_hook_accounts_info was None on a hooked pool.
InsufficientLiquidityThe curve cannot fill the requested amount. Use partial fill.
PoolIsCompletedThe curve has graduated. Trade the DAMM v2 pool.