> For the complete documentation index, see [llms.txt](https://docs.bitcoinos.build/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bitcoinos.build/technical-documentation/grail-pro-charms-zkbtc/technical-overview/charms.md).

# Charms

Charms are represented as metadata written onto Bitcoin transactions as inscriptions. This metadata maps information to each one of the transaction’s outputs, allowing these pieces of information to be owned in the same sense that a Bitcoin UTXO is owned by some wallet’s keys. Charms, therefore, use the same ownership model as Bitcoin, and rely on Bitcoin’s security and consensus mechanism.&#x20;

Charms come in two flavors: non-fungible tokens (NFT) and fungible tokens. An NFT can contain any data that can practically be written to Bitcoin, while fungible tokens only contain amounts. The simplest charm is a fungible token, for which the total amount in each transaction’s inputs is equal to the total amount in the transaction’s outputs, thus maintaining a constant supply.&#x20;

Each charm is associated with a specific program, called zk-app, which enforces constraints on the ways metadata can be manipulated. zk-apps, plus the ability of different charms to interact in interesting ways, allow developers to implement any conceivable behavior.&#x20;

A transaction that contains charms as inputs or outputs we call a “spell”. The distinction between charms (tokens) and spells (operations on tokens) is critical for our understanding of how charms work. Let’s examine a spell from two perspectives, a “physical” perspective in which we look at the Bitcoin transaction containing the spell, and a logical perspective in which we look at the metadata and how it is interpreted.&#x20;

![](/files/kZwhi0e7DTVl15FOCPJE)\
\
Each spell contains two Bitcoin transactions, the spell itself, and a commitment transaction that precedes it. The commitment transaction receives BTC (1 in the diagram) for the transaction’s fees, as well as BTC needed to fund the spell’s outputs, since every output has to contain at least 546 satoshis (dust limit). The commitment transaction’s output (2 in the diagram) has a taproot address that allows the spending input to specify a spending script which contains the inscription. The inscription is encoded as binary data in CBOR format, and is encapsulated in the script between OP\_FALSE, OP\_IF and OP\_ENDIF instructions so that it is ignored when running the script. This allows arbitrary data to be encoded into the transaction. The spell transaction also has additional inputs and outputs (3 and 4 in the diagram), and a change output (5 in the diagram) which allows redundant BTC to be returned to the user’s wallet after deducting the transaction fee.&#x20;

A Logical Perspective&#x20;

Each spell can contain multiple zk-apps. A zk-app is a program, identified as a string of the form: \<n|t>/\<app\_id>/\<app\_vk>, where the first character is either ‘n’ for an NFT or ‘t’ for a fungible token. app\_id is an arbitrary 32-byte hex string. For the sake of uniqueness, it is recommended for app\_id be the SHA256 digest of the incoming output that funds the spell. app\_vk is the verification key, and is the SHA256 digest of the zk-app compiled binary. This distinction allows forming multiple charms of the same zk-app (by having a unique app\_id for each one), or multiple charms with the same app\_id that have different zk-apps associated with them.&#x20;

A spell can have multiple outputs, where each output contains multiple charms with different IDs. For each NFT, an object can be associated with each output. Fungible tokens have only amounts associated with each output.&#x20;

A typical pattern, which can be described as the simplest useful application of charms, would be an NFT/fungible token pair. The NFT metadata describes the pair by providing a name and icon. Ownership of the NFT allows its owner to mint new batches of the fungible token. A transaction of this application would look like this:&#x20;

![](/files/kSOZXAEKgRIaZVPUndbd)\
\
In this example, the owner of an NFT performs a transaction that transmits the NFT charm from an address in his wallet to a different address in his wallet, while also producing a fungible token with the same app\_id and app\_vk. The zk-app must verify that the amount of fungible tokens in the output is allowed to exceed the number of tokens in the inputs only if one of the inputs contains the NFT token, thus enforcing the owner’s minting privilege.

A subsequent transferal of tokens minted in this way would look like this:

![](/files/iNfnP7ppVtEWpCbv2xz5)<br>

In this example, the transaction has multiple inputs containing the fungible token, and two outputs, one where the tokens are to be sent, and the other a change output, returning the rest of the token back to the sender’s wallet.&#x20;

Proofs and Recursion&#x20;

A zk-app is a program, expressed in any high level language and compiled to WASM. The program receives an object describing a spell as its input, and either allows or forbids the transaction. If the program approves it, the Charms SDK will generate the required transaction, calculate a GROTH16 SNARK proof and embed the proof into the binary object included in the inscription. Each transaction can have inputs that also contain charms, and their proofs are “folded” into the current proof using recursive ZKP techniques. In this way it can be assured that a spell is only valid if all of its preceding spells are also valid.&#x20;

In order to verify the validity of a spell, it is therefore not necessary to traverse the graph backwards all the way to the originating transduction - the validity of a transaction history is included in the proof itself.&#x20;

A spell with an invalid proof is treated as non-existent by the wallet and all related software. In this way, if a spell is generated that violates the constraints defined by zk-app, the tokens involved in that transaction simply cease to exist. This gives a strong incentive to participants in the protocol to generate only permitted spells.&#x20;

Limitations of the Ownership Model&#x20;

Since Bitcoin lacks the ability to verify SNARK proofs on-chain, invalid spells can be created and mined. The incentive to avoid this lies in the fact that any operations that violate the constraints of the zk-app result in the tokens involved ceasing to exist so that cheating means losing funds.. This loss in itself is a strong incentive to behave honestly, and is in addition to losing the dust required for the tx, which acts as a spam control for the entire system.&#x20;

This limitation prevents certain smart contracts from being implemented using charms alone. Grail Pro allows this problem to be overcome efficiently, by providing a “Grail address” that is owned by the network and can only be spent according to the constraints of the zk-app, thus making Charms a complete platform for general purpose smart contracts.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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://docs.bitcoinos.build/technical-documentation/grail-pro-charms-zkbtc/technical-overview/charms.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.
