Pausable Mint

What Is a Pausable Mint?

The Token Extension Program's PausableConfig mint extension gives a pause authority the ability to pause and resume token activity for the entire mint.

When a mint is paused, the Token Extension Program rejects:

  • Transfers
  • Mints
  • Burns

When the mint is resumed, those instructions work normally again.

How to Create, Pause, and Resume a Mint

To create, pause, and resume a mint:

  1. Calculate the mint account size and rent needed for the mint and the PausableConfig extension.
  2. Create the mint account with CreateAccount, initialize PausableConfig, and initialize the mint with InitializeMint.
  3. Mint tokens and create token accounts for the mint.
  4. Use Pause to block token activity for the mint.
  5. Use Resume to allow token activity again.

Calculate account size

Calculate the mint account size for the base mint plus the PausableConfig 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 recipient = await generateKeyPairSigner();
const pausableExtension = extension("PausableConfig", {
authority: client.payer.address,
paused: false
});
const mintSpace = BigInt(getMintSize([pausableExtension]));

Calculate rent

Calculate rent using the size needed for the mint plus the PausableConfig 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 recipient = await generateKeyPairSigner();
const pausableExtension = extension("PausableConfig", {
authority: client.payer.address,
paused: false
});
const mintSpace = BigInt(getMintSize([pausableExtension]));
const mintRent = await client.rpc
.getMinimumBalanceForRentExemption(mintSpace)
.send();

Create the mint account

Create the mint account with the calculated space and lamports.

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 recipient = await generateKeyPairSigner();
const pausableExtension = extension("PausableConfig", {
authority: client.payer.address,
paused: false
});
const mintSpace = BigInt(getMintSize([pausableExtension]));
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
})
]);

Initialize PausableConfig

Initialize the PausableConfig extension on 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 recipient = await generateKeyPairSigner();
const pausableExtension = extension("PausableConfig", {
authority: client.payer.address,
paused: false
});
const mintSpace = BigInt(getMintSize([pausableExtension]));
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
}),
getInitializePausableConfigInstruction({
mint: mint.address,
authority: client.payer.address
})
]);

Initialize the mint

Initialize the mint with InitializeMint in the same transaction.

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 recipient = await generateKeyPairSigner();
const pausableExtension = extension("PausableConfig", {
authority: client.payer.address,
paused: false
});
const mintSpace = BigInt(getMintSize([pausableExtension]));
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
}),
getInitializePausableConfigInstruction({
mint: mint.address,
authority: client.payer.address
}),
getInitializeMintInstruction({
mint: mint.address,
decimals: 0,
mintAuthority: client.payer.address,
freezeAuthority: client.payer.address
})
]);

Pause the mint

Pause the mint with Pause.

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 recipient = await generateKeyPairSigner();
const pausableExtension = extension("PausableConfig", {
authority: client.payer.address,
paused: false
});
const mintSpace = BigInt(getMintSize([pausableExtension]));
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
}),
getInitializePausableConfigInstruction({
mint: mint.address,
authority: client.payer.address
}),
getInitializeMintInstruction({
mint: mint.address,
decimals: 0,
mintAuthority: client.payer.address,
freezeAuthority: client.payer.address
})
]);
await client.sendTransaction([
getPauseInstruction({
mint: mint.address,
authority: client.payer
})
]);

Resume the mint

Resume the mint with Resume.

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 recipient = await generateKeyPairSigner();
const pausableExtension = extension("PausableConfig", {
authority: client.payer.address,
paused: false
});
const mintSpace = BigInt(getMintSize([pausableExtension]));
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
}),
getInitializePausableConfigInstruction({
mint: mint.address,
authority: client.payer.address
}),
getInitializeMintInstruction({
mint: mint.address,
decimals: 0,
mintAuthority: client.payer.address,
freezeAuthority: client.payer.address
})
]);
await client.sendTransaction([
getPauseInstruction({
mint: mint.address,
authority: client.payer
})
]);
await client.sendTransaction([
getResumeInstruction({
mint: mint.address,
authority: client.payer
})
]);

Calculate account size

Calculate the mint account size for the base mint plus the PausableConfig extension. This is the size used in CreateAccount.

Calculate rent

Calculate rent using the size needed for the mint plus the PausableConfig extension.

Create the mint account

Create the mint account with the calculated space and lamports.

Initialize PausableConfig

Initialize the PausableConfig extension on the mint.

Initialize the mint

Initialize the mint with InitializeMint in the same transaction.

Pause the mint

Pause the mint with Pause.

Resume the mint

Resume the mint with Resume.

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 recipient = await generateKeyPairSigner();
const pausableExtension = extension("PausableConfig", {
authority: client.payer.address,
paused: false
});
const mintSpace = BigInt(getMintSize([pausableExtension]));

Instruction Order

PausableInstruction::Initialize must come before InitializeMint. CreateAccount, PausableInstruction::Initialize, and InitializeMint must be included in the same transaction.

Source Reference

ItemDescriptionSource
PausableConfigMint extension that stores the pause authority and whether the mint is currently paused.Source
PausableInstruction::InitializeInstruction that initializes the pausable config before InitializeMint.Source
PausableInstruction::PauseInstruction that marks the mint as paused.Source
PausableInstruction::ResumeInstruction that marks the mint as unpaused.Source
process_initializeProcessor logic that initializes PausableConfig on an uninitialized mint and stores the pause authority.Source
process_toggle_pauseProcessor logic that verifies the pause authority before toggling the mint's paused flag.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,
fetchMint,
findAssociatedTokenPda,
getCreateAssociatedTokenInstructionAsync,
getInitializeMintInstruction,
getInitializePausableConfigInstruction,
getMintSize,
getMintToCheckedInstruction,
getPauseInstruction,
getResumeInstruction,
getTransferCheckedInstruction,
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 recipient = await generateKeyPairSigner();
const pausableExtension = extension("PausableConfig", {
authority: client.payer.address,
paused: false
});
const mintSpace = BigInt(getMintSize([pausableExtension]));
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 plus PausableConfig.
programAddress: TOKEN_2022_PROGRAM_ADDRESS // Program that owns the mint account.
}),
getInitializePausableConfigInstruction({
mint: mint.address, // Mint account that stores the PausableConfig extension.
authority: client.payer.address // Authority allowed to pause and resume the mint.
}),
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 [sourceToken] = await findAssociatedTokenPda({
mint: mint.address,
owner: client.payer.address,
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
const [destinationToken] = await findAssociatedTokenPda({
mint: mint.address,
owner: recipient.address,
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
await client.sendTransaction([
await getCreateAssociatedTokenInstructionAsync({
payer: client.payer, // Account funding the associated token account creation.
mint: mint.address, // Mint for the associated token account.
owner: client.payer.address // Owner of the associated token account.
}),
await getCreateAssociatedTokenInstructionAsync({
payer: client.payer, // Account funding the associated token account creation.
mint: mint.address, // Mint for the associated token account.
owner: recipient.address // Owner of the associated token account.
}),
getMintToCheckedInstruction({
mint: mint.address, // Mint account that issues the tokens.
token: sourceToken, // Token account receiving the newly minted tokens.
mintAuthority: client.payer, // Signer authorized to mint new tokens.
amount: 1n, // Token amount in base units.
decimals: 0 // Decimals defined on the mint.
})
]);
await client.sendTransaction([
getPauseInstruction({
mint: mint.address, // Mint account to pause.
authority: client.payer // Signer authorized to pause the mint.
})
]);
const mintAccountAfterPause = await fetchMint(client.rpc, mint.address);
const configAfterPause = (
unwrapOption(mintAccountAfterPause.data.extensions) ?? []
).find((item) => isExtension("PausableConfig", item));
let pausedTransferFailure: string | undefined;
try {
await client.sendTransaction([
getTransferCheckedInstruction({
source: sourceToken, // Token account sending the transfer.
mint: mint.address, // Mint with the pausable configuration.
destination: destinationToken, // Token account receiving the transfer.
authority: client.payer, // Signer approving the transfer.
amount: 1n, // Token amount in base units.
decimals: 0 // Decimals defined on the mint.
})
]);
} catch (error) {
pausedTransferFailure =
error instanceof Error ? error.message : String(error);
}
if (!pausedTransferFailure) {
throw new Error("Expected the paused transfer to fail");
}
await client.sendTransaction([
getResumeInstruction({
mint: mint.address, // Mint account to resume.
authority: client.payer // Signer authorized to resume the mint.
})
]);
await client.sendTransaction([
getTransferCheckedInstruction({
source: sourceToken, // Token account sending the transfer.
mint: mint.address, // Mint with the pausable configuration.
destination: destinationToken, // Token account receiving the transfer.
authority: client.payer, // Signer approving the transfer.
amount: 1n, // Token amount in base units.
decimals: 0 // Decimals defined on the mint.
})
]);
const mintAccountAfterResume = await fetchMint(client.rpc, mint.address);
const configAfterResume = (
unwrapOption(mintAccountAfterResume.data.extensions) ?? []
).find((item) => isExtension("PausableConfig", item));
console.log("\nMint Address:", mint.address);
console.log("\nConfig After Pause:", configAfterPause);
console.log("\nError From Failed Transaction:", pausedTransferFailure);
console.log("\nConfig After Resume:", configAfterResume);
Console
Click to execute the code.

Web3.js

Instructions
import {
Connection,
Keypair,
LAMPORTS_PER_SOL,
sendAndConfirmTransaction,
SystemProgram,
Transaction
} from "@solana/web3.js";
import {
ASSOCIATED_TOKEN_PROGRAM_ID,
createAssociatedTokenAccountInstruction,
createInitializeMintInstruction,
createInitializePausableConfigInstruction,
createMintToCheckedInstruction,
createPauseInstruction,
createResumeInstruction,
createTransferCheckedInstruction,
ExtensionType,
getAssociatedTokenAddressSync,
getMint,
getMintLen,
getPausableConfig,
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 recipient = 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([ExtensionType.PausableConfig]);
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 plus PausableConfig.
lamports: mintRent, // Lamports funding the mint account rent.
programId: TOKEN_2022_PROGRAM_ID // Program that owns the mint account.
}),
createInitializePausableConfigInstruction(
mint.publicKey, // Mint account that stores the PausableConfig extension.
feePayer.publicKey, // Authority allowed to pause and resume the mint.
TOKEN_2022_PROGRAM_ID // Token program that owns the mint.
),
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 sourceToken = getAssociatedTokenAddressSync(
mint.publicKey,
feePayer.publicKey,
false,
TOKEN_2022_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID
);
const destinationToken = getAssociatedTokenAddressSync(
mint.publicKey,
recipient.publicKey,
false,
TOKEN_2022_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID
);
await sendAndConfirmTransaction(
connection,
new Transaction().add(
createAssociatedTokenAccountInstruction(
feePayer.publicKey, // Account funding the associated token account creation.
sourceToken, // Associated token account address to create.
feePayer.publicKey, // Owner of the associated token account.
mint.publicKey, // Mint for the associated token account.
TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
ASSOCIATED_TOKEN_PROGRAM_ID // Associated Token Program that creates the account.
),
createAssociatedTokenAccountInstruction(
feePayer.publicKey, // Account funding the associated token account creation.
destinationToken, // Associated token account address to create.
recipient.publicKey, // Owner of the associated token account.
mint.publicKey, // Mint for the associated token account.
TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
ASSOCIATED_TOKEN_PROGRAM_ID // Associated Token Program that creates the account.
),
createMintToCheckedInstruction(
mint.publicKey, // Mint account that issues the tokens.
sourceToken, // Token account receiving the newly minted tokens.
feePayer.publicKey, // Signer authorized to mint new tokens.
1, // Token amount in base units.
0, // Decimals defined on the mint.
[], // Additional multisig signers.
TOKEN_2022_PROGRAM_ID // Token program that owns the mint and token account.
)
),
[feePayer],
{ commitment: "confirmed" }
);
await sendAndConfirmTransaction(
connection,
new Transaction().add(
createPauseInstruction(
mint.publicKey, // Mint account to pause.
feePayer.publicKey, // Authority allowed to pause the mint.
[], // Additional multisig signers.
TOKEN_2022_PROGRAM_ID // Token program that owns the mint.
)
),
[feePayer],
{ commitment: "confirmed" }
);
const mintAccountAfterPause = await getMint(
connection,
mint.publicKey,
"confirmed",
TOKEN_2022_PROGRAM_ID
);
const configAfterPause = getPausableConfig(mintAccountAfterPause);
let pausedTransferFailure: string | undefined;
try {
await sendAndConfirmTransaction(
connection,
new Transaction().add(
createTransferCheckedInstruction(
sourceToken, // Token account sending the transfer.
mint.publicKey, // Mint with the pausable configuration.
destinationToken, // Token account receiving the transfer.
feePayer.publicKey, // Signer approving the transfer.
1, // Token amount in base units.
0, // Decimals defined on the mint.
[], // Additional multisig signers.
TOKEN_2022_PROGRAM_ID // Token program that processes the transfer.
)
),
[feePayer],
{ commitment: "confirmed" }
);
} catch (error: any) {
pausedTransferFailure =
error instanceof Error ? error.message : String(error);
}
if (!pausedTransferFailure) {
throw new Error("Expected the paused transfer to fail");
}
await sendAndConfirmTransaction(
connection,
new Transaction().add(
createResumeInstruction(
mint.publicKey, // Mint account to resume.
feePayer.publicKey, // Authority allowed to resume the mint.
[], // Additional multisig signers.
TOKEN_2022_PROGRAM_ID // Token program that owns the mint.
)
),
[feePayer],
{ commitment: "confirmed" }
);
await sendAndConfirmTransaction(
connection,
new Transaction().add(
createTransferCheckedInstruction(
sourceToken, // Token account sending the transfer.
mint.publicKey, // Mint with the pausable configuration.
destinationToken, // Token account receiving the transfer.
feePayer.publicKey, // Signer approving the transfer.
1, // Token amount in base units.
0, // Decimals defined on the mint.
[], // Additional multisig signers.
TOKEN_2022_PROGRAM_ID // Token program that processes the transfer.
)
),
[feePayer],
{ commitment: "confirmed" }
);
const mintAccountAfterResume = await getMint(
connection,
mint.publicKey,
"confirmed",
TOKEN_2022_PROGRAM_ID
);
const configAfterResume = getPausableConfig(mintAccountAfterResume);
console.log("\nMint Address:", mint.publicKey.toBase58());
console.log("\nConfig After Pause:", configAfterPause);
console.log("\nError From Failed Transaction:", pausedTransferFailure);
console.log("\nConfig After Resume:", configAfterResume);
Console
Click to execute the code.

Rust

Rust
use anyhow::{anyhow, Result};
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_commitment_config::CommitmentConfig;
use solana_sdk::{
signature::{Keypair, Signer},
transaction::Transaction,
};
use solana_system_interface::instruction::create_account;
use spl_associated_token_account_interface::{
address::get_associated_token_address_with_program_id,
instruction::create_associated_token_account,
};
use spl_token_2022_interface::{
extension::{
pausable::{instruction as pausable_ix, PausableConfig},
BaseStateWithExtensions, ExtensionType, StateWithExtensions,
},
instruction::{initialize_mint, mint_to_checked, transfer_checked},
state::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 recipient = Keypair::new();
let mint_space = ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::Pausable])?;
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 plus PausableConfig.
&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.
),
pausable_ix::initialize(
&TOKEN_2022_PROGRAM_ID, // Token program that owns the mint.
&mint.pubkey(), // Mint account that stores the PausableConfig extension.
&fee_payer.pubkey(), // Authority allowed to pause and resume the mint.
)?,
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 source_token = get_associated_token_address_with_program_id(
&fee_payer.pubkey(),
&mint.pubkey(),
&TOKEN_2022_PROGRAM_ID,
);
let destination_token = get_associated_token_address_with_program_id(
&recipient.pubkey(),
&mint.pubkey(),
&TOKEN_2022_PROGRAM_ID,
);
let create_token_accounts_transaction = Transaction::new_signed_with_payer(
&[
create_associated_token_account(
&fee_payer.pubkey(), // Account funding the associated token account creation.
&fee_payer.pubkey(), // Owner of the associated token account.
&mint.pubkey(), // Mint for the associated token account.
&TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
),
create_associated_token_account(
&fee_payer.pubkey(), // Account funding the associated token account creation.
&recipient.pubkey(), // Owner of the associated token account.
&mint.pubkey(), // Mint for the associated token account.
&TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
),
mint_to_checked(
&TOKEN_2022_PROGRAM_ID, // Token program that owns the mint and token account.
&mint.pubkey(), // Mint account that issues the tokens.
&source_token, // Token account receiving the newly minted tokens.
&fee_payer.pubkey(), // Signer authorized to mint new tokens.
&[&fee_payer.pubkey()], // Additional multisig signers.
1, // Token amount in base units.
0, // Decimals defined on the mint.
)?,
],
Some(&fee_payer.pubkey()),
&[&fee_payer],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&create_token_accounts_transaction)
.await?;
let pause_ix = pausable_ix::pause(
&TOKEN_2022_PROGRAM_ID, // Token program that owns the mint.
&mint.pubkey(), // Mint account to pause.
&fee_payer.pubkey(), // Authority allowed to pause the mint.
&[&fee_payer.pubkey()], // Additional multisig signers.
)?;
let pause_transaction = Transaction::new_signed_with_payer(
&[pause_ix],
Some(&fee_payer.pubkey()),
&[&fee_payer],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&pause_transaction)
.await?;
let mint_data_after_pause = client.get_account(&mint.pubkey()).await?;
let mint_state_after_pause =
StateWithExtensions::<Mint>::unpack(&mint_data_after_pause.data)?;
let config_after_pause = mint_state_after_pause.get_extension::<PausableConfig>()?;
let transfer_ix = transfer_checked(
&TOKEN_2022_PROGRAM_ID, // Token program that processes the transfer.
&source_token, // Token account sending the transfer.
&mint.pubkey(), // Mint with the pausable configuration.
&destination_token, // Token account receiving the transfer.
&fee_payer.pubkey(), // Signer approving the transfer.
&[&fee_payer.pubkey()], // Additional multisig signers.
1, // Token amount in base units.
0, // Decimals defined on the mint.
)?;
let paused_transfer_transaction = Transaction::new_signed_with_payer(
&[transfer_ix.clone()],
Some(&fee_payer.pubkey()),
&[&fee_payer],
client.get_latest_blockhash().await?,
);
let paused_transfer_result = client.simulate_transaction(&paused_transfer_transaction).await?;
let paused_transfer_failure = paused_transfer_result
.value
.err
.ok_or_else(|| anyhow!("Expected the paused transfer to fail"))?;
let resume_ix = pausable_ix::resume(
&TOKEN_2022_PROGRAM_ID, // Token program that owns the mint.
&mint.pubkey(), // Mint account to resume.
&fee_payer.pubkey(), // Authority allowed to resume the mint.
&[&fee_payer.pubkey()], // Additional multisig signers.
)?;
let resume_transaction = Transaction::new_signed_with_payer(
&[resume_ix],
Some(&fee_payer.pubkey()),
&[&fee_payer],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&resume_transaction)
.await?;
let transfer_transaction = Transaction::new_signed_with_payer(
&[
transfer_checked(
&TOKEN_2022_PROGRAM_ID, // Token program that processes the transfer.
&source_token, // Token account sending the transfer.
&mint.pubkey(), // Mint with the pausable configuration.
&destination_token, // Token account receiving the transfer.
&fee_payer.pubkey(), // Signer approving the transfer.
&[&fee_payer.pubkey()], // Additional multisig signers.
1, // Token amount in base units.
0, // Decimals defined on the mint.
)?,
],
Some(&fee_payer.pubkey()),
&[&fee_payer],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&transfer_transaction)
.await?;
let mint_data_after_resume = client.get_account(&mint.pubkey()).await?;
let mint_state_after_resume =
StateWithExtensions::<Mint>::unpack(&mint_data_after_resume.data)?;
let config_after_resume = mint_state_after_resume.get_extension::<PausableConfig>()?;
println!("\nMint Address: {}", mint.pubkey());
println!("\nConfig After Pause: {:#?}", config_after_pause);
println!("\nError From Failed Transaction: {:?}", paused_transfer_failure);
println!("\nConfig After Resume: {:#?}", config_after_resume);
Ok(())
}
Console
Click to execute the code.

Is this page helpful?

Table of Contents

Edit Page
© 2026 Solana Foundation. All rights reserved.