Skip to main content
This entry covers an upcoming AMM v4 program update. It was verified against the local release branch before deployment. Confirm the deployed program before relying on the new instruction.
Two unrelated things arrive together in one rebuild. The first is housekeeping: AMM v4 had been pinned to solana-program =2.1.0 since the 2.1 upgrade, and that pin was blocking. The system-program helpers moved into their own solana-system-interface crate in Solana 3.0, spl-token reached 9.0, and spl-associated-token-account reached 8.0. This release takes all three. The second is money the protocol is owed. SIMD-0437 is cutting the rent-exempt minimum by 90% in five steps, and step 1 landed on mainnet on 3 September 2026. Every account AMM v4 created before then — hundreds of pool vaults, LP mints, AmmInfo and TargetOrders accounts — is now over-funded, and lamports in a program-owned account can only be moved by that program. Hence a new instruction.

TL;DR for integrators

  • Nothing a trader or LP calls has changed. Initialize2, Deposit, Withdraw, SwapBaseIn, SwapBaseOut, SwapBaseInV2, SwapBaseOutV2, WithdrawPnl and SetParams keep their account lists, argument layouts and math. No account layout changed. No existing error code moved.
  • One instruction is added: WithdrawExcessLamports, tag 18. Admin-only, no arguments, variadic account list. It returns lamports above the rent-exempt minimum from AMM v4-controlled accounts and touches nothing else. See products/amm-v4/instructions.
  • One error code is appended: 60 LamportsCalculateError. AmmError is not Anchor-numbered — it starts at 0 — so this is custom program error: 0x3c. Codes 059 are unchanged.
  • CreateConfigAccount (tag 14) stopped reading the rent sysvar and is now documented as a 4-account instruction. Nothing in this release is breaking, this included: the account was last in the list and the handler reads positionally with no length check, so admin tooling that still passes it keeps working.
  • An IDL refresh is required if you generate clients from one. One new instruction, one new error variant, one changed account list.

WithdrawExcessLamports

The instruction takes the collect-lamports wallet as the sole signer and destination, the AMM v4 authority PDA, the SPL Token program, and then any number of source accounts. It dispatches on each source account’s owner: The wSOL branch is the interesting one. A wrapped-SOL account’s lamport balance is its token balance, so the token program rejects WithdrawExcessLamports on it outright. The round-trip through SyncNative and a delta-sized UnwrapLamports extracts only the donated excess and leaves the wrapped balance exactly where it started — which is asserted afterwards, with LamportsCalculateError if the arithmetic disagrees. A SOL-side pool vault therefore keeps its full liquidity through a sweep, and no LP sees a price change across one. The signer is a dedicated key per cluster, hardcoded under the same config_feature module as the existing AMM owner and create-pool-fee addresses. Unlike CPMM and LaunchLab, AMM v4 accepts only that wallet — there is no admin fallback. Addresses are in reference/program-addresses.

CreateConfigAccount stopped reading the rent sysvar

Solana 3.0 is what makes Rent::get() the natural way to read rent parameters, so the release replaced all four Rent::from_account_info(...) calls in the program. In three of them — the helpers that create a pool’s token accounts, LP mint and PDA accounts during Initialize2 — the sysvar account is still passed and still forwarded into the token-program CPIs, so nothing about that account list changes. In CreateConfigAccount the sysvar had no other purpose and was the last account in the list, so it came out of the documented list: Sending the old five-account list still works. The removed account was last, and process_create_config reads its four accounts positionally through next_account_info with nothing checking the total count, so a trailing rent account is never looked at. Admin tooling should be updated for clarity, not urgency. No user-facing builder constructs this instruction at all. Initialize2 is the case not to over-read: it also stopped calling Rent::from_account_info, but its rent account stays in position 3 and is still genuinely used — the program forwards it into the spl_token::initialize_account and initialize_mint CPIs that create the pool’s vaults and LP mint. Dropping it from that account list would break pool creation.

Dependency changes

The system-program pieces the program uses — system_instruction::create_account, transfer, allocate, assign, and the program ID itself — now come from solana-system-interface rather than solana_program::system_program and solana_program::system_instruction. The program ID is byte-identical, so this is a compile-time move with no on-chain consequence, including for the InvalidSysProgramAddress checks that compare against it. Two dead modules were also deleted: srm_token and msrm_token, the Serum/MSRM mint declarations left over from the OpenBook removal. Nothing referenced them.

What did not change

  • Every account layout. AmmInfo, StateData, TargetOrders, AmmConfig — same sizes, same field offsets. No indexer or decoder change.
  • Error codes 059. LamportsCalculateError is appended at 60, so nothing shifts.
  • The AMM authority PDA. Still one PDA for the whole program, seed ["amm authority"], nonce 254.
  • Fees, PnL accounting, and the curve. Untouched. WithdrawExcessLamports moves lamports that were never part of any pool’s reserves.
  • Token-2022. Still unsupported. The new instruction speaks only to the legacy SPL Token program.
  • Program ID. Unchanged — see reference/program-addresses.

Pages updated

  • products/amm-v4/instructionsWithdrawExcessLamports added with its account list and per-owner dispatch table; new CreateConfigAccount / UpdateConfigAccount section covering the rent-sysvar removal; inventory table and state-change matrix rows added.
  • products/amm-v4/overview — release banner.
  • reference/error-codes — new “AMM v4: AmmError is not Anchor-numbered” section documenting code 60 and the 0-based numbering.
  • reference/program-addresses — new “Excess-lamports collection wallets” section.
  • solana-fundamentals/rent-and-reclaimable-rent — new “What the Raydium programs sweep on their own side” section; the wrapped-SOL note corrected to say both token programs expose UnwrapLamports.
  • solana-fundamentals/toolchain — Agave 3.1.10, release.anza.xyz, Rust 1.91.0.