TypeScript SDK

Program Upgrade 0.1.10

What the marginfi 0.1.9 → 0.1.10 program upgrade means for SDK integrators

Mainnet flips to program 0.1.10 on Tuesday 2026-08-25 at 17:00 CEST (15:00 UTC, unix 1787670000). Be on @0dotxyz/p0-ts-sdk@^2.7.0 before then. SDK 2.6.x and older keep working until the flip, then break on flash loans (loops, repay-with-collateral, collateral/debt swaps), health simulation and account transfers. Reads are not affected.

TL;DR: program 0.1.10 inserts required accounts into six instructions. That is a positional wire break in both directions, so a single SDK build cannot be sent to both programs unchanged. SDK >= 2.7.0 builds 0.1.10-style and, for the three affected instructions it actually uses, removes the inserted account again while the target program still runs 0.1.9. The switch is a per-program-id timestamp baked into the SDK — no RPC call, no caching. Upgrade the SDK any time before the flip with zero code changes.

Deployments

ProgramProgram IDGroupStatus
0.1.9MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA4qp6Fx6tnZkY5Wropq9wUYgtFxXKwE6viZxFHg3rdAG8mainnet production until the flip
0.1.10stag8sTKds2h4KzjUw3zKTsxbqvT4XKHdaR9X9E6RctFCPfpHA69EbS8f9KKSreTRkXbzFpunsKuYf5qNmnJjpostaging since 2026-08-03; mainnet after

Use getConfig("staging") (or "staging-mainnet-clone" for a production-like bank set) to test against 0.1.10 today.

What changes in the program

  • Per-bank oracle circuit breaker — a bank whose price moves more than a configured threshold in a window temporarily halts risk-increasing operations (borrow, withdraw, liquidate). New OperationalState.CircuitBroken bank state, which the SDK parses instead of throwing.
  • Same-asset e-mode — banks sharing a mint and oracle family (e.g. Kamino SOL, JupLend SOL, P0 SOL) can be placed in same-asset e-mode for higher leverage. New SameAssetEmodeRegistry account per group.
  • Configurable fees — per-liability-bank liquidation fees and a configurable account-transfer fee in FeeState.
  • Account resizesMarginfiGroup grows 1,056 → 9,248 bytes and FeeState 256 → 512 bytes (reserved padding, layouts are prefix-identical). Expect a short outage right after the mainnet deploy while accounts are resized.
  • Oracle fix — Switchboard feeds no longer use std_dev; oracle_max_confidence configures a static confidence spread instead.

Full details: UPGRADE-0.1.10.md in the SDK repo.

The breaking change: inserted accounts

Solana instructions carry accounts as an ordered, unnamed array. Inserting a required account mid-list shifts every later index, so the six instructions below break in both directions (old layout → new program and new layout → old program):

InstructionInserted accountPositionSDK handles it
lending_account_end_flashloangroupbefore authority (displaces the signer)makeEndFlashLoanIx
lending_account_pulse_healthgroupafter marginfi_accountmakePulseHealthIx
transfer_to_new_accountfee_statebefore system_programmakeAccountTransferToNewAccountIx
transfer_to_new_account_pdafee_statebefore system_program— no SDK builder
lending_account_start_liquidationgroupafter liquidation_record— no SDK builder
lending_account_end_liquidationgroup (+ optional trailing fee_payer)after liquidation_record— no SDK builder

Everything else survives: deposit / withdraw / borrow / repay / account create & close are unchanged, account decoding works across versions (layouts are prefix-identical), and admin instructions that only gained trailing Option args are tolerated by 0.1.9.

How the SDK handles it

Two pieces, both exported from the main entry:

import {
  MARGINFI_V0_1_10_ACTIVATION,
  isMarginfiV0110Live,
} from "@0dotxyz/p0-ts-sdk";

// program id (base58) → unix seconds at which that deployment runs 0.1.10
// `0` = already upgraded; unlisted programs count as already upgraded
console.log(MARGINFI_V0_1_10_ACTIVATION);
// { MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA: 1787670000,
//   stag8sTKds2h4KzjUw3zKTsxbqvT4XKHdaR9X9E6Rct: 0 }

// synchronous clock check — defaults to "now", optionally pass a unix timestamp
if (isMarginfiV0110Live(client.program.programId)) {
  console.log("target program speaks 0.1.10");
}

makeEndFlashLoanIx, makePulseHealthIx and makeAccountTransferToNewAccountIx always build the 0.1.10 layout and, while isMarginfiV0110Live(programId) is false, splice the inserted account out before returning. Every Layer 2–4 builder that uses them (makeLoopTx, makeRepayWithCollatTx, makeSwapCollateralTx, makeSwapDebtTx, makeFlashLoanTx, makeTransferPositionsTx, makeAccountTransferToNewAccountTx, simulateHealthCache, …) inherits the behaviour.

The timestamp encodes the plan, not the chain. If the upgrade is rescheduled, a patch release will carry the new timestamp — update before the originally announced time. Once the upgrade is final the switch is removed in a later release.

What you must do

Using the SDK's builders (Layers 2–4):

  1. Upgrade to @0dotxyz/p0-ts-sdk@^2.7.0 before 2026-08-25 15:00 UTC. No code changes.
  2. Optionally test against getConfig("staging"), which already runs 0.1.10.

Hand-rolling any of the six instructions (raw program.methods.*() calls, the /instructions subpath, or your own Borsh encoding) — the SDK cannot intercept those:

  • Add the inserted account at the positions in the table above, and gate on isMarginfiV0110Live(programId) if you need to keep sending to 0.1.9 until the flip.
  • end_liquidation gains an optional trailing fee_payer writable signer; when omitted, liquidation_receiver pays the flat fee as before.
  • Don't send 0.1.9-encoded admin instructions to 0.1.10: shorter args make the new program read garbage for the appended options.

Decoding accounts yourself: nothing breaks — but a Bank in CircuitBroken state only decodes with the 0.1.10 IDL bundled in SDK >= 2.7.0.

Troubleshooting

SymptomCauseFix
AnchorError caused by account: group. AccountNotEnoughKeys on a loop/swap0.1.9-style end_flashloan sent to a 0.1.10 programUpgrade SDK to >= 2.7.0
Same error from simulateBundle health simulation0.1.9-style pulse_healthUpgrade SDK to >= 2.7.0
Signer / system_program mismatch on flash loans or account transfer before the flip0.1.10 layout sent to 0.1.9 (hand-rolled, or wrong timestamp)Use the SDK builders, or gate on isMarginfiV0110Live

On this page