How to Secure a Solana NFT Collection - Updating and Revoking Authorities
Terminology
- Mint Authority: Grants the ability to mint more tokens of an asset (irrelevant for NFTs, as they have a fixed supply of 1).
- Freeze Authority: Allows an account to freeze and unfreeze assets, restricting their movement.
- Update Authority (UA): The wallet that has permission to modify an NFT’s metadata.
- Revoking Authority: The act of permanently removing control from any wallet to ensure security.
- Liquidity Pool (LP): A decentralized reserve of tokens that facilitates trading.
Introduction
In our previous article, we covered updating NFT metadata, migrating update authorities, and adjusting royalty share structures. If you haven't read it yet, I highly recommend checking it out: How to DeRug a Solana NFT Collection - Updating NFT Authority.
Now, let's dive deeper into another critical aspect of securing an NFT or token collection: updating and revoking the Mint Authority and Freeze Authority.
These authorities are crucial when dealing with SFTs (Semi-Fungible Tokens) and fungible tokens, as they can impact liquidity, security, and token economics.
Why Revoking Authorities Matters
For a token or NFT collection to be considered trustworthy, these authorities must be properly managed. A well-known practice in legitimate projects is burning the Mint & Freeze Authorities, meaning no one can mint extra tokens or freeze assets arbitrarily.
A Real-World Example
Imagine a liquidity pool with 100 tokens and $100 in liquidity. This means each token is worth $1. Now, if someone mints 100 billion more tokens for themselves, the token supply becomes 100,000,000,100, while the liquidity pool remains at $100. This person now owns nearly 100% of the supply and can drain the liquidity pool, rendering the token worthless.
Revoking these authorities ensures that such exploits are impossible, maintaining fairness and stability in the ecosystem.
Updating Authorities on Solana
To manage these authorities, we'll use Metaplex's mpl-toolbox, which provides a setAuthority function to update or revoke permissions.
Here, we'll build two transactions:
- Updating the Mint Authority
- Updating the Freeze Authority
Code Implementation
Setting New Authorities
let builder = await setAuthority(umi, {
authorityType: AuthorityType.MintTokens,
newAuthority: newAuthority,
owned: itemMint,
owner: umi.identity.publicKey,
}).add(
setAuthority(umi, {
authorityType: AuthorityType.FreezeAccount,
newAuthority: newAuthority,
owned: itemMint,
owner: umi.identity.publicKey,
})
);
builder = await builder.setLatestBlockhash(umi, { commitment: "confirmed" });
const tx = await builder.sendAndConfirm(umi);
Explanation of Parameters:
-
authorityType
: Specifies which authority to update (Mint or Freeze Authority). -
newAuthority
: New owner’s public key. Set to null if you want to revoke the authority permanently. -
owned
: Mint address of the asset to update. -
owner
: The current authority owner’s public key.
Automating Authority Updates for Multiple Assets
To update a collection of SFTs, we need to retrieve and process them dynamically. Below is a script that:
- Loads all SFTs belonging to a specific collection.
- Updates their Mint & Freeze Authorities.
- Skips assets that are already updated.
import bs58 from "bs58";
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
import { mplCore } from "@metaplex-foundation/mpl-core";
import { createSignerFromKeypair, publicKey, signerIdentity } from "@metaplex-foundation/umi";
import dotenv from "dotenv";
import { AuthorityType, setAuthority } from "@metaplex-foundation/mpl-toolbox";
import { fetchAllDigitalAssetByUpdateAuthority, fetchDigitalAsset } from "@metaplex-foundation/mpl-token-metadata";
dotenv.config();
async function migrateSFTsAuthorities() {
const privateKey = process.env.OLD_UA_SECRET_KEY as string;
const umi = createUmi(process.env.RPC as string, "confirmed").use(mplCore());
const signer = umi.eddsa.createKeypairFromSecretKey(bs58.decode(privateKey));
umi.use(signerIdentity(createSignerFromKeypair(umi, signer)));
const newAuthority = publicKey("PUBLIC_KEY");
const collectionKey = publicKey("COLLECTION_KEY");
const assets = await fetchAllDigitalAssetByUpdateAuthority(umi, signer.publicKey);
const filteredAssets = assets.filter(
(el) => el.metadata.collection.__option === "Some" &&
el.metadata.collection.value.key === collectionKey &&
el.publicKey !== collectionKey
);
console.log(`Total assets: ${filteredAssets.length}`);
for (let i = 0; i < filteredAssets.length; i++) {
const asset = await fetchDigitalAsset(umi, publicKey(filteredAssets[i]));
const itemMint = filteredAssets[i].publicKey;
if (
asset.mint.mintAuthority.__option === "Some" &&
asset.mint.freezeAuthority.__option === "Some" &&
asset.mint.mintAuthority.value.toString() === newAuthority.toString() &&
asset.mint.freezeAuthority.value.toString() === newAuthority.toString()
) {
console.log(`#${i} is already updated`);
return;
}
console.log(`Handling i: ${i}, mint: ${itemMint.toString()}`);
let builder = await setAuthority(umi, {
authorityType: AuthorityType.MintTokens,
newAuthority: newAuthority,
owned: itemMint,
owner: umi.identity.publicKey,
}).add(
setAuthority(umi, {
authorityType: AuthorityType.FreezeAccount,
newAuthority: newAuthority,
owned: itemMint,
owner: umi.identity.publicKey,
})
);
builder = await builder.setLatestBlockhash(umi, { commitment: "confirmed" });
const tx = await builder.sendAndConfirm(umi);
if (tx.result.value.err) throw new Error(tx.result.value.err.toString());
console.log(`Success #${i}`, tx);
}
}
migrateSFTsAuthorities().catch((err) => console.error(err));
Summary
- Mint & Freeze Authorities play a vital role in asset security.
- Revoking them prevents supply manipulation and freezing exploits.
- Using Metaplex's mpl-toolbox, we can update or revoke authorities.
- Automating the process ensures large collections are updated efficiently.
Conclusion
By properly securing the authorities of your NFTs and tokens, you can prevent exploits and reinforce trust in your project. If you're working with a Solana-based collection, taking these steps is essential for security and decentralization.
If you have any questions or need further help, feel free to reach out on X or GitHub.
Top comments (0)