Mint NFTs (CIP-68)

An overview of how to mint CIP-68 compliant NFTs and other native assets on Cardano using the Anvil API

What is CIP-68?

Cardano Improvement Proposal 68 (CIP-68) defines a way to mint native assets whose metadata can be updated after issuance. By storing the metadata on-chain and linking it to each token, creators can evolve NFTs—such as game items or collectibles—without burning and re-minting them.

How It Works

CIP-68 uses a dual-token system to achieve this functionality:

  1. Reference Token (label: 100): This token holds the asset's metadata within an on-chain wallet (or smart contract script address).

  2. User Token (label: 222): This is the actual token held in a user's wallet. It acts as a pointer to the Reference Token and inherits its metadata.

Because the metadata lives with the Reference Token, creators can update an asset’s metadata simply by modifying that single token—no need to re-mint or burn the user-facing token.

Validation Approaches: Native Scripts vs. Smart Contracts

CIP-68's updatable metadata is managed by a Reference Token, which can be secured in two ways:

  1. Metadata-Manager Wallet with a Native Script: This approach uses a standard wallet and a native script to control the Reference Token. It's straightforward and low-cost, making it ideal for projects that don't need complex on-chain logic. The trade-off is that it relies on trusting the wallet owner to manage metadata updates and token supply correctly.

  2. Smart Contract (Plutus/Aiken): This method uses a full smart contract to govern the Reference Token. While someone still needs to trigger updates, the smart contract validates critical aspects like supply limits and reference token to user token ratios on-chain, requiring less trust than the wallet approach. It enables complex rules for metadata updates, supply caps, and other on-chain logic, but is more complex and expensive to develop and interact with.

The choice between them depends on your project's need for trustless validation versus simplicity and cost-effectiveness. If you need custom smart contract development, or are not sure which option to choose, we recommend reaching out at [email protected].

Forward-Compatibility with Versioning

CIP-68 uses a version field in the on-chain datum of the Reference Token ([metadata, version, extra_data]) to ensure forward-compatibility.

As the standard evolves, this version number is incremented to support new features—for example, V1 introduced NFTs (222) and FTs (333), while V2 added Rich Fungible Tokens (444). By specifying the version at mint, your assets remain readable by older tools while enabling new functionality as it becomes available.

Minting a CIP-68 Asset

Minting a CIP-68 asset typically requires constructing a transaction using Anvil API's transactions/build endpoint that creates both the Reference and User tokens simultaneously. Smart contracts usually enforce this simultaneous minting, but the tokens can technically be minted separately.

Prerequisites

Before you mint, make sure you have:

  1. Anvil API key – Obtain one here to submit transactions.

  2. Three wallets

    • Customer wallet – Pays fees and receives the NFT. Must have UTxOs to pay for fees.

    • Policy wallet – Signs the minting transaction due to the native script requirement. For secutiry reasons, make sure no UTxOs are on this address.

    • Metadata-manager wallet (or script address) – Holds the reference token and controls metadata updates. If you want to update the metadata, you need make sure you have some ADA on this address to pay for fees. Use our wallet CLI to create them.

  3. NFT metadata – Name, description, image URL, etc., formatted per CIP-68.

  4. Minting rules – Define who can sign and when:

Each guide below walks you through collecting these requirements.

Payload Example

Regardless of using a Metadata Manager Wallet or a Smart Contract, interacting with the API is almost the same. We need to start by building a transaction. This transaction defines what we want to submit to the blockchain. The native script, or smart contract defines how the transaction is validated.

Native Script vs Smart Contract Validation

Validation options

  • Native Script – Script that checks:

    1. Signer – Required key-hash

    2. Timing – Optional timelock Ideal for straightforward mint/burn rules. See Native Scripts.

  • Smart Contract (Plutus/Aiken) – Fully programmable logic. Verify payments, token ownership, game achievements, or any custom rule you write in Plutus or Aiken. Include a scriptInteractions section with validator, redeemer, and datum. See Smart Contract Documentation.

Choose based on complexity: • native scripts for quick, signature and time-lock validation rules • smart contracts for advanced, application-specific logic

{
  // Customer wallet address receive any leftover UTxOs from the transaction. 
  "changeAddress": "addr_test1...",
  
  // UTXOs from the customer wallet paying for fees (list of CBOR UTXOs)
  "utxos": ["8282...", "8282..."],

  "mint": [
    {
      // Reference Token - Label 100 -> Sent to Metadata Manager Wallet or Script Address
      "version": "cip68",
      //Name of the asset. Must be the same for both tokens
      "assetName": { "name": "youruniquecip68asset", "format": "utf8", "label": 100 },
      "metadata": {
        "name": "Your NFT Name",
        "image": "ipfs://your-image-hash",
        "mediaType": "image/png",
        "description": "A description for your CIP-68 asset"
      },
      "policyId": "8e024681ee83f54bd5f9a0334641...",
      "quantity": 1,
      "destAddress": "addr_test2..."
    },
    {
      // User Token - Label 222 -> Sent to User Wallet
      "version": "cip68",
      // Asset name must be identical to the (100) token's assetName
      "assetName": { "name": "youruniquecip68asset", "format": "utf8", "label": 222 },
      "policyId": "8e024681ee83f54bd5f9a0334641...",
      "quantity": 1,
      "destAddress": "addr_test1..."
    }
  ],
  
  // The `preloadedScripts` array provides script data for minting authorization.
  // - Native scripts: contains the actual native script
  // - Plutus scripts: contains blueprint data (native script derived from blueprint)
  // Optional but recommended for performance and latency. Required for new/unregistered scripts.
  "preloadedScripts": [ /* ... script details ... */ ],

  // The `scriptInteractions` array is ONLY required for smart contract validation.
  // It is not used for the native script / Metadata-Manager Wallet approach.
  // It is ONLY required for blueprints that are not registered yet. 
  // The full payload format is covered in the smart contract guide.
  "scriptInteractions": [ /* ... validator, redeemer, datum ... */ ],
}

CIP-68 Guides

Deno & Fetch

Last updated

Was this helpful?