This entry covers an upcoming CLMM program update. It was verified against the
chore/upgrade-anchor branch of raydium-clmm (head a72f9e1) before deployment. Confirm the deployed program before relying on the new instruction or the changed CreateAmmConfig behaviour.0.32.1 to =1.0.2, and the build toolchain goes from Agave 2.3.0 to 3.1.10. Two admin-side changes ride along: a new CollectExcessLamports instruction, and fixed fee owners in CreateAmmConfig.
Every instruction a trader, an LP, a limit-order user or a pool creator calls keeps its account list, arguments and math.
TL;DR for integrators
- No user-facing instruction changed.
CreatePool,CreateCustomizablePool,CreatePermissionedPool, everyOpenPosition*/IncreaseLiquidity*/DecreaseLiquidity*path,ClosePosition,Swap/SwapV2/SwapRouterBaseIn, the five limit-order instructions and the reward instructions are byte-identical on the wire. No account layout changed. - One instruction is added:
CollectExcessLamports. It is admin-only and takes no arguments. It sweeps one pool per call: the pool’s ownPoolStateis always swept, and the pool PDA signs for its vaults, which you pass inremaining_accounts. Any other CLMM-owned account inremaining_accountsis swept too. Seeproducts/clmm/instructions. - One error code is appended:
6052LamportsCalculateError. Codes6000–6051are unchanged. CreateAmmConfigno longer copies the signer intoowner/fund_owner. New configs get hardcodedprotocol_fee_ownerandfund_fee_ownerkeys. On mainnet these are the same two keys already stored on all 21 existing configs. ExistingAmmConfigaccounts are untouched, so keep reading the fields off the account.- Refresh your IDL. It adds one instruction and one error variant, for 39 instructions and 53 errors.
- You can now put CPMM and CLMM in one crate. Both repos pin
anchor-lang/anchor-spl=1.0.2on theirchore/upgrade-anchorbranches, so a single program can CPI into both. Seesdk-api/rust-cpi. - The TypeScript client package is renamed. The test suite moves from
@coral-xyz/anchor0.32.1to@anchor-lang/core1.0.2.
CollectExcessLamports
Step 1 of SIMD-0437 activated on mainnet on 3 September 2026. Every CLMM account created before a step is now over-funded, and only the CLMM program can move lamports out of an account it owns. That covers pool vaults, reward vaults, PoolState, AmmConfig, ObservationState, TickArrayBitmapExtension and the rest.
The instruction takes four fixed accounts, then any number of source accounts in remaining_accounts:
The pool is the signing authority, not a program-wide PDA. CPMM signs with one global
vault_and_lp_mint_auth_seed authority. CLMM token vaults are owned by their PoolState, so a single call can only sign for the pool passed in slot 2. Each token-program source must have that pool as its authority: token_vault_0, token_vault_1, or one of the pool’s reward vaults. A token account from another pool, or a user’s token account, fails the token program’s owner check and reverts the whole instruction. The program does not skip it. Position NFT mints are not sweepable either, because their mint authority is revoked when the position is opened. Sweep pool by pool.
The instruction makes two passes, and that order is fixed:
- Token-program CPIs first. For every source owned by SPL Token or Token-2022, a non-native account gets
WithdrawExcessLamports(discriminant38). A native wSOL vault gets theSyncNative→UnwrapLamports(discriminant45) round-trip, which ends with a check that the wrapped balance equals its pre-sync value. If it doesn’t, the call fails withLamportsCalculateError. A SOL-side vault keeps its full liquidity, and no swap quote changes across a sweep. - Direct debits second. Pass 2 debits
pool_statefirst, then every source owned by the CLMM program, down torent.minimum_balance(data_len).
UnbalancedInstruction, so callers can pass sources in any order.
The wallet addresses are listed in reference/program-addresses.
CreateAmmConfig writes fixed fee owners
Before this release, create_amm_config set both fee-owner fields from the calling signer:
CreateAmmConfig is still gated to crate::admin::ID. Before this release, every new fee tier started with the admin in both fields and had to be rotated with UpdateAmmConfig param 3 / 4. Now it starts with the operational wallets. On mainnet the constants are the same keys already stored as owner / fund_owner on all 21 existing configs. The program now writes a value that operations used to set by hand.
Collection signers do not change. CollectProtocolFee accepts amm_config.owner or crate::admin::ID, and CollectFundFee accepts amm_config.fund_owner or crate::admin::ID, both before and after this release.
On devnet, both constants resolve to the same key. See reference/program-addresses.
Toolchain and dependency changes
The Anchor 1.0 changes at CPI call sites are the same ones CPMM integrators already handled.
CpiContext::new takes the program’s Pubkey rather than its AccountInfo, and Context has one lifetime parameter instead of four. In the client crate, RequestBuilder::instructions() now returns Vec<Instruction> without a Result, and system_program moved to solana-system-interface. See sdk-api/rust-cpi.
Build-system details with no on-chain effect:
- Localnet admin. The
localnetfeature no longer compiles in a fixed test key backed by a committed fixture. Instead it reads the admin from theCLMM_LOCALNET_ADMINenvironment variable at build time, whichyarn test:local-adminsets from your local wallet. The fixture’s.gitignoreexception is gone. - Release profile. The duplicate
[profile.release]block inprograms/amm/Cargo.tomlwas deleted. Cargo ignores[profile]outside the workspace root, so the root block was already the one in effect, and the program-levelpanic = "abort"was never applied. - Anchor.toml.
seeds = falsebecomesresolution = trueplusskip-lint = false, and the stale[registry]URL is removed. - Lints.
programs/amm/Cargo.tomladds a[lints.rust] unexpected_cfgsallow-list for the feature cfgs that the Anchor and Solana macros emit. - README. On this branch the README still tells you to run
rustup default 1.86.0andavm install 0.32.1fromcoral-xyz/anchor. FollowAnchor.tomlandsolana-fundamentals/toolchaininstead.
What did not change
- Every account layout.
PoolState,AmmConfig,TickArrayState,TickArrayBitmapExtension,PersonalPositionState,ObservationState,LimitOrderState,DynamicFeeConfig,PermissionandSupportMintAssociatedkeep the same sizes and offsets. - Error codes
6000–6051. - Swap, liquidity, fee, dynamic-fee and limit-order math.
CollectExcessLamportsmoves lamports that were never part of any pool’s reserves. - Position NFT freezing from 2026-08-17, including the pool-as-freeze-authority rule and the
ClosePositionthaw path. spl_memo.DecreaseLiquidityV2’s memo-program constraint moved fromspl_memo::id()toanchor_spl::memo::ID. Both name the same address;anchor-spljust renamed the export.- Program ID.
Pages updated
products/clmm/instructions: upgrade banner;CollectExcessLamportssection with its account list, two-pass dispatch table and per-pool scoping; inventory, admin-gating and state-change-matrix rows; fee-owner note onCollectProtocolFee/CollectFundFee.products/clmm/accounts:AmmConfigowner comments and a note on whatCreateAmmConfigwrites.products/clmm/code-demos: version banner and Rust CPI skeleton moved to Anchor 1.0.products/cpmm/code-demos: the “cannot share a crate with CLMM” note removed.reference/error-codes:6052documented.reference/program-addresses: new “CLMM fee-owner wallets” section; CLMM added to “Excess-lamports collection wallets”.sdk-api/rust-cpi,sdk-api/anchor-idl,solana-fundamentals/toolchain: Anchor 1.0 pins forraydium-clmm, and the crate-split warning retired.solana-fundamentals/rent-and-reclaimable-rent: CLMM added to “What the Raydium programs sweep on their own side”.security/admin-and-multisig: CLMM excess-lamports collector role.protocol-overview/versions-and-migration: CLMM upgrade history bullet.

