CPI Guard

What Is CPI Guard?

The Token Extension Program's CpiGuard account extension prevents another onchain program from using a token account for certain token instructions through a cross-program invocation (CPI).

When CPI guard is enabled, the Token Extension Program rejects these instructions when another onchain program invokes them through CPI:

  • Transfer, TransferChecked, and TransferCheckedWithFee when the token account owner is used as the instruction authority
  • Burn and BurnChecked when the token account owner is used as the instruction authority
  • Approve and ApproveChecked
  • CloseAccount when lamports would be sent somewhere other than the token account owner
  • SetAuthority when adding or replacing the close authority

When CPI guard is enabled, these cases are still allowed:

  • Transfer, TransferChecked, TransferCheckedWithFee, Burn, and BurnChecked through CPI when a delegate or permanent delegate signs instead of the token account owner
  • CloseAccount through CPI when lamports are sent to the token account owner
  • SetAuthority to remove an existing close authority
  • Revoke

When the token account owner is used as the instruction authority, Token Extension Program instructions can still be processed if the instruction is added directly to the transaction instead of being invoked through CPI. Changing the token account owner with SetAuthority stays blocked while CPI guard is enabled, even outside CPI. EnableCpiGuard and DisableCpiGuard also cannot be invoked through CPI.

How to Enable CPI Guard

To enable CPI guard:

  1. Create and initialize a mint.
  2. Calculate the token account size and rent needed for a token account with CpiGuard.
  3. Create and initialize a token account for the mint.
  4. Invoke EnableCpiGuard on the token account.
  5. Invoke DisableCpiGuard on the token account to allow those instructions through CPI again.

Create and initialize the mint

Create and initialize the mint that the token account will use.

Example
const client = await createClient()
.use(generatedPayer())
.use(
solanaRpc({
rpcUrl: "http://localhost:8899",
rpcSubscriptionsUrl: "ws://localhost:8900"
})
)
.use(rpcAirdrop())
.use(airdropPayer(lamports(1_000_000_000n)));
const mint = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();
const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
.getMinimumBalanceForRentExemption(mintSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer,
newAccount: mint,
lamports: mintRent,
space: mintSpace,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
getInitializeMintInstruction({
mint: mint.address,
decimals: 0,
mintAuthority: client.payer.address,
freezeAuthority: client.payer.address
})
]);

Calculate token account size

Calculate the token account size for the base token account plus the CpiGuard extension. This is the size used in CreateAccount.

Example
const client = await createClient()
.use(generatedPayer())
.use(
solanaRpc({
rpcUrl: "http://localhost:8899",
rpcSubscriptionsUrl: "ws://localhost:8900"
})
)
.use(rpcAirdrop())
.use(airdropPayer(lamports(1_000_000_000n)));
const mint = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();
const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
.getMinimumBalanceForRentExemption(mintSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer,
newAccount: mint,
lamports: mintRent,
space: mintSpace,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
getInitializeMintInstruction({
mint: mint.address,
decimals: 0,
mintAuthority: client.payer.address,
freezeAuthority: client.payer.address
})
]);
const cpiGuardExtension = extension("CpiGuard", {
lockCpi: false
});
const tokenSpace = BigInt(getTokenSize([cpiGuardExtension]));

Calculate rent

Calculate rent using the token account size needed for the CpiGuard extension.

Example
const client = await createClient()
.use(generatedPayer())
.use(
solanaRpc({
rpcUrl: "http://localhost:8899",
rpcSubscriptionsUrl: "ws://localhost:8900"
})
)
.use(rpcAirdrop())
.use(airdropPayer(lamports(1_000_000_000n)));
const mint = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();
const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
.getMinimumBalanceForRentExemption(mintSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer,
newAccount: mint,
lamports: mintRent,
space: mintSpace,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
getInitializeMintInstruction({
mint: mint.address,
decimals: 0,
mintAuthority: client.payer.address,
freezeAuthority: client.payer.address
})
]);
const cpiGuardExtension = extension("CpiGuard", {
lockCpi: false
});
const tokenSpace = BigInt(getTokenSize([cpiGuardExtension]));
const tokenRent = await client.rpc
.getMinimumBalanceForRentExemption(tokenSpace)
.send();

Create and initialize the token account

Create the token account with the calculated space and lamports, then initialize it for the mint.

Example
const client = await createClient()
.use(generatedPayer())
.use(
solanaRpc({
rpcUrl: "http://localhost:8899",
rpcSubscriptionsUrl: "ws://localhost:8900"
})
)
.use(rpcAirdrop())
.use(airdropPayer(lamports(1_000_000_000n)));
const mint = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();
const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
.getMinimumBalanceForRentExemption(mintSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer,
newAccount: mint,
lamports: mintRent,
space: mintSpace,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
getInitializeMintInstruction({
mint: mint.address,
decimals: 0,
mintAuthority: client.payer.address,
freezeAuthority: client.payer.address
})
]);
const cpiGuardExtension = extension("CpiGuard", {
lockCpi: false
});
const tokenSpace = BigInt(getTokenSize([cpiGuardExtension]));
const tokenRent = await client.rpc
.getMinimumBalanceForRentExemption(tokenSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer,
newAccount: tokenAccount,
lamports: tokenRent,
space: tokenSpace,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
getInitializeAccountInstruction({
account: tokenAccount.address,
mint: mint.address,
owner: client.payer.address
})
]);

Enable CPI guard

Enable CpiGuard on the token account.

Example
const client = await createClient()
.use(generatedPayer())
.use(
solanaRpc({
rpcUrl: "http://localhost:8899",
rpcSubscriptionsUrl: "ws://localhost:8900"
})
)
.use(rpcAirdrop())
.use(airdropPayer(lamports(1_000_000_000n)));
const mint = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();
const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
.getMinimumBalanceForRentExemption(mintSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer,
newAccount: mint,
lamports: mintRent,
space: mintSpace,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
getInitializeMintInstruction({
mint: mint.address,
decimals: 0,
mintAuthority: client.payer.address,
freezeAuthority: client.payer.address
})
]);
const cpiGuardExtension = extension("CpiGuard", {
lockCpi: false
});
const tokenSpace = BigInt(getTokenSize([cpiGuardExtension]));
const tokenRent = await client.rpc
.getMinimumBalanceForRentExemption(tokenSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer,
newAccount: tokenAccount,
lamports: tokenRent,
space: tokenSpace,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
getInitializeAccountInstruction({
account: tokenAccount.address,
mint: mint.address,
owner: client.payer.address
})
]);
await client.sendTransaction([
getEnableCpiGuardInstruction({
token: tokenAccount.address,
owner: client.payer
})
]);

Disable CPI guard

Disable CpiGuard on the token account.

Example
const client = await createClient()
.use(generatedPayer())
.use(
solanaRpc({
rpcUrl: "http://localhost:8899",
rpcSubscriptionsUrl: "ws://localhost:8900"
})
)
.use(rpcAirdrop())
.use(airdropPayer(lamports(1_000_000_000n)));
const mint = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();
const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
.getMinimumBalanceForRentExemption(mintSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer,
newAccount: mint,
lamports: mintRent,
space: mintSpace,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
getInitializeMintInstruction({
mint: mint.address,
decimals: 0,
mintAuthority: client.payer.address,
freezeAuthority: client.payer.address
})
]);
const cpiGuardExtension = extension("CpiGuard", {
lockCpi: false
});
const tokenSpace = BigInt(getTokenSize([cpiGuardExtension]));
const tokenRent = await client.rpc
.getMinimumBalanceForRentExemption(tokenSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer,
newAccount: tokenAccount,
lamports: tokenRent,
space: tokenSpace,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
getInitializeAccountInstruction({
account: tokenAccount.address,
mint: mint.address,
owner: client.payer.address
})
]);
await client.sendTransaction([
getEnableCpiGuardInstruction({
token: tokenAccount.address,
owner: client.payer
})
]);
await client.sendTransaction([
getDisableCpiGuardInstruction({
token: tokenAccount.address,
owner: client.payer
})
]);

Create and initialize the mint

Create and initialize the mint that the token account will use.

Calculate token account size

Calculate the token account size for the base token account plus the CpiGuard extension. This is the size used in CreateAccount.

Calculate rent

Calculate rent using the token account size needed for the CpiGuard extension.

Create and initialize the token account

Create the token account with the calculated space and lamports, then initialize it for the mint.

Enable CPI guard

Enable CpiGuard on the token account.

Disable CPI guard

Disable CpiGuard on the token account.

Example
const client = await createClient()
.use(generatedPayer())
.use(
solanaRpc({
rpcUrl: "http://localhost:8899",
rpcSubscriptionsUrl: "ws://localhost:8900"
})
)
.use(rpcAirdrop())
.use(airdropPayer(lamports(1_000_000_000n)));
const mint = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();
const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
.getMinimumBalanceForRentExemption(mintSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer,
newAccount: mint,
lamports: mintRent,
space: mintSpace,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
getInitializeMintInstruction({
mint: mint.address,
decimals: 0,
mintAuthority: client.payer.address,
freezeAuthority: client.payer.address
})
]);

Source Reference

ItemDescriptionSource
CpiGuardAccount extension that stores whether CPI guard is currently enabled for the token account.Source
CpiGuardInstruction::EnableInstruction that enables CPI guard on a token account.Source
CpiGuardInstruction::DisableInstruction that disables CPI guard on a token account.Source
process_toggle_cpi_guardProcessor logic used by Enable and Disable that validates account ownership, rejects CPI changes to the guard itself, and initializes CpiGuard if it is not already present before setting lock_cpi.Source

Typescript

The Kit example below uses the generated instructions directly. Legacy examples using @solana/web3.js and @solana/spl-token are included for reference.

Kit

Instructions
import {
lamports,
createClient,
generateKeyPairSigner,
unwrapOption
} from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import { getCreateAccountInstruction } from "@solana-program/system";
import {
extension,
fetchToken,
getDisableCpiGuardInstruction,
getEnableCpiGuardInstruction,
getInitializeAccountInstruction,
getInitializeMintInstruction,
getMintSize,
getTokenSize,
isExtension,
TOKEN_2022_PROGRAM_ADDRESS
} from "@solana-program/token-2022";
const client = await createClient()
.use(generatedPayer())
.use(
solanaRpc({
rpcUrl: "http://localhost:8899",
rpcSubscriptionsUrl: "ws://localhost:8900"
})
)
.use(rpcAirdrop())
.use(airdropPayer(lamports(1_000_000_000n)));
const mint = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();
const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
.getMinimumBalanceForRentExemption(mintSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer, // Account funding account creation.
newAccount: mint, // New mint account to create.
lamports: mintRent, // Lamports funding the mint account rent.
space: mintSpace, // Account size in bytes for the mint account.
programAddress: TOKEN_2022_PROGRAM_ADDRESS // Program that owns the mint account.
}),
getInitializeMintInstruction({
mint: mint.address, // Mint account to initialize.
decimals: 0, // Number of decimals for the token.
mintAuthority: client.payer.address, // Authority allowed to mint new tokens.
freezeAuthority: client.payer.address // Authority allowed to freeze token accounts.
})
]);
const cpiGuardExtension = extension("CpiGuard", {
lockCpi: false
});
const tokenSpace = BigInt(getTokenSize([cpiGuardExtension]));
const tokenRent = await client.rpc
.getMinimumBalanceForRentExemption(tokenSpace)
.send();
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer, // Account funding account creation.
newAccount: tokenAccount, // New token account to create.
lamports: tokenRent, // Lamports funding the token account rent.
space: tokenSpace, // Account size in bytes for the token account plus CpiGuard.
programAddress: TOKEN_2022_PROGRAM_ADDRESS // Program that owns the token account.
}),
getInitializeAccountInstruction({
account: tokenAccount.address, // Token account to initialize.
mint: mint.address, // Mint for the token account.
owner: client.payer.address // Owner allowed to control the token account.
})
]);
await client.sendTransaction([
getEnableCpiGuardInstruction({
token: tokenAccount.address, // Token account that stores the CpiGuard extension.
owner: client.payer // Token account owner authorized to enable CPI guard.
})
]);
const enabledTokenAccount = await fetchToken(client.rpc, tokenAccount.address);
const enabledCpiGuard = (
unwrapOption(enabledTokenAccount.data.extensions) ?? []
).find((item) => isExtension("CpiGuard", item));
await client.sendTransaction([
getDisableCpiGuardInstruction({
token: tokenAccount.address, // Token account that stores the CpiGuard extension.
owner: client.payer // Token account owner authorized to disable CPI guard.
})
]);
const disabledTokenAccount = await fetchToken(client.rpc, tokenAccount.address);
const disabledCpiGuard = (
unwrapOption(disabledTokenAccount.data.extensions) ?? []
).find((item) => isExtension("CpiGuard", item));
console.log("\nMint Address:", mint.address);
console.log("\nToken Account:", tokenAccount.address);
console.log("\nEnabled CPI Guard:", enabledCpiGuard);
console.log("\nDisabled CPI Guard:", disabledCpiGuard);
Console
Click to execute the code.

Web3.js

Instructions
import {
Connection,
Keypair,
LAMPORTS_PER_SOL,
sendAndConfirmTransaction,
SystemProgram,
Transaction
} from "@solana/web3.js";
import {
createDisableCpiGuardInstruction,
createEnableCpiGuardInstruction,
createInitializeAccountInstruction,
createInitializeMintInstruction,
ExtensionType,
getAccountLen,
getAccount,
getCpiGuard,
getMintLen,
TOKEN_2022_PROGRAM_ID
} from "@solana/spl-token";
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();
const feePayer = Keypair.generate();
const mint = Keypair.generate();
const tokenAccount = Keypair.generate();
const airdropSignature = await connection.requestAirdrop(
feePayer.publicKey,
5 * LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
signature: airdropSignature
});
const mintSpace = getMintLen([]);
const mintRent = await connection.getMinimumBalanceForRentExemption(mintSpace);
await sendAndConfirmTransaction(
connection,
new Transaction().add(
SystemProgram.createAccount({
fromPubkey: feePayer.publicKey, // Account funding account creation.
newAccountPubkey: mint.publicKey, // New mint account to create.
space: mintSpace, // Account size in bytes for the mint account.
lamports: mintRent, // Lamports funding the mint account rent.
programId: TOKEN_2022_PROGRAM_ID // Program that owns the mint account.
}),
createInitializeMintInstruction(
mint.publicKey, // Mint account to initialize.
0, // Number of decimals for the token.
feePayer.publicKey, // Authority allowed to mint new tokens.
feePayer.publicKey, // Authority allowed to freeze token accounts.
TOKEN_2022_PROGRAM_ID // Program that owns the mint account.
)
),
[feePayer, mint],
{ commitment: "confirmed" }
);
const tokenAccountSpace = getAccountLen([ExtensionType.CpiGuard]);
const tokenAccountRent =
await connection.getMinimumBalanceForRentExemption(tokenAccountSpace);
await sendAndConfirmTransaction(
connection,
new Transaction().add(
SystemProgram.createAccount({
fromPubkey: feePayer.publicKey, // Account funding account creation.
newAccountPubkey: tokenAccount.publicKey, // New token account to create.
space: tokenAccountSpace, // Account size in bytes for the token account plus CpiGuard.
lamports: tokenAccountRent, // Lamports funding the token account rent.
programId: TOKEN_2022_PROGRAM_ID // Program that owns the token account.
}),
createInitializeAccountInstruction(
tokenAccount.publicKey, // Token account to initialize.
mint.publicKey, // Mint for the token account.
feePayer.publicKey, // Owner allowed to control the token account.
TOKEN_2022_PROGRAM_ID // Program that owns the token account.
)
),
[feePayer, tokenAccount],
{ commitment: "confirmed" }
);
await sendAndConfirmTransaction(
connection,
new Transaction().add(
createEnableCpiGuardInstruction(
tokenAccount.publicKey, // Token account that stores the CpiGuard extension.
feePayer.publicKey, // Token account owner authorized to enable CPI guard.
[], // Additional multisig signers.
TOKEN_2022_PROGRAM_ID // Token program that owns the token account.
)
),
[feePayer],
{ commitment: "confirmed" }
);
const enabledTokenAccount = await getAccount(
connection,
tokenAccount.publicKey,
"confirmed",
TOKEN_2022_PROGRAM_ID
);
const enabledCpiGuard = getCpiGuard(enabledTokenAccount);
await sendAndConfirmTransaction(
connection,
new Transaction().add(
createDisableCpiGuardInstruction(
tokenAccount.publicKey, // Token account that stores the CpiGuard extension.
feePayer.publicKey, // Token account owner authorized to disable CPI guard.
[], // Additional multisig signers.
TOKEN_2022_PROGRAM_ID // Token program that owns the token account.
)
),
[feePayer],
{ commitment: "confirmed" }
);
const disabledTokenAccount = await getAccount(
connection,
tokenAccount.publicKey,
"confirmed",
TOKEN_2022_PROGRAM_ID
);
const disabledCpiGuard = getCpiGuard(disabledTokenAccount);
console.log("\nMint Address:", mint.publicKey.toBase58());
console.log("\nToken Account:", tokenAccount.publicKey.toBase58());
console.log("\nEnabled CPI Guard:", enabledCpiGuard);
console.log("\nDisabled CPI Guard:", disabledCpiGuard);
Console
Click to execute the code.

Rust

Rust
use anyhow::Result;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_commitment_config::CommitmentConfig;
use solana_sdk::{
program_pack::Pack,
signature::{Keypair, Signer},
transaction::Transaction,
};
use solana_system_interface::instruction::create_account;
use spl_token_2022_interface::{
extension::{
cpi_guard::{
instruction::{disable_cpi_guard, enable_cpi_guard},
CpiGuard,
},
BaseStateWithExtensions, ExtensionType, StateWithExtensions,
},
instruction::{initialize_account, initialize_mint},
state::{Account, Mint},
ID as TOKEN_2022_PROGRAM_ID,
};
#[tokio::main]
async fn main() -> Result<()> {
let client = RpcClient::new_with_commitment(
String::from("http://localhost:8899"),
CommitmentConfig::confirmed(),
);
let fee_payer = Keypair::new();
let airdrop_signature = client
.request_airdrop(&fee_payer.pubkey(), 5_000_000_000)
.await?;
loop {
let confirmed = client.confirm_transaction(&airdrop_signature).await?;
if confirmed {
break;
}
}
let mint = Keypair::new();
let token_account = Keypair::new();
let mint_space = Mint::LEN;
let mint_rent = client
.get_minimum_balance_for_rent_exemption(mint_space)
.await?;
let create_mint_transaction = Transaction::new_signed_with_payer(
&[
create_account(
&fee_payer.pubkey(), // Account funding account creation.
&mint.pubkey(), // New mint account to create.
mint_rent, // Lamports funding the mint account rent.
mint_space as u64, // Account size in bytes for the mint account.
&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.
),
initialize_mint(
&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.
&mint.pubkey(), // Mint account to initialize.
&fee_payer.pubkey(), // Authority allowed to mint new tokens.
Some(&fee_payer.pubkey()), // Authority allowed to freeze token accounts.
0, // Number of decimals for the token.
)?,
],
Some(&fee_payer.pubkey()),
&[&fee_payer, &mint],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&create_mint_transaction)
.await?;
let token_account_space =
ExtensionType::try_calculate_account_len::<Account>(&[ExtensionType::CpiGuard])?;
let token_account_rent = client
.get_minimum_balance_for_rent_exemption(token_account_space)
.await?;
let create_token_account_transaction = Transaction::new_signed_with_payer(
&[
create_account(
&fee_payer.pubkey(), // Account funding account creation.
&token_account.pubkey(), // New token account to create.
token_account_rent, // Lamports funding the token account rent.
token_account_space as u64, // Account size in bytes for the token account plus CpiGuard.
&TOKEN_2022_PROGRAM_ID, // Program that owns the token account.
),
initialize_account(
&TOKEN_2022_PROGRAM_ID, // Program that owns the token account.
&token_account.pubkey(), // Token account to initialize.
&mint.pubkey(), // Mint for the token account.
&fee_payer.pubkey(), // Owner allowed to control the token account.
)?,
],
Some(&fee_payer.pubkey()),
&[&fee_payer, &token_account],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&create_token_account_transaction)
.await?;
let enable_cpi_guard_instruction = enable_cpi_guard(
&TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
&token_account.pubkey(), // Token account that stores the CpiGuard extension.
&fee_payer.pubkey(), // Token account owner authorized to enable CPI guard.
&[], // Additional multisig signers.
)?;
let enable_transaction = Transaction::new_signed_with_payer(
&[enable_cpi_guard_instruction],
Some(&fee_payer.pubkey()),
&[&fee_payer],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&enable_transaction)
.await?;
let enabled_token_account_data = client.get_account(&token_account.pubkey()).await?;
let enabled_token_account_state =
StateWithExtensions::<Account>::unpack(&enabled_token_account_data.data)?;
let enabled_cpi_guard = enabled_token_account_state.get_extension::<CpiGuard>()?;
let disable_cpi_guard_instruction = disable_cpi_guard(
&TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
&token_account.pubkey(), // Token account that stores the CpiGuard extension.
&fee_payer.pubkey(), // Token account owner authorized to disable CPI guard.
&[], // Additional multisig signers.
)?;
let disable_transaction = Transaction::new_signed_with_payer(
&[disable_cpi_guard_instruction],
Some(&fee_payer.pubkey()),
&[&fee_payer],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&disable_transaction)
.await?;
let disabled_token_account_data = client.get_account(&token_account.pubkey()).await?;
let disabled_token_account_state =
StateWithExtensions::<Account>::unpack(&disabled_token_account_data.data)?;
let disabled_cpi_guard = disabled_token_account_state.get_extension::<CpiGuard>()?;
println!("\nMint Address: {}", mint.pubkey());
println!("\nToken Account: {}", token_account.pubkey());
println!("\nEnabled CPI Guard: {:#?}", enabled_cpi_guard);
println!("\nDisabled CPI Guard: {:#?}", disabled_cpi_guard);
Ok(())
}
Console
Click to execute the code.

Is this page helpful?

Table of Contents

Edit Page

Managed by

© 2026 Solana Foundation.
All rights reserved.
Get connected
CPI Guard | Solana