---
title: Set Authority
description:
  Change or revoke authority roles on a mint or token account, including mint,
  freeze, owner, and close authority.
url: /docs/tokens/basics/set-authority
type: tutorial
prerequisites:
  - /docs/tokens/basics/create-mint
  - /docs/tokens/basics/create-token-account
related:
  - /docs/tokens/basics/freeze-account
  - /docs/tokens/basics/close-account
  - /docs/tokens/basics/mint-tokens
  - /docs/tokens/basics/approve-delegate
---

## What Does Setting Authority Do?

Setting authority changes or revokes specific authority roles on a mint or token
account.

Mint accounts can store a mint authority and a freeze authority. Token accounts
store an owner and can optionally store a close authority. Each role controls a
specific permission set, and setting an authority to _rs`None`_ permanently
removes the selected authority role.

The Token Extension Program also defines additional authority types for specific
extensions.

## How to Set Authority

Changing an authority uses the Token Program's _rs`SetAuthority`_ instruction.

Each call updates one authority type on one mint or token account. The current
authority signs the change, and the new authority may be another address or
_rs`None`_ to revoke the selected authority permanently.

### Source Reference

| Item                        | Description                                                                      | Token Program                                                                                                  | Token Extension Program                                                                                                |
| --------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| _rs`Mint`_                  | The mint state stores _rs`mint_authority`_ and _rs`freeze_authority`_.           | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/state.rs#L13-L30)         | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/state.rs#L25-L42)           |
| _rs`Account`_               | The token account state stores _rs`owner`_ and _rs`close_authority`_.            | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/state.rs#L84-L108)        | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/state.rs#L99-L123)          |
| _rs`AuthorityType`_         | The authority roles that _rs`SetAuthority`_ can update.                          | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L739-L751) | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L1116-L1157) |
| _rs`SetAuthority`_          | An instruction that changes or revokes one authority on a mint or token account. | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L141-L158) | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L183-L200)   |
| _rs`process_set_authority`_ | Shared processor logic for authority updates.                                    | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L423-L518)     | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L677-L978)       |

### Typescript

The `Kit` examples below show the recommended approach using `@solana/kit`.
Legacy examples using `@solana/web3.js` are included for reference.

#### Kit

<CodeTabs storage="token-ts-kit" flags="r">

```ts !! title="Plugin"
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import { AuthorityType, tokenProgram } from "@solana-program/token";

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)))
  // !mark[/\.use\(tokenProgram\(\)\)/]
  .use(tokenProgram());

const mint = await generateKeyPairSigner();
const newAuthority = await generateKeyPairSigner();

// !collapse(1:9) collapsed
// Setup: create a mint before changing its authorities.
await client.token.instructions
  .createMint({
    newMint: mint,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
  .sendTransaction();

const result = await client.sendTransaction([
  // !mark(1:12)
  client.token.instructions.setAuthority({
    owned: mint.address, // Mint whose authority changes.
    owner: client.payer, // Current authority approving this change.
    authorityType: AuthorityType.MintTokens, // Authority role to update on the mint.
    newAuthority: newAuthority.address // New authority to assign to this role.
  }),
  client.token.instructions.setAuthority({
    owned: mint.address, // Mint whose authority changes.
    owner: client.payer, // Current authority approving this change.
    authorityType: AuthorityType.FreezeAccount, // Authority role to update on the mint.
    newAuthority: newAuthority.address // New authority to assign to this role.
  })
]);

const mintAccount = await client.token.accounts.mint.fetch(mint.address);

console.log("Mint Address:", mint.address);
console.log("Mint Account:", mintAccount.data);
console.log("\nNew Authority Address:", newAuthority.address);
console.log("\nTransaction Signature:", result.context.signature);
```

```ts !! title="Instructions"
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import {
  AuthorityType,
  fetchMint,
  getCreateMintInstructionPlan,
  getSetAuthorityInstruction
} from "@solana-program/token";

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 newAuthority = await generateKeyPairSigner();

// !collapse(1:10) collapsed
// Setup: create a mint before changing its authorities.
await client.sendTransaction(
  getCreateMintInstructionPlan({
    payer: client.payer,
    newMint: mint,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
);

const result = await client.sendTransaction([
  // !mark(1:12)
  getSetAuthorityInstruction({
    owned: mint.address, // Mint whose authority changes.
    owner: client.payer, // Current authority approving this change.
    authorityType: AuthorityType.MintTokens, // Authority role to update on the mint.
    newAuthority: newAuthority.address // New authority to assign to this role.
  }),
  getSetAuthorityInstruction({
    owned: mint.address, // Mint whose authority changes.
    owner: client.payer, // Current authority approving this change.
    authorityType: AuthorityType.FreezeAccount, // Authority role to update on the mint.
    newAuthority: newAuthority.address // New authority to assign to this role.
  })
]);

const mintAccount = await fetchMint(client.rpc, mint.address);

console.log("Mint Address:", mint.address);
console.log("Mint Account:", mintAccount.data);
console.log("\nNew Authority Address:", newAuthority.address);
console.log("\nTransaction Signature:", result.context.signature);
```

</CodeTabs>

#### Web3.js

<CodeTabs storage="token-ts-legacy" flags="r">

```ts !! title="Helper Function"
import {
  Connection,
  Keypair,
  sendAndConfirmTransaction,
  Transaction,
  LAMPORTS_PER_SOL
} from "@solana/web3.js";
import {
  createMint,
  AuthorityType,
  createSetAuthorityInstruction,
  getMint,
  TOKEN_PROGRAM_ID
} from "@solana/spl-token";

// !collapse(1:29) collapsed
// Setup: create a mint before changing its authorities.
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();

const feePayer = Keypair.generate();
const newAuthority = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const mintPubkey = await createMint(
  connection,
  feePayer,
  feePayer.publicKey,
  feePayer.publicKey,
  2,
  Keypair.generate(),
  {
    commitment: "confirmed"
  },
  TOKEN_PROGRAM_ID
);

const authorityBlockhash = await connection.getLatestBlockhash();
// !mark(1:26)
const result = await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: authorityBlockhash.blockhash,
    lastValidBlockHeight: authorityBlockhash.lastValidBlockHeight
  }).add(
    createSetAuthorityInstruction(
      mintPubkey, // Mint whose authority changes.
      feePayer.publicKey, // Current authority approving this change.
      AuthorityType.MintTokens, // Authority role to update on the mint.
      newAuthority.publicKey, // New authority to assign to this role.
      [], // Additional multisig signers.
      TOKEN_PROGRAM_ID // Token program to invoke.
    ),
    createSetAuthorityInstruction(
      mintPubkey, // Mint whose authority changes.
      feePayer.publicKey, // Current authority approving this change.
      AuthorityType.FreezeAccount, // Authority role to update on the mint.
      newAuthority.publicKey, // New authority to assign to this role.
      [], // Additional multisig signers.
      TOKEN_PROGRAM_ID // Token program to invoke.
    )
  ),
  [feePayer]
);

const mintAccount = await getMint(
  connection,
  mintPubkey,
  "confirmed",
  TOKEN_PROGRAM_ID
);

console.log("Mint Address:", mintPubkey.toBase58());
console.log("Mint Account:", mintAccount);
console.log("\nNew Authority Address:", newAuthority.publicKey.toBase58());
console.log("\nTransaction Signature:", result);
```

```ts !! title="Instructions"
import {
  Connection,
  Keypair,
  sendAndConfirmTransaction,
  SystemProgram,
  Transaction,
  LAMPORTS_PER_SOL
} from "@solana/web3.js";
import {
  createSetAuthorityInstruction,
  createInitializeMintInstruction,
  AuthorityType,
  getMinimumBalanceForRentExemptMint,
  getMint,
  MINT_SIZE,
  TOKEN_PROGRAM_ID
} from "@solana/spl-token";

// !collapse(1:45) collapsed
// Setup: create a mint before changing its authorities.
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();

const feePayer = Keypair.generate();
const newAuthority = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const mint = Keypair.generate();
const mintRent = await getMinimumBalanceForRentExemptMint(connection);
await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: latestBlockhash.blockhash,
    lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
  }).add(
    SystemProgram.createAccount({
      fromPubkey: feePayer.publicKey,
      newAccountPubkey: mint.publicKey,
      space: MINT_SIZE,
      lamports: mintRent,
      programId: TOKEN_PROGRAM_ID
    }),
    createInitializeMintInstruction(
      mint.publicKey,
      2,
      feePayer.publicKey,
      feePayer.publicKey,
      TOKEN_PROGRAM_ID
    )
  ),
  [feePayer, mint]
);

const authorityBlockhash = await connection.getLatestBlockhash();

const result = await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: authorityBlockhash.blockhash,
    lastValidBlockHeight: authorityBlockhash.lastValidBlockHeight
  }).add(
    // !mark(1:16)
    createSetAuthorityInstruction(
      mint.publicKey, // Mint whose authority changes.
      feePayer.publicKey, // Current authority approving this change.
      AuthorityType.MintTokens, // Authority role to update on the mint.
      newAuthority.publicKey, // New authority to assign to this role.
      [], // Additional multisig signers.
      TOKEN_PROGRAM_ID // Token program to invoke.
    ),
    createSetAuthorityInstruction(
      mint.publicKey, // Mint whose authority changes.
      feePayer.publicKey, // Current authority approving this change.
      AuthorityType.FreezeAccount, // Authority role to update on the mint.
      newAuthority.publicKey, // New authority to assign to this role.
      [], // Additional multisig signers.
      TOKEN_PROGRAM_ID // Token program to invoke.
    )
  ),
  [feePayer]
);

const mintAccount = await getMint(
  connection,
  mint.publicKey,
  "confirmed",
  TOKEN_PROGRAM_ID
);

console.log("Mint Address:", mint.publicKey.toBase58());
console.log("Mint Account:", mintAccount);
console.log("\nNew Authority Address:", newAuthority.publicKey.toBase58());
console.log("\nTransaction Signature:", result);
```

</CodeTabs>

### Rust

<CodeTabs storage="token-rs" flags="r">

```rust !! title="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_interface::{
    id as token_program_id,
    instruction::{initialize_mint, set_authority, AuthorityType},
    state::Mint,
};

#[tokio::main]
async fn main() -> Result<()> {
    let client = RpcClient::new_with_commitment(
        String::from("http://localhost:8899"),
        CommitmentConfig::confirmed(),
    );
    let new_authority = Keypair::new();

    // !collapse(1:42) collapsed
    // Setup: create a mint before changing its authorities.
    let fee_payer = Keypair::new();

    let airdrop_signature = client
        .request_airdrop(&fee_payer.pubkey(), 1_000_000_000)
        .await?;
    loop {
        let confirmed = client.confirm_transaction(&airdrop_signature).await?;
        if confirmed {
            break;
        }
    }

    let mint = Keypair::new();
    let mint_rent = client
        .get_minimum_balance_for_rent_exemption(Mint::LEN)
        .await?;
    let latest_blockhash = client.get_latest_blockhash().await?;
    let setup_transaction = Transaction::new_signed_with_payer(
        &[
            create_account(
                &fee_payer.pubkey(),
                &mint.pubkey(),
                mint_rent,
                Mint::LEN as u64,
                &token_program_id(),
            ),
            initialize_mint(
                &token_program_id(),
                &mint.pubkey(),
                &fee_payer.pubkey(),
                Some(&fee_payer.pubkey()),
                2,
            )?,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &mint],
        latest_blockhash,
    );
    client
        .send_and_confirm_transaction(&setup_transaction)
        .await?;

    let transaction = Transaction::new_signed_with_payer(
        &[
            // !mark(1:16)
            set_authority(
                &token_program_id(), // Token program to invoke.
                &mint.pubkey(), // Mint whose authority changes.
                Some(&new_authority.pubkey()), // New authority to assign to this role.
                AuthorityType::MintTokens, // Authority role to update on the mint.
                &fee_payer.pubkey(), // Current authority approving this change.
                &[], // Additional multisig signers.
            )?,
            set_authority(
                &token_program_id(), // Token program to invoke.
                &mint.pubkey(), // Mint whose authority changes.
                Some(&new_authority.pubkey()), // New authority to assign to this role.
                AuthorityType::FreezeAccount, // Authority role to update on the mint.
                &fee_payer.pubkey(), // Current authority approving this change.
                &[], // Additional multisig signers.
            )?,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer],
        latest_blockhash,
    );

    let transaction_signature = client.send_and_confirm_transaction(&transaction).await?;
    let mint_account = client.get_account(&mint.pubkey()).await?;
    let mint_data = Mint::unpack(&mint_account.data)?;

    println!("Mint Address: {}", mint.pubkey());
    println!("Mint Account: {:#?}", mint_data);
    println!("\nNew Authority Address: {}", new_authority.pubkey());
    println!("\nTransaction Signature: {}", transaction_signature);

    Ok(())
}
```

</CodeTabs>

### Python

<CodeTabs flags="r">

```py !! title="Python"
#!/usr/bin/env python3

import asyncio
import json
from solana.rpc.async_api import AsyncClient
from solders.keypair import Keypair
from solders.message import Message
from solders.pubkey import Pubkey
from solders.system_program import create_account, CreateAccountParams
from solders.transaction import Transaction
from spl.token.async_client import AsyncToken
from spl.token.instructions import (
    AuthorityType,
    initialize_mint,
    InitializeMintParams,
    set_authority,
    SetAuthorityParams,
)
from spl.token.constants import MINT_LEN, TOKEN_PROGRAM_ID

async def main():
    rpc = AsyncClient("http://localhost:8899")

    new_authority = Keypair()

    async with rpc:
        # !collapse(1:18) collapsed
        # Setup: create a mint before changing the mint authority.
        fee_payer = Keypair()
        airdrop_signature = (await rpc.request_airdrop(fee_payer.pubkey(), 1_000_000_000)).value
        await rpc.confirm_transaction(airdrop_signature)
        mint = Keypair()
        mint_rent = (await rpc.get_minimum_balance_for_rent_exemption(MINT_LEN)).value
        setup_instructions = [
            create_account(CreateAccountParams(from_pubkey=fee_payer.pubkey(), to_pubkey=mint.pubkey(), lamports=mint_rent, space=MINT_LEN, owner=TOKEN_PROGRAM_ID)),
            initialize_mint(InitializeMintParams(decimals=2, program_id=TOKEN_PROGRAM_ID, mint=mint.pubkey(), mint_authority=fee_payer.pubkey())),
        ]
        setup_blockhash = await rpc.get_latest_blockhash()
        setup_transaction = Transaction(
            [fee_payer, mint],
            Message(setup_instructions, fee_payer.pubkey()),
            setup_blockhash.value.blockhash,
        )
        await rpc.send_transaction(setup_transaction)
        token = AsyncToken(rpc, mint.pubkey(), TOKEN_PROGRAM_ID, fee_payer)

        # !mark(1:9)
        set_authority_instruction = set_authority(
            SetAuthorityParams(
                program_id=TOKEN_PROGRAM_ID,  # Token program to invoke.
                account=mint.pubkey(),  # Mint whose authority changes.
                authority=AuthorityType.MINT_TOKENS,  # Authority role to update.
                current_authority=fee_payer.pubkey(),  # Current authority approving the authority update.
                new_authority=new_authority.pubkey(),  # New authority for the selected role.
            )
        )
        latest_blockhash = await rpc.get_latest_blockhash()
        transaction = Transaction(
            [fee_payer],
            Message([set_authority_instruction], fee_payer.pubkey()),
            latest_blockhash.value.blockhash,
        )
        result = await rpc.send_transaction(transaction)

        mint_info = await token.get_mint_info()
        mint_account = {
            key: str(value) if isinstance(value, Pubkey) else value
            for key, value in mint_info._asdict().items()
        }

        print("Mint Address:", mint.pubkey())
        print("Mint Account:")
        print(json.dumps(mint_account, indent=2))
        print("\nNew Authority Address:", new_authority.pubkey())
        print("\nTransaction Signature:", result.value)

if __name__ == "__main__":
    asyncio.run(main())
```

</CodeTabs>
