> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ton.org/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.ton.org/feedback

```json
{
  "path": "/standard/tokens/jettons/mintless/overview",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# Mintless Jetton

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

## Introduction

<Aside>
  To understand this document, you should be familiar with the other basic Jetton standards.
</Aside>

TON has introduced [Mintless Jettons](https://github.com/ton-community/mintless-jetton?tab=readme-ov-file), an innovative extension of the Jetton standard.

Mintless extension adopts [Merkle proofs](/foundations/proofs/overview), using them to make airdrops without requiring traditional minting processes.

In this article, we will explore how mintless jettons work and how to use them.

## Overview

Mintless jettons are an extension ([TEP-177](https://github.com/ton-blockchain/TEPs/pull/177) and [TEP-176](https://github.com/ton-blockchain/TEPs/pull/176)) of the standard Jetton implementation ([TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md)) on TON Blockchain.

This implementation enables large-scale, decentralized airdrops to millions of users while minimizing costs and blockchain load.

Note that to use a mintless jetton to its full extent, you will need to establish an off-chain architecture.

### Basic features

* **Scalability**: Traditional minting processes can be resource-intensive and costly when distributing tokens to a vast number of users.
* **Efficiency**: By utilizing Merkle trees, mintless jettons store a single hash representing all airdropped amounts, reducing storage requirements.
* **User-friendly airdrops**: No separate pre-claim: wallets attach a Merkle proof on first transfer, so users don't perform a manual claim action.

Because mintless jettons extend the standard jettons, you can interact with them the same way as standard jettons — no additional steps required.

## How it works

Mintless jettons leverage [Merkle trees](/foundations/proofs/overview) and cryptographic proofs to enable efficient, decentralized airdrops without traditional minting. Here's a detailed breakdown of the technical implementation:

### Merkle Tree Foundation

The core innovation lies in representing all airdrop data as a single Merkle tree, where:

* **Leaf nodes** contain airdrop information for individual addresses
* **Internal nodes** store cryptographic hashes of their children
* **Root hash** represents the entire airdrop dataset with a single 256-bit value

This approach reduces storage from O(n) per recipient to O(1) for the entire airdrop.

### Data Structures

Airdrop HashMap represents how we store individual users' airdrop information.

```tlb theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
_ amount:Coins start_from:uint48 expired_at:uint48 = AirdropItem;

_ _(HashMap 267 AirdropItem) = Airdrop;
```

Each airdrop entry contains:

* `amount`: Number of tokens allocated to the recipient
* `start_from`: Unix timestamp when claiming becomes available
* `expired_at`: Unix timestamp when claiming expires

The complete airdrop is stored as a HashMap where the key is a 267-bit internal TON account address and the value is an AirdropItem structure.

For the Jetton Master contract, standard storage is extended with `merkle_hash`: 256-bit root hash of the Merkle tree containing all airdrop data.

The standard wallet storage is extended with:

* `merkle_hash`: Copy of the master's Merkle hash for validation
* `already_claimed`: Boolean flag indicating whether the airdrop has been claimed

### Claiming Mechanism

```tlb theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
merkle_airdrop_claim#0df602d6 proof:^Cell = CustomPayload;
```

The claiming process uses the `custom_payload` field in standard jetton transfers with:

* `0x0df602d6`: Operation identifier for Merkle airdrop claims
* `proof`: MerkleProof exotic cell containing the cryptographic proof

```tlb theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
transfer#0f8a7ea5 query_id:uint64 amount:(VarUInteger 16) destination:MsgAddress
                 response_destination:MsgAddress custom_payload:(Maybe ^Cell)
                 forward_ton_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell)
                 = InternalMsgBody;
```

The standard transfer message is enhanced by including the claim proof in `custom_payload`.

### Cryptographic Proof Validation

When a jetton wallet receives a transfer with a claim payload, it performs these validation steps:

1. Merkle Proof Verification

* Extracts the MerkleProof exotic cell from `custom_payload`
* Verifies the proof's cryptographic integrity against the stored `merkle_hash`
* Ensures the proof path leads to a valid `AirdropItem` for the sender's address

2. Timestamp Validation

* Checks that `now() >= start_from` (claiming period has begun)
* Verifies that `now() <= expired_at` (claiming period hasn't expired)

3. Claim Status Check

* Ensures `already_claimed == false` (prevents double-claiming)

4. Amount Validation

* Extracts the airdrop amount from the validated AirdropItem
* Credits this amount to the wallet's balance

### State Transitions

Before Claim:

```
JettonWallet {
  balance: 0,
  already_claimed: false,
  merkle_hash: <root_hash>
}
```

After Successful Claim:

```
JettonWallet {
  balance: <airdrop_amount>,
  already_claimed: true,
  merkle_hash: <root_hash>
}
```

### Off-chain Infrastructure

#### Merkle Tree Generation

1. **Data Collection**: Gather all recipient addresses and their allocated amounts
2. **Tree Construction**: Build a binary Merkle tree with AirdropItem structures as leaves
3. **Hash Computation**: Calculate SHA-256 hashes recursively up to the root
4. **Proof Generation**: Create individual Merkle proofs for each recipient

#### Proof Serving

* **Static Storage**: Host the complete Merkle tree data at `mintless_merkle_dump_uri`
* **Dynamic API**: Implement `custom_payload_api_uri` to serve individual proofs on demand
* **Caching**: Optimize proof retrieval with appropriate caching strategies

## Supporting mintless jettons in wallet applications

Wallet applications play a key role in improving the user experience with mintless jettons:

* **Display unclaimed jettons**: Wallets should show users the jettons they are eligible to claim based on the Merkle tree data.
* **Automated claim process**: When users initiate an outgoing transfer, wallets should automatically include the necessary Merkle proof in the transfer message's custom payload.

Wallets can achieve this by:

Integrating with the off-chain API specified in the [custom payload API](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#jetton-metadata-example-offchain):

* Check if the jetton is mintless.
* Verify whether the wallet owner has claimed it.
* If unclaimed, retrieve data from the custom payload API and add the off-chain balance to the on-chain one.
* If the user hasn’t claimed the airdrop, retrieve the custom payload and initialization data from the Custom Payload API and include it in the `transfer` message to the Jetton wallet.

Using a custom API:

* Download the airdrop tree from `mintless_merkle_dump_uri` in the jetton metadata.
* Parse the data as explained in [Merkle tree generation](#merkle-tree-generation).
* Make the parsed result available via API.

<Aside>
  Wallets are not required to support mintless claims, including indexing airdrop trees. Wallet applications may charge the jetton issuer for this service.
</Aside>

## Supporting mintless jettons in DApps (DEX/Lending platforms)

Because wallet applications handle claims automatically, DApps don’t need special logic for mintless jettons. DApps can use APIs (such as TonAPI or Ton Center API) to display unclaimed balances.

To improve the user experience, DApps can check if the user's wallet application supports a specific mintless jetton. If unsupported, retrieve the airdrop proof and initialization data from the Jetton API and include it in the transfer message.

## See also

* [Understanding mintless jettons: a comprehensive guide](https://gist.github.com/EmelyanenkoK/bfe633bdf8e22ca92a5138e59134988f) - the original post.
* [Mintless jetton standard implementation](https://github.com/ton-community/mintless-jetton)
* [Jetton offchain payloads TEP](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#jetton-metadata-example-offchain)
* [Jetton metadata standard](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md)
