Skip to main content
PlatformConfig is the platform-level overlay that sits on top of GlobalConfig. Where GlobalConfig defines the protocol-wide rules (“trade fee is 1%, supply must be at least 10M, only this wallet can graduate”), PlatformConfig is what each launch platform — pump.fun, Raydium’s own UI, third-party launchpads — uses to add their fee, claim their slice of post-graduation LP, restrict which launch parameters their launches can pick, and surface their branding (name, website, image) on-chain.

What it is

A PlatformConfig account owns five cross-cutting concerns for a platform:
  1. Branding — name, website, image link, all stored inline so any explorer or aggregator can display the platform that launched a token.
  2. Platform fee — an extra trade fee (fee_rate) on top of the protocol’s trade_fee_rate. Accrues to the platform’s platform_fee_wallet. Capped at 500 bps (50000) on both the create and the update path, raised from 100 bps (10000) on 2026-08-26 — see Rate caps.
  3. LP migration split — three stored integers (platform_scale, creator_scale, burn_scale) that sum to 1_000_000. Before the 2026-08-17 upgrade, the creator scale produced a separate creator Fee Key. Migrations executed after the upgrade combine the first two into one platform-owned locked-LP share; the remainder is burned.
  4. Launch-parameter rules — an opt-in restriction (restrict_curve_param) that requires a launch to satisfy the PlatformCurveRule account of the GlobalConfig it selected. Rules support value bands, alternative tiers, and token-type gating; they live in their own accounts, not on PlatformConfig.
  5. Global-config allowlist — an opt-in restriction that requires a platform-created PlatformAllowConfig for the selected GlobalConfig.
PDA derivation:
(See create_platform_config in the source for the canonical seed list.)

Layout

The account is a fixed 944 bytes. It held a trailing Vec<PlatformCurveParam> until the 2026-08-31 release moved launch parameters into PlatformCurveRule accounts; restrict_curve_param, curve_rule_manager, and the 4 bytes that vec’s length prefix occupied all come out of the padding, so the byte count and every earlier field offset are unchanged. See the changelog entry for what decoders must change. platform_scale + creator_scale + burn_scale must equal 1_000_000. Before the 2026-08-17 upgrade, creator_scale was locked separately and its Fee Key went to the token creator. For migrations executed after the upgrade, it is added to platform_scale and its locked-LP rights go to the platform instead. Example outcomes under the updated logic:
  • (0, 100_000, 900_000) — 90% LP burned, 10% locked to the platform.
  • (50_000, 100_000, 850_000) — 85% burned, 15% locked to the platform.
  • (0, 0, 1_000_000) — full burn, no NFT mints. Strict “no insiders” launches.

Branding fields

name, web, and img are inline byte arrays padded with zeros up to their size constants. To read them as strings, slice up to the first \0:
The constants are deliberately generous (name: 64, web: 256, img: 256) so platforms can include enough metadata for explorers and aggregators without touching off-chain storage. Anything that exceeds these sizes reverts at CreatePlatformConfig with InvalidInput.

Fee mechanics

A swap on a curve bound to a PlatformConfig charges three layered fees:
  • trade_fee accrues to the protocol’s protocol_fee_owner (claimed via CollectFee).
  • platform_fee accrues to a per-platform vault (claimed via ClaimPlatformFee or ClaimPlatformFeeFromVault; see instructions).
  • creator_fee accrues to a per-creator vault keyed by the creator’s pubkey + quote mint (claimed via ClaimCreatorFee).

Rate caps

Both rates are denominated in 1/1_000_000, so 5000 is 50 bps and 50000 is 500 bps. The two enforcement points for fee_rate are separate require! calls in different files, so they carry different error codes, but they apply the same ceiling. A platform created at any permitted rate can be edited later, including through the AllInfo bulk variant that rewrites every field at once. Both fee_rate caps were 100 bps (10000) originally. The update cap moved to 25000 (250 bps) on 2026-01-27; on 2026-08-26 both moved to 50000 (500 bps) — see the changelog entry. GlobalConfig.max_share_fee_rate does not bound either rate. It bounds the per-transaction share_fee_rate argument that the four swap instructions take — the referral fee — and nothing else. See global-config.

Token-2022 transfer-fee authorities

transfer_fee_extension_auth names the platform key that ends up holding the base mint’s TransferFeeConfig authorities when a launch is created through InitializeWithToken2022 with a transfer fee attached. The extension carries two authorities, and they are handed over at different points in the launch lifecycle: Before 2026-08-27 the mint was created with the authority PDA on both authorities, and both moved to the platform at graduation. The program exposes no withdraw-withheld or harvest instruction, so fees withheld during the bonding-curve phase were unreachable until the launch graduated. Writing the withdraw side at mint creation makes them claimable from the first trade — see the changelog entry. Two consequences worth planning for:
  • Set the field before you launch, not after. A launch created while transfer_fee_extension_auth is Pubkey::default() puts the authority PDA on the withdraw side. Setting the field later still works — graduation finds the PDA in place and hands the authority over — but nothing can withdraw the withheld balance in the meantime.
  • Rotating the field mid-launch splits the two authorities. Change transfer_fee_extension_auth between a launch’s creation and its graduation and the mint’s withdraw-withheld authority stays with the key configured at creation (the PDA no longer holds it, so migration skips that handover) while the fee-config authority goes to the new key. Rotate between launches, or plan to reconcile the two keys yourself through Token-2022 directly.
A platform that leaves the field at Pubkey::default() for a launch’s whole life keeps both authorities on the authority PDA permanently: the fee rate can never be changed and the withheld balance can never be withdrawn. Only attach a transfer fee to a launch if the platform intends to hold these keys.

NFT migration split (CPMM-only)

When a launch graduates to CPMM, the migration instruction splits the LP tokens minted by CPMM::InitializeWithPermission two ways:
If lp_to_platform is non-zero, the LP-Lock program wraps it into one Fee Key NFT owned by platform_nft_wallet. This replaces the pre-upgrade behavior that created separate platform and creator Fee Keys. Fee Keys created by migrations completed before the upgrade remain unchanged. This LP-fee right is separate from CPMM creator fees controlled by platform_cp_creator. The burn slice is burned directly, so no account can withdraw it or claim the LP fees represented by that share. Existing launches with stored migrate_type = 0 can still use the legacy AMM v4 path. New initialization rejects that migrate type.

Launch-parameter rules

restrict_curve_param is the switch. At 0 the program does not read rules at all. At 1, every launch routed through this platform must satisfy the PlatformCurveRule account of the GlobalConfig it selected, and the launch builder must append that account to remaining_accounts.
A rule is a menu of permitted launch shapes: constraints inside one check group are ANDed, groups are ORed, and each constraint is a (field, op, value) triple supporting Eq, Gte, Lte, and Neq. That covers value bands, alternative tiers, graduation-valuation caps, migration floors, token-type gating, and time-boxed groups — the full model, the field table, and nine worked playbooks are in products/launchlab/curve-rules. Two things belong here rather than on that page:
  • curve_rule_manager is a delegation, not a transfer. Set it through UpdatePlatformConfig::CurveRuleManager and that wallet can create, update, remove, and close this platform’s rule accounts without the admin key. The platform admin keeps the same power in parallel, so rotating or clearing the field recovers control. Pubkey::default() means only the admin can manage rules. It cannot flip restrict_curve_param, which stays an admin-only call.
  • Rules are enforced on top of GlobalConfig, never instead of it. The rule check runs before the config’s own limits and can only narrow them.
This replaces the former curve_params: Vec<PlatformCurveParam> whitelist, which could only test exact equality, held at most 10 entries across all configs, and grew the PlatformConfig account itself. Platforms that used it were migrated by the protocol in a one-off pass; the legacy field, its two instructions, and MAX_CURVE_PARAMS are gone.

PlatformAllowConfig — restricting a platform

Each platform decides whether to restrict which GlobalConfig accounts its launches may use. Set restrict_global_config with UpdatePlatformConfig::RestrictGlobalConfig(0 | 1).
PDA seeds: [b"platform_allow_config", platform_config, global_config]. The platform admin creates or closes one account per allowed pair via CreatePlatformAllowConfig and ClosePlatformAllowConfig. When restriction is 1, initialization searches remaining_accounts for the expected PDA and rejects a missing account with NotEnoughRemainingAccounts. When restriction is 0, no allow account is required. The former protocol-admin-managed PlatformGlobalAccess account and its create/close instructions are retired. Existing PlatformConfig and GlobalConfig sizes do not change, but decoders must replace the old global flag with the new platform flag. Old access PDAs are not consumed by the new check.

Read path

For a UI showing “where did this token launch from”, PoolState.platform_config points at the originating PlatformConfig directly — fetch it once and cache the branding.

Update path

Wallet rotations (platform_fee_wallet, platform_nft_wallet, platform_vesting_wallet, platform_cp_creator, transfer_fee_extension_auth, cpswap_config) all go through UpdatePlatformConfig. Read the source’s update_platform_config dispatch table for the exact param codes.

Common pitfalls

  • restrict_curve_param enabled before the builder was updated. While it is 1 the rule PDA must be in remaining_accounts on every launch, even for a config with no rule account — an absent account is NotEnoughRemainingAccounts, not a pass. Ship the builder change first, then flip the flag.
  • restrict_curve_param enabled with an empty rule. A rule holding zero groups, or a group holding zero constraints, allows everything. Enabling the flag is not by itself a restriction; write the groups first, verify them with the SDK check, and rehearse the whole sequence on devnet.
  • NFT-split rounding. The three scales must sum to exactly 1_000_000. Off-by-one errors at CreatePlatformConfig revert; off-by-one at runtime would mint or burn one extra LP unit, which is what the strict-equality check is there to prevent.
  • Platform vesting double-allocation. If platform_vesting_scale > 0, the platform must call CreatePlatformVestingAccount once after the launch’s fundraising ends; if it forgets, that share remains unallocated and dormant forever (the launch’s total_locked_amount budget is consumed but the platform never claims).
  • platform_cp_creator ambiguity. When set to Pubkey::default(), the launch creator is recorded as the post-graduation CPMM pool’s pool_creator; when set to a real key, that key is recorded instead. This determines the beneficiary of post-graduation CPMM creator fees and who can sign the original CPMM::CollectCreatorFee path. The permissionless collection path still pays this recorded key’s canonical ATAs. Decide at platform-config creation time which model you want.
  • transfer_fee_extension_auth set late or rotated. The field is read twice per Token-2022 launch — once at mint creation for withdraw_withheld_authority, once at graduation for transfer_fee_config_authority — so a value that changes between those two moments leaves the two authorities on different keys. See Token-2022 transfer-fee authorities.
  • Restriction without an allow account. Enabling restrict_global_config before creating the required PlatformAllowConfig blocks new launches that select that config.

Pointers

Sources:
  • raydium-launch/programs/launchpad/src/states/platform_config.rsPlatformConfig, PlatformParams, MigrateNftInfo, is_curve_rule_manager, is_platform_admin.
  • raydium-launch/programs/launchpad/src/states/platform_curve_rule.rsPlatformCurveRule, CurveRuleGroup, ParamConstraint.
  • raydium-launch/programs/launchpad/src/states/platform_allow_config.rsPlatformAllowConfig.
  • raydium-launch/programs/launchpad/src/instructions/platform/update_platform_config.rsPlatformConfigParam dispatch and the per-field setters that enforce the update-time rate caps.
  • raydium-launch/programs/launchpad/src/lib.rs — platform config and allow-config entrypoints.
  • raydium-launch/programs/launchpad/src/instructions/initialize_with_token_2022.rs — where transfer_fee_extension_auth is written into the new mint’s TransferFeeConfig.
  • raydium-launch/programs/launchpad/src/instructions/admin/migrate_to_cpswap.rs — the graduation-time authority handover and its get_withdraw_withheld_authority guard.