1.0.0
Anchor - Release Notes 1.0.0
1.0.0 is the first stable major release of Anchor. It ships a large number of
breaking changes designed to clean up long-standing technical debt, modernize
the toolchain, and establish a stable foundation going forward. We cover the most
important changes below, but be sure to check out the full list of changes in
the
CHANGELOG.
How to upgrade
Using AVM (recommended)
-
Update
avmitself before installing the new CLI. If your currentavmsupportsself-update, use:Otherwise, bootstrap using
cargo install: -
Update
anchor-cli:
Without AVM
Install anchor-cli directly:
Common steps
-
Update Anchor crate(s) to
1.0.0. -
Update TS package(s). Note that the package has been renamed — see TypeScript package rename below.
Recommended Solana Version
The recommended Solana version is 3.1.10.
You can install the newer tooling by running:
Breaking Changes
TypeScript package rename
The TypeScript package has been moved from @coral-xyz/anchor to
@anchor-lang/core:
Update every import in your project:
IDL types that were previously imported from @coral-xyz/anchor/dist/cjs/idl
can now be imported directly from @anchor-lang/core:
Solana 3.0
Anchor 1.0.0 targets Solana 3.x. If you are still on Solana 2.x you must
upgrade your toolchain.
Solana CLI dependency removed
The anchor CLI no longer depends on the external solana CLI binary. Native
implementations are now provided for the most common sub-commands: balance,
airdrop, address, deploy, and others. This means the solana binary no
longer needs to be on your PATH for Anchor commands to work.
anchor test / anchor localnet now use Surfpool by default
Surfpool replaces the local validator as
the default backend for anchor test and anchor localnet. If you want to
keep using the solana-test-validator, pass --validator legacy.
Duplicate mutable accounts disallowed by default
Passing the same mutable account twice in an instruction now produces a runtime
error by default. If you intentionally need duplicate mutable accounts, opt in
with the dup constraint:
Legacy IDL instructions replaced by Program Metadata
The on-chain IDL management instructions that Anchor has used since the
beginning have been removed and replaced with the new
Program Metadata Program (PMP).
IDL uploads through anchor deploy and anchor idl commands work as before;
only the underlying mechanism has changed.
The program-id argument of anchor idl init and anchor idl upgrade is now
optional — when omitted, the program ID is read from the address field of the
IDL file itself.
If you are migrating an existing deployed program with IDL, you will need to close existing IDL accounts before deploying the new program based on anchor v1.0.0 as this will remove the IDL management instructions. This also depends on the previous v0.32.1 anchor cli.
Remove program account info from CPI context
The program field in CpiContext previously held a redundant copy of the
program AccountInfo. It has been removed:
interface-instructions feature removed
The interface-instructions feature flag and the #[interface] attribute have
been removed. Use #[instruction(discriminator = <EXPR>)]! to specify custom
discriminators.
Anchor.toml cleanup
- The
[registry]section is no longer recognized and should be removed. - The program
archbuild options have been removed from the CLI.
#[error_code] may only appear once per program
Having multiple #[error_code] blocks in a single program is now a
compile-time error.
Client tx signing error no longer panics
RequestBuilder::send (and friends) previously panicked when signing failed.
It now returns an Err instead.
AVM
avm self-update
Once your installed avm is v1-capable, you can update it without going
through cargo install:
To bootstrap to a version that supports this command, install via cargo:
Additionally, avm will passively warn you when it detects that a newer
version of itself is available.
Pre-release support
All avm commands (install, list, update) now understand pre-release
version labels:
CLI
Lifecycle hooks
You can now run shell commands at key points in the build/test/deploy
lifecycle by adding a [hooks] section to your Anchor.toml:
Supported hooks: pre_build, post_build, pre_test, post_test,
pre_deploy, post_deploy.
LiteSVM test template is now the default
anchor init now generates a LiteSVM
test template by default, replacing the previous TypeScript based default. You
can still pick a different template explicitly:
Program ID mismatch check
anchor build now checks that the program ID declared in your source code
matches the public key in the program's keypair file and emits an error if
they differ. This check is skipped during anchor test where ephemeral
keypairs are common. You can skip this check during builds with
anchor build --ignore-keys.
--install-agent-skills
Pass --install-agent-skills to anchor init to automatically install
Solana agent AI skills into the new workspace.
login command removed
anchor login has been removed along with the [registry] section of
Anchor.toml.
Lang
Migration<'info, From, To> account type
The new Migration type makes it straightforward to migrate accounts between
two different data layouts in a single instruction:
The account is deserialized as From, and serialized back as To on exit.
declare_program! improvements
Several renames apply to the code generated by declare_program!:
utils module renamed to parsers, and the parse methods renamed from
try_from_bytes to parse:
errors module renamed to error. ProgramError renamed to
<ProgramName>Error, where <ProgramName> is the PascalCase name of the
declared program:
declare_program! also now generates a typed instruction parser alongside the
CPI helpers. Use my_program::parsers::Instruction::parse with a
solana_instruction::Instruction to decode any instruction belonging to the
program.
Composite (non-instruction) account structs used multiple times within a program previously caused duplicate definitions or incorrect instruction name derivation in the generated code. Both issues are now fixed: each composite account definition is guaranteed to be unique, and instruction names that would collide have a number appended until a unique name is found.
Error generation has also been improved: declare_program! previously
interfered with the IDL error module generation of the declaring program.
Programs that use declare_program! alongside their own #[error_code] block
now produce correct error code definitions.
Use declare_program! with only anchor_client
It is no longer necessary to pull in anchor_lang just to use
declare_program! in a client-side context. Adding anchor_client as a
dependency is sufficient.
Remove lifetime definitions from Context
Three redundant lifetime parameters have been removed from Context. Most
programs will not be affected; if you referenced these lifetimes explicitly
you will need to update the annotations.
Deprecate AccountInfo in Accounts macro
Using AccountInfo directly inside an #[derive(Accounts)] struct now emits
a compile-time warning. Prefer UncheckedAccount or a more specific account
type.
Relaxed PDA seed syntax
The seed expressions accepted inside seeds = [...] constraints are now more
flexible and support a broader set of Rust expressions. Note that more complex
seed expressions reduce the likelihood of seeds being representable in the IDL
and of successful automatic account resolution on the client side.
Owner check on account reload
Calling .reload() on an Account now re-validates the owner, the same as
the initial load.
Generic Program type
Program<'info> can now be used without a type parameter for executable-only
validation when the concrete program type is not known statically:
Owners exported from prelude
anchor_lang::Owners is now re-exported from the prelude, so you no
longer need a separate use statement for it.
Borsh upgraded to 1.5.7
Both the Rust and TypeScript Borsh implementations have been updated to
1.5.7. Make sure your borsh dependency in Cargo.toml is compatible.
#[instruction(..)] argument validation
The compiler now enforces that the types and count of arguments in
#[instruction(..)] match the corresponding instruction handler signature,
catching mismatches that were previously silent.
IDL
Unsupported field types produce a hard error
Previously, defined types containing unsupported fields (e.g. tuple types) were silently omitted from the generated IDL. They now produce a compile-time error:
If you were relying on silent omission, you will need to refactor those fields into supported types before building.
Full path account names supported in IDL generation
The IDL builder previously rejected account types that shared a short name with
another type in a different module (e.g. program::module::Account conflicting
with other::Account). The conflicting account names check has been removed,
allowing full path account names to be used without errors.
address constraint resolves constants with numbers in their names
The address constraint previously failed to resolve constants whose
identifiers contained numbers (e.g. MY_PROGRAM_V2_ID). This is now fixed.
serde_json is now optional
The serde_json dependency of anchor-lang-idl is now behind an opt-in
feature flag, reducing compile times when JSON serialization is not needed.
External accounts excluded from IDL
Accounts defined in external programs (e.g. SPL token accounts referenced in
your IDL) are no longer included in the generated IDL's accounts array,
keeping the IDL focused on your own program's types.
Custom error offset respected
The offset = N argument in #[error_code] is now correctly reflected in
the generated IDL, so the error codes in the IDL match what is emitted at
runtime.
TypeScript
IDL fetching updated for PMP
The TypeScript client now fetches IDLs from the new Program Metadata Program
storage. Existing code using Program.fetchIdl continues to work without
changes.
Rust Client
FnMut closures for event subscriptions
program.on::<Event>(|event, slot| { ... }) now accepts FnMut closures,
allowing you to capture mutable state from the surrounding scope.
Reduced re-exports from anchor-client
anchor-client previously re-exported the entirety of solana-sdk, which
made it easy to discover types but pulled in a large dependency. It now only
re-exports the types that are directly part of its public API. If you were
relying on transitive solana-sdk types through anchor-client, you will
need to add the relevant crates (solana-account, solana-pubkey, etc.) as
explicit dependencies.
See the full list of notable changes in the CHANGELOG.