# Mint Logic

You've chosen the **Smart Contract approach** for CIP-68 - excellent choice for projects needing more validation control and complex business rules!

{% hint style="info" %}
**Don't worry about Aiken syntax!** This guide focuses on *what* the smart contract validates and *why*, not how to write Aiken code. You can successfully use CIP-68 smart contracts through the Anvil API without being an Aiken expert.

**Ready to implement?** Skip to the [practical minting example](/guides/nft-and-ft/mint-nft-cip-68/smart-contract/mint-example.md) and return here when you want to understand the underlying logic.
{% endhint %}

### What the Smart Contract Does

While the [main guide](/guides/nft-and-ft/mint-nft-cip-68.md) explained *what* CIP-68 achieves (updatable NFT metadata), this guide explains *how* the smart contract ensures everything works correctly with the CIP-68 NFT standard.

**The Smart Contract's Job:**

* ✅ **Enforces CIP-68 Rules**: Ensures reference tokens (100) and user tokens (222) are always created together
* ✅ **Validates Authorization**: Only authorized admins can mint new token pairs
* ✅ **Guarantees Metadata Integrity**: Reference tokens contain valid CIP-68 metadata structure
* ✅ **Enables Future Updates**: Reference tokens can be spent later to update metadata

### How It Works: The Validation Flow

Every CIP-68 mint using this smart contract follows the same validation sequence: **Build Transaction** → **Validate Smart Contract** → **Submit Valid Transaction** → **Outputs**.

**Quick Setup Process:**

1. **Upload & Parameterize**: Deploy the smart contract with admin keys via [POST /blueprints](/guides/smart-contract/blueprint-management.md) endpoints
2. **Build Transactions**: Use the parameterized contract in [POST /transactions/build](/guides/transaction.md) calls
3. **Let Validation Happen**: Smart contract automatically enforces all CIP-68 rules
4. **Submit Valid Transaction**: Validated transaction is submitted to the Cardano network via the `POST /transactions/submit` endpoint.

{% hint style="success" %}
**The beauty of smart contracts**: Once deployed and parameterized, they handle all the complex validation automatically. You just build transactions - the contract ensures everything follows CIP-68 standards, and you are creating the NFTs correctly.

**Ready to implement?** See the [Mint Example](/guides/nft-and-ft/mint-nft-cip-68/smart-contract/mint-example.md) for step-by-step code implementation.
{% endhint %}

### Smart Contract Validation Flow

The diagram below shows how the CIP-68 smart contract processes your transaction. Follow the arrows to understand the validation sequence:

{% hint style="info" %}
**How to read this diagram**: Start with "Build Transaction" (what you provide), follow the arrows through "Validate Smart Contract" (validation checks), and end at "Submit Valid Transaction" (what gets created). Each validation step must pass for the transaction to succeed.
{% endhint %}

{% @mermaid/diagram content="flowchart TD
subgraph inputs\["<b>Build Transaction</b>"]
utxos\["💰 <b>UTxOs</b> (ADA for fees)"]
user\_input\["<b><b>Reference NFT (100)</b></b><br>(Label 100 → sent to SC)"]
ref\_input\["<b><b>User Token (222)</b></b><br>(Label 222 -> sent to User)"]
admin\_sig\["🔑 <b>Admin Signature</b>"]
applied\_script\["📋 <b>Blueprint</b> with Applied Parameters"]
end
subgraph validation\["<b>Validate Smart Contract</b>"]
check\_sig\["✅ <b>Check Admin Signature<br></b>list.has(extra\_signatories, admin\_key)"]
check\_tokens\["✅ <b>Validate CIP-68 Tokens<br></b>Token pairs, metadata, and exact mint matching"]
check\_datum@{ label: "✅ <b>Validate Metadata<br></b>Metadata is valid CIP-68 format and the token's names match" }
end
subgraph outputs\["📤 Outputs"]
ref\_token\["🏷️ Reference Token (100)<br>→ Script Address<br>→ Contains Metadata Datum"]
user\_token\["🎨 User Token (222)<br>→ Any Address<br>→ The Actual NFT"]
end
subgraph submission\["📤 Submit Valid Transaction"]
n2\["💰 <b>UTxOs</b> (ADA for fees)"]
admin\["🔑 <b>Admin Signature</b>"]
user\["🔑 <b>User Signature</b>"]
n1\["✅ Valid Transaction"]
n2\["💰 <b>UTxOs</b> (ADA for fees)"]
end
inputs -- <b>'POST transactions/build'</b> --> validation
check\_sig --> check\_tokens
check\_tokens --> check\_datum
validation -- All Checks Pass --> success\["✅ Transaction Valid"]
validation -- Any Check Fails --> failure\["❌ Transaction Rejected"]
success --> submission
submission --> outputs

```
check_datum@{ shape: rect}
n1@{ shape: rect}
n2@{ shape: rect}
 utxos:::inputStyle
 user_input:::inputStyle
 ref_input:::inputStyle
 admin_sig:::inputStyle
 applied_script:::inputStyle
 check_sig:::validationStyle
 check_tokens:::validationStyle
 check_datum:::validationStyle
 ref_token:::outputStyle
 user_token:::outputStyle
 admin:::inputStyle
 user:::inputStyle
 n1:::successStyle
 inputs:::inputStyle
 validation:::validationStyle
 success:::successStyle
 failure:::failureStyle
 submission:::inputStyle
 outputs:::outputStyle
 n2:::inputStyle
classDef inputStyle fill:#e1f5fe,stroke:#0277bd,stroke-width:2px
classDef validationStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef outputStyle fill:#e8f5e8,stroke:#388e3c,stroke-width:2px
classDef successStyle fill:#c8e6c9,stroke:#4caf50,stroke-width:3px
classDef failureStyle fill:#ffcdd2,stroke:#f44336,stroke-width:3px" %}
```

### 1. Build Transaction

Your transaction requires these inputs: For more information on transaction building, see the [transaction building guide](/guides/transaction.md).

**Required Transaction Inputs:**

* 💰 **UTxOs (ADA for fees)** - Sufficient ADA for transaction fees and minimum UTxO requirements
* 🏷️ **Reference NFT (100)** - Token sent to smart contract address containing metadata
* 🎨 **User Token (222)** - Token sent to user as the actual NFT
* 🔑 **Admin Signature** - Parameterized admin key authorization
* 📋 **Blueprint with Applied Parameters** - Smart contract with embedded admin key

### 2. POST /transactions/build (API Processing)

Once you build your transaction, it gets processed through the Anvil API's transaction builder endpoint:

```http
POST /transactions/build
```

**What happens at this step:**

* Your transaction details are received by the Anvil API
* The API loads the parameterized smart contract from `preloadedScripts`
* Transaction structure is validated for basic requirements
* The smart contract validation logic is triggered
* If validation passes, a transaction is built and returned

**Key Point:** The smart contract validation (next section) happens *during* this API call, not separately.

{% hint style="info" %}
**Want to understand transaction building in detail?** This overview focuses on smart contract validation, but for comprehensive transaction construction details, see the [transaction building guide](/guides/transaction.md).
{% endhint %}

### 3. Validate Smart Contract

The smart contract performs three validation checks:

#### ✅ Check Admin Signature

```typescript
let is_signed = list.has(self.extra_signatories, signer)
```

Ensures only the parameterized admin can authorize mints.

#### ✅ Validate CIP-68 Tokens

The contract performs comprehensive validation of CIP-68 dual-token creation, metadata, and exact mint matching:

```typescript
validator cip68examples(signer: VerificationKeyHash) {
  mint(redeemer: MintRedeemer, policy_id: PolicyId, self: Transaction) {
    // Step 1: Generate expected tokens based on redeemer instructions
    let expected_mint =
      generate_mint(redeemer.assetnames, policy_id, zero, self)
        |> tokens(policy_id)

    // Step 2: Get what's actually being minted in this transaction
    let currently_minting = self.mint |> tokens(policy_id)

    // Step 3: Ensure both admin signature AND exact token match
    and {
      is_signed?,                              // Admin must sign
      (expected_mint == currently_minting)?,   // Mint exactly what's expected, nothing more/less
    }
  }
}
```

**How this validation works:**

1. **Expected vs Actual**: The contract calculates what tokens *should* be minted based on the redeemer, then compares against what's *actually* being minted
2. **No Surprises**: If someone tries to mint extra tokens or different quantities, the validation fails
3. **Dual Validation**: Both admin signature AND exact token matching must pass

#### ✅ Validate Metadata

The contract ensures each reference token output contains valid CIP-68 metadata:

```typescript
// Extract and validate datum from reference token output
expect Some(datum) = find_datum(output, self)
expect _: Cip68Metadata = datum
```

**Metadata Structure:**

```typescript
pub type Cip68Metadata {
  metadata: Pairs<Data, Data>,
  version: Int,
  extra_datum: MetadataUpdateExpiration,
}
```

**What this validates:**

* **Datum Presence**: Reference token outputs must contain a datum
* **Structure Validation**: Datum must conform to CIP-68 metadata specification
* **Version Control**: Metadata includes version information for future updates

**The `generate_mint` function handles all token validation:**

This function processes each asset name from the redeemer and validates the corresponding transaction outputs:

```typescript
pub fn generate_mint(
  tokens: List<(ByteArray, Int)>,  // List of (asset_name, output_index) pairs
  policy_id: PolicyId,
  mint: Value,                     // Accumulator for expected mint value
  self: Transaction,
) -> Value {
  when tokens is {
    [] -> mint  // Base case: return accumulated mint value
    [(assetname, index), ..rest] -> {
      // Step 1: Generate the CIP-68 token pair names
      let (ref_tok, user_tok) = generate_ref_and_user_token(assetname)
      
      // Step 2: Find and validate the reference token output
      expect Some(output) = self.outputs |> at(index)  // Must exist at specified index
      expect Some(datum) = find_datum(output, self)     // Must have a datum
      expect _: Cip68Metadata = datum                   // Datum must be valid CIP-68 metadata
      
      // Step 3: Verify reference token goes to script address with correct value
      let output_value = without_lovelace(output.value)
      let expected_output_value = zero |> add(policy_id, ref_tok, 1)  // Exactly 1 reference token
      expect output_value == expected_output_value                    // No extra tokens in output
      expect
        when output.address.payment_credential is {
          Script(hash) -> hash == policy_id  // Must go to this script's address
          _ -> False                         // Not a script address = fail
        }
      
      // Step 4: Add both tokens to mint and process remaining assets
      generate_mint(
        rest,
        policy_id,
        mint
          |> add(policy_id, ref_tok, 1)   // Add reference token to expected mint
          |> add(policy_id, user_tok, 1), // Add user token to expected mint
        self,
      )
    }
  }
}
```

**What each validation step ensures:**

* **Output Existence**: The transaction must have an output at the specified index
* **Metadata Presence**: Reference token output must contain valid CIP-68 metadata
* **Address Validation**: Reference token must be sent to the smart contract address
* **Value Precision**: Output contains exactly 1 reference token, no extras
* **Recursive Processing**: All asset names in the redeemer are validated

**CIP-68 Token Generation:**

```typescript
/// (100) Reference Token Prefix
pub const prefix_100: ByteArray = #"000643b0"
/// (222) Non-Fungible Token Prefix  
pub const prefix_222: ByteArray = #"000de140"

pub fn generate_ref_and_user_token(assetname: ByteArray) -> (ByteArray, ByteArray) {
  (prefix_100 |> concat(assetname), prefix_222 |> concat(assetname))
}
```

**Metadata Structure:**

```typescript
pub type Cip68Metadata {
  metadata: Pairs<Data, Data>,
  version: Int,
  extra_datum: MetadataUpdateExpiration,
}
```

**What this comprehensive validation ensures:**

* **Token Pairs**: Creates Reference (100) and User (222) tokens for each asset name
* **Metadata Validation**: Reference tokens must have valid CIP-68 metadata datum
* **Output Placement**: Reference tokens sent to script address, user tokens to specified address
* **Exact Matching**: Only specified tokens are minted, no extras allowed
* **Label Prefixes**: Proper CIP-68 label encoding (100 = `000643b0`, 222 = `000de140`)

### 4. Submit Valid Transaction

Once all validations pass, the transaction is submitted to the Cardano network and CIP-68 token pairs are created on-chain.

### 5. Outputs

The successful transaction creates both tokens as validated above:

* 🏷️ **Reference NFT (100)** - Sent to smart contract address with metadata datum
* 🎨 **User Token (222)** - Sent to user's wallet as the actual NFT

### Security Model

* **Admin Authorization**: Admin key hash is embedded in the contract; only they can authorize mints
* **Customer Control**: Customers control their UTxOs and receive user tokens (222) directly
* **Metadata Protection**: Reference tokens (100) are locked at script address with validated metadata

### Next Steps

Now that you understand the smart contract validation logic, you can:

* **Ready to implement?** See the [practical minting example](/guides/nft-and-ft/mint-nft-cip-68/smart-contract/mint-example.md) for step-by-step code
* **Want to build custom applications?** Use this validation knowledge to create applications that interact with CIP-68 contracts

### Technical References

* [CIP-68 Specification](https://cips.cardano.org/cips/cip68/)
* [Aiken Smart Contract Language](https://aiken-lang.org/)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.ada-anvil.io/guides/nft-and-ft/mint-nft-cip-68/smart-contract/mint-logic.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
