Skip to main content
TLDR:
  • SIMD-0500 makes sBPFv3 the only bytecode format a Solana cluster accepts when you deploy, upgrade, or finalize a program. It is expected on Mainnet with Agave 4.4 in November 2026.
  • Programs already on chain keep running in the format they were built in. The next upgrade of a v0, v1, or v2 program has to ship a v3 build, and the program ID stays the same.
  • cargo build-sbf still builds sBPFv0 unless you pass --arch v3. Anchor 1.2.0 and later build v3 by default.
  • A program that declares syscalls in its own extern "C" block fails to link as v3. Declare them through solana-define-syscall instead.
  • solana-test-validator 4.3.0 already enforces SIMD-0500, so a default v0 build fails to deploy to a local validator today.

Main article

Every Solana program is compiled to sBPF bytecode before it is deployed. Mainnet runs programs in four sBPF versions, v0 to v3, and most deployed programs are still v0. SIMD-0500 stops new v0, v1, and v2 code from reaching the chain so that the older formats can eventually be retired. The rule is gated behind the B8JJXCy5amZyWG9r7EnUYLwzXSXTxG7GZ1qZ1qggo83g feature. sBPFv3 deployment itself has been enabled on Mainnet since slot 428,976,000 on June 26, 2026, under the 5cC3foj77CWun58pC51ebHFUWavHWKarWyR5UUik7dnC feature, so you can rebuild and upgrade now.
To follow along with the deploy and call examples, you need a Solana node endpoint. See Solana tooling to get set up.

What sBPFv3 changes

sBPFv3 is the combination of three proposals:
  • Static syscalls (SIMD-0178) — a syscall is an ordinary call instruction whose immediate value is the murmur3 hash of the syscall name, fixed at link time. Validators no longer patch syscall addresses into a copy of the program when they load it.
  • Stricter ELF headers (SIMD-0189) — a v3 file carries no dynamic linking sections and no PT_DYNAMIC program header.
  • eBPF ISA compatibility (SIMD-0377) — the instruction set matches the eBPF that the LLVM BPF backend generates.
The version is stored in the e_flags field of the ELF header: 0x0 for v0 and 0x3 for v3. For most programs, the source code does not change and rebuilding with a current toolchain is the whole migration. The exception is a program that declares syscalls by hand. See Hand-declared syscalls fail to link.

What SIMD-0500 blocks

Once the feature is active, the upgradeable loader rejects a v0, v1, or v2 ELF in three instructions: Writing a buffer, extending a program, and closing an account are not affected. A rejected deployment fails in simulation:
By then, the CLI has already written the program to a buffer account, so a rejected deployment leaves the buffer and its rent behind. List and reclaim your buffers with:

Check the activation status

Query both features through your endpoint:
On Mainnet, before SIMD-0500 activates:

Check which format a program uses

For a program you built, read the ELF header of the .so file:
0x0 is v0, and 0x3 is v3. readelf comes with GNU binutils on Linux. On macOS, use the llvm-readelf that cargo build-sbf installs with its platform tools, for example ~/.cache/solana/v1.57/platform-tools/llvm/bin/llvm-readelf for Agave 4.3.0. For a program that is already deployed, dump its ELF through your endpoint and read the same field:
Any program that shows 0x0, 0x1, or 0x2 needs a v3 build before its next upgrade.

Install the toolchain

Install the Agave 4.3.0 release of the Solana CLI:
cargo build-sbf needs the cargo that rustup installs. A cargo from another package manager, such as Homebrew, fails with error: no such command: +1.95.0-sbpf-solana-v1.57.
Solana lists these minimum versions for sBPFv3 builds:

Rebuild a native or Pinocchio program

This minimal program logs a message with msg!:
Build it for v3:
The same command builds a Pinocchio program. Pinocchio 0.11 re-exports the solana-define-syscall declarations as pinocchio::syscalls, so a program that calls syscalls through that module links as v3 without changes.

Rebuild an Anchor program

Anchor 1.2.0 and later pass --arch v3 to cargo build-sbf, so anchor build produces a v3 program:
Update anchor-lang in your program’s Cargo.toml to the same version as the CLI. On Anchor 0.30.2, 0.31.2, and 0.32.2, anchor build still produces v0. Arguments after -- go to cargo build-sbf, but Anchor also passes them to the IDL build, which rejects --arch. Build the program and the IDL in two steps:
anchor idl build does not create its output directories, which is why the mkdir step comes first. A v0 program can declare a syscall in its own extern "C" block, because the loader resolves the name when it loads the program:
src/lib.rs
sBPFv3 has no load-time resolution, so cargo build-sbf --arch v3 fails at the link step:
Take the declaration from solana-define-syscall instead:
Import the syscall from solana_define_syscall::definitions and keep the rest of the program as it is:
src/lib.rs
For a syscall that definitions does not include, declare it with the define_syscall! macro instead of an extern "C" block. The macro emits the hash-based call for v3 and an extern "C" declaration for older versions. In macro form, the sol_log_ declaration is:
Agave 4.3.0 catches a hand-declared syscall at build time, and older toolchains do not. With Agave 4.2.2, cargo build-sbf --arch v3 builds the extern "C" version without an error, and the 4.2.2 CLI deploys it. The unresolved call never reaches the syscall, so every invocation fails with exceeded max BPF to BPF call depth. The 4.3.0 CLI refuses such a file before it sends anything, with Verifier error: Invalid function at instruction <N> (local pre-flight).
Build and deploy v3 programs with Agave 4.3.0 or later.

Deploy through your Chainstack endpoint

Deploy a new program:
To upgrade an existing program, pass its address with --program-id and sign with its upgrade authority, which is your default keypair unless you set --upgrade-authority. Upgrading a v0 program with a v3 build keeps the program ID, so clients and PDAs derived from it are unaffected:

Call the program

This script sends one instruction to the program with Solana Kit and prints the transaction logs:
call.mjs
A program becomes callable in the slot after its deployment. A call sent in the same slot fails with Program is not deployed.

Test locally

solana-test-validator 4.3.0 starts with every feature active, SIMD-0500 included, so it rejects a v0 build with the same error as above. To deploy a v0 build locally, start the validator with the feature turned off:
To rehearse the Mainnet upgrade with SIMD-0500 active, dump your current program and load it into the local validator at genesis, which bypasses the deployment check. Set the upgrade authority to the address of the keypair you deploy with, then upgrade the program with your v3 build:
In a second terminal:
The preloaded v0 program runs until the upgrade, the upgrade with the v3 build succeeds, and an upgrade with a v0 build fails.

Verified builds

solana-verify picks its Docker build image from the Solana version of your project. Programs that don’t depend on solana-program, such as Pinocchio programs, set the version in the root Cargo.toml:
Cargo.toml
solana-verify build and solana-verify verify-from-repo take an --arch flag that defaults to v0. Pass --arch v3 to both, so the verified build matches the v3 program on chain.

Readiness checklist

1

Inventory your programs

Dump each upgradeable program you own with solana program dump and read its Flags field. Anything other than 0x3 needs a v3 build before its next upgrade.
2

Update the toolchain

Install Agave 4.3.0 and, for Anchor projects, Anchor 1.2.0 or later.
3

Build for v3

Use cargo build-sbf --arch v3, or anchor build on Anchor 1.2.0 and later. Confirm Flags: 0x3 before you deploy.
4

Replace hand-declared syscalls

Move every extern "C" syscall declaration to solana-define-syscall.
5

Rehearse the upgrade locally

Preload the current program into solana-test-validator and upgrade it with the v3 build.
6

Upgrade before you have to

sBPFv3 deployment is already enabled on Mainnet. Upgrading now leaves no v0 program to block a later hotfix.

Additional resources

Last modified on October 7, 2026