Release Notes

Release Notes 0.30.0

The long-awaited v0.30.0 release is finally here!

We'll go over the main changes, but if you'd like to see all notable changes, check out the CHANGELOG.

How to upgrade

  1. Update avm:

    cargo install --git --tag v0.30.0 avm --locked
  2. Update anchor-cli:

    avm install latest
  3. Update Anchor crate(s) to 0.30.0. Optionally, run cargo update to update other dependencies to the latest compatible versions.

  4. Update TS package(s) to 0.30.0.

While this release supports anything above 1.16, the recommended Solana version is 1.18.8. You can upgrade Solana tools by running:

solana-install init 1.18.8


The IDL type specification and generation has been rewritten. To keep the release notes short, we won't go over the changes here, but see this if you'd like to learn more.

idl-build feature

idl-build feature is now required in your program's Cargo.toml definition in order for the IDL generation to work.

Without this feature, anchor build outputs:

Error: `idl-build` feature is missing. To solve, add

idl-build = ["anchor-lang/idl-build"]


Note that all crates that you use to generate type definitions for the IDL need to be specified in the list of idl-build, e.g. anchor-spl/idl-build, some-program/idl-build...


Dependency free program declaration

Depending on other crates who used different versions of Anchor is not the best experience, to say the least. To solve this problem, program clients can now be generated from their IDL using the new declare_program! macro:


program_name is based on the file name of the IDL in idls directory, e.g. idls/program_name.json is required to exist in order for the above example to work.

This works for both on-chain (CPI) and off-chain (RPC) usage, allowing program interactions without creating a dependency hell. Check out this example for on-chain CPI usage.

For more information, see the macro's documentation.

Token extensions


There are new account constraints for Token Extensions (Token 2022):

  • group_pointer:
    • authority
    • group_address
  • group_member_pointer:
    • authority
    • member_address
  • metadata_pointer:
    • authority
    • metadata_address
  • close_authority
    • authority
  • permanent_delegate:
    • delegate
  • transfer_hook:
    • authority
    • program_id

Note: Above values are concatinated with :: (similar to other Anchor constraints) and have extensions prefix e.g. extensions::group_pointer::authority = <EXPR>.

These constraints can be used both with or without the init constraint.

Here is an example program that uses these constraints.

CPI wrappers

anchor-spl now includes CPI wrappers for Token Extensions which can be accessed from anchor_spl::token_2022_extensions.

#[interface] attribute

Transfer hooks can now be used with the new #[interface] macro. This argument overrides the Anchor's default instruction discriminator to use the interface instruction's discriminator.

Current supported values are:

  • spl_transfer_hook_interface::initialize_extra_account_meta_list
  • spl_transfer_hook_interface::execute
mod my_hook_program {
    pub fn initialize(ctx: Context<Initialize>, metas: Vec<AnchorExtraAccountMeta>) -> Result<()> {
        /* ... */

    pub fn execute(ctx: Context<Execute>, amount: u64) -> Result<()> {
        /* ... */

Optional bumps

When an optional account is not specified, instead of defaulting it to u8::MAX, this release changes the optional bump type to be Option<u8> and sets the bump field to None.

Less heap allocations

BorshSerialize::try_to_vec implementation, which is used in events, CPI, and return data, heap allocates 1024 bytes each time it's used, even if your data is much smaller. In this release, the default allocation is set to 256 bytes.

There is also a new method InstructionData::write_to() to write to an existing allocation rather than creating a new allocation with InstructionData::data().


Priority fees in CLI

IDL commands take in --priority-fee argument As it's getting harder and harder to land transactions in mainnet-beta without using priority fees, this release supports setting --priority-fee argument for the IDL commands. For example:

anchor idl erase-authority --program-id <PROGRAM_ID> --priority-fee 9000

When the --priortiy-fee argument is not specified, the median fee of the last 150 confirmed slots is used.

--no-idl flag on builds

IDL generation requires building of the program, but this is unnecessary if your program API doesn't change. In that case, you can use --no-idl flag to build your program but skip the IDL generation:

anchor build --no-idl

IDL buffer is closed after idl upgrade

After an IDL upgrade, the buffer account is now closed and the lamports are returned back to the IDL authority.

Pass deploy arguments to solana-cli

You can now pass arguments to solana program deploy from anchor deploy:

anchor deploy -- --final

Verifiable deployments

Similar to verifiable builds, you can now deploy the verified build instead of the default build:

anchor deploy --verifiable

Accept package name as program name

--program-name (-p) argument of various commands also works with package name of the program rather than lib name which is snake_case. For example:

anchor build -p my-program

Deactivate test-validator features

You can now deactivate test-validator features from Anchor.toml:

deactivate_feature = ["GDH5TVdbTPUpRnXaRyQqiKUa7uZAbZ28Q2N9bhbKoMLm", "zkiTNuzBKxrCLMKehzuQeKZyLtX2yvFcEKMML8nExU8"]

Crate and package compatibility

Using non-matching versions of anchor-cli, anchor-lang, and @coral-xyz/anchor can result in unexpected behavior. In this release, you'll get a warning if any of them don't match.

Explicit overflow-checks flag

overflow-checks flag is implicitly disabled by default. Anchor workspaces that are crated with anchor init have this flag enabled, however, Anchor doesn't do any checks for it after the initial workspace creation.

With this release, overflow-checks in the workspace Cargo.toml need to be specified. Note that "specified" does not mean enabled, as you can also disable it, but you need to be explicit in doing so.

Wildcard pattern in Anchor.toml

workspace.members and workspace.exclude now supports simple wildcard pattern:

members = ["programs/*"]

Note that the support is limited to this simple wildcard pattern, and more complex globs are not currently supported.

cargo build-sbf is now the default

Before this release, anchor build used cargo build-bpf to build programs, however, because it is deprecated, anchor build now defaults to cargo build-sbf.

To preserve the old behavior, you can use:

anchor build --arch bpf

Run multiple commands in scripts

Scripts in Anchor.toml now supports running multiple commands:

test-all = "cargo test && yarn run ts-mocha tests/**/*.ts"

This script would run both cargo and yarn commands:

anchor run test-all

Test only a specified program

A single program can be tested in a multi program workspace with the --program-name (-p) argument:

anchor test --program-name example

This builds and tests only the specified program.

Rust test template

A wild TypeScript test won't appear if you initialize your workspace with the new Rust test template:

anchor init --test-template rust


Account resolution

Account resolution refers to the ability of clients to resolve accounts without having to manually specify them when sending transactions.

There are too many changes to the account resolution logic in the TS library, however, we can skip a good chunk of them since they're mostly internal.

One change that affects everyone is the change in the accounts method. Even though the TS library had some support for account resolution, it had no type-level support for it — all accounts were essentially typed as partial, and there was no way to know which accounts were resolvable and which were not.

There are now 3 methods to specify accounts with the transaction builder:

  • accounts: This method is now fully type-safe based on the resolution fields in the IDL, making it much easier to only specify the accounts that are actually needed.
  • accountsPartial: This method keeps the old behavior and let's you specify all accounts including the resolvable ones.
  • accountsStrict: If you don't want to use account resolution and specify all accounts manually (unchanged).

This change is likely to result in errors in your existing .accounts() calls. To fix, either change accounts to accountsPartial, or remove all accounts that can be resolved from the IDL. For example:

- await program.methods
-   .init()
-   .accounts({
-     pda: ...,
-     signer: ...,
-     systemProgram: ...,
-   })
-   .rpc();
+ await program.methods.init().rpc();

Magic account names

Another change that affects most projects is the removal of "magic" account names. The TS library used to autofill common program and sysvar accounts based on their name, e.g. systemProgram, however, this is no longer necessary with the introduction of the address field (in the IDL) which is used to resolve all program and sysvars by default.

Case conversion

The internals of the TS library are filled with case conversion logic before making string comparison and this also forces other libraries who build on top of Anchor to do the same.

Along with making the IDL have consistent casing, TS library also has consistent casing (camelCase) in this release.

No more Program ID

programId parameter of Program is removed since the new IDL requires to store the program id in its address field:

- new Program(idl, programId);
+ new Program(idl);

Optional provider options

opts parameter of AnchorProvider is now optional:

- new AnchorProvider(connection, wallet, {});
+ new AnchorProvider(connection, wallet);

Type changes

There are too many type changes to list here, especially the types that are related to the IDL. The new IDL types can be found here.

See the full list of notable changes in the CHANGELOG.