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
| Program | Program ID | Group | Status |
|---|---|---|---|
| 0.1.9 | MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA | 4qp6Fx6tnZkY5Wropq9wUYgtFxXKwE6viZxFHg3rdAG8 | mainnet production until the flip |
| 0.1.10 | stag8sTKds2h4KzjUw3zKTsxbqvT4XKHdaR9X9E6Rct | FCPfpHA69EbS8f9KKSreTRkXbzFpunsKuYf5qNmnJjpo | staging 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.CircuitBrokenbank 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
SameAssetEmodeRegistryaccount per group. - Configurable fees — per-liability-bank liquidation fees and a configurable account-transfer fee in
FeeState. - Account resizes —
MarginfiGroupgrows 1,056 → 9,248 bytes andFeeState256 → 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_confidenceconfigures 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):
| Instruction | Inserted account | Position | SDK handles it |
|---|---|---|---|
lending_account_end_flashloan | group | before authority (displaces the signer) | ✅ makeEndFlashLoanIx |
lending_account_pulse_health | group | after marginfi_account | ✅ makePulseHealthIx |
transfer_to_new_account | fee_state | before system_program | ✅ makeAccountTransferToNewAccountIx |
transfer_to_new_account_pda | fee_state | before system_program | — no SDK builder |
lending_account_start_liquidation | group | after liquidation_record | — no SDK builder |
lending_account_end_liquidation | group (+ 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):
- Upgrade to
@0dotxyz/p0-ts-sdk@^2.7.0before 2026-08-25 15:00 UTC. No code changes. - 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_liquidationgains an optional trailingfee_payerwritable signer; when omitted,liquidation_receiverpays 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
| Symptom | Cause | Fix |
|---|---|---|
AnchorError caused by account: group. AccountNotEnoughKeys on a loop/swap | 0.1.9-style end_flashloan sent to a 0.1.10 program | Upgrade SDK to >= 2.7.0 |
Same error from simulateBundle health simulation | 0.1.9-style pulse_health | Upgrade SDK to >= 2.7.0 |
Signer / system_program mismatch on flash loans or account transfer before the flip | 0.1.10 layout sent to 0.1.9 (hand-rolled, or wrong timestamp) | Use the SDK builders, or gate on isMarginfiV0110Live |