Blockchain innovation often emerges at the intersection of security and flexibility. Charms represents a fascinating blend of Bitcoin's robustness and Cardano's programmability, introducing Datum and Redeemer-like concepts to Bitcoin in a unique way. As these technologies grow, we might witness a cross-chain synergy, where Charms tokens integrate with Cardano, and Cardano's native assets appear on Bitcoin. This article will explore the Charm protocol and compare it to Cardano's Extended UTXO model, highlighting their differences and unique advantages. Cardano’s Extended UTXO Model in Brief Cardano’s Extended UTXO (eUTxO) model builds on Bitcoin’s UTXO design to enable smart contracts and application state on a UTXO ledger. In Cardano, each unspent output can carry more than just the ADA cryptocurrency – it can include multiple user-defined tokens and an arbitrary piece of data (called a Datum). This Datum effectively serves as the local state for a smart contract, associated with that specific output. To spend a “scripted” output (one guarded by a smart contract), a spending transaction must provide two things in addition to the usual signature: A Redeemer: an arbitrary input supplied to the contract (e.g., an action or parameter). The Validator Script itself (Cardano’s scripts are written in Plutus, a native smart contract language). The validator script is essentially a function (a predicate) that takes the datum (state), the redeemer (input), and the ScriptContext (including transaction context), and returns a boolean indicating whether the spend is allowed. In code form, a Cardano validator might be represented as: Every Cardano node executes this script during transaction validation. All scripts in a transaction must evaluate to True for the transaction to be accepted. Application State Management In Cardano, the Datum attached to an output holds the application state for that UTXO. To update the state, a transaction must consume (spend) the output and create a new output with a revised Datum (new state). This means the state is passed forward from one UTXO to the next. A common pattern is to use a unique token (an NFT) to identify a particular contract instance, ensuring only one UTXO represents that instance at any time. For example, a simple auction contract might use an NFT to tag the auction state UTXO; the Datum holds the highest bid and bidder. Each new bid is a transaction that consumes the auction UTXO and produces a new one (with the same NFT) carrying an updated Datum (the new highest bid). The Plutus script ensures the transition is valid (e.g., the new bid is higher and the proper funds are included) before allowing the spend. In this way, Cardano maintains state across transactions by chaining UTXOs, with the ledger itself enforcing the contract rules on-chain. This on-chain enforcement guarantees that invalid state updates (e.g., a too-low bid or an unauthorized spend) are simply rejected by the network. Spells: Embedding Smart Logic in Bitcoin Transactions In the Charms protocol, Spells are the core mechanism that create and transfer Charms assets. A spell is essentially a blob of metadata attached to a transaction that describes what tokens or state (“charms”) are being created, moved, or destroyed. Spells are often compared to Ordinals inscriptions, since they also reside in transaction data. However, spells are far more powerful: they can encode arbitrary state transitions and even carry zero-knowledge proofs to validate complex logic. Most Bitcoin-based protocols, like Ordinals and Runes, rely on centralized indexers to scan the ledger and track ownership off-chain, requiring users to trust third-party databases. Charms eliminates this reliance. Each transaction includes a zkVM-powered “spell”, a cryptographic proof that ensures: The transaction and app logic are valid. Previous transactions were correctly processed. The spell is authentic, preventing fraud. Thanks to recursive zero-knowledge proofs, Charms clients—whether desktop wallets or mobile apps—can independently verify asset state without indexers. Every user becomes their own validator, with no need for trust or off-chain infrastructure. Just run a Bitcoin client and a Charms client, and you control your sovereign UTXO superchain. How spells work A spell is inserted in the witness field of a Bitcoin input (specifically, in a Taproot input’s script path), formatted as a no-op script fragment. The spell data is wrapped in an OP_FALSE/OP_IF ... OP_ENDIF so that it has no effect on Bitcoin’s script execution. This clever encoding allows up to ~10 KB of data to be attached in a single input if needed, bypassing the 80-byte limit of OP_RETURN. Inside this “envelope,” the spell contains a structured description of Charms' operations, plus a cryptographic proof. A spell typically includes: A list of apps (smart contracts or token types) involved in the transaction. The list of input UTXOs being consumed and what charms (tokens/state) they carried. The list of output UTXOs being created and what charms they will carry. A zk-SNARK proof attesting that the state transition from inputs to outputs obeys all the rules of the involved apps. When a Charms-enabled wallet sees a Bitcoin transaction, it will look for a spell in the inputs. If found, the wallet tries to parse and validate it. A spell is considered “correct” (valid) only if all of the following hold true: The spell’s metadata is well-formed and interpretable (correct format, proper structure). The spell’s contents make sense relative to the transaction (e.g., it doesn’t assign more Charms outputs than there are actual Bitcoin outputs). The included proof verifies successfully against the specified app logic and prior state. The Charms metadata for outputs is not stored in the output itself within the Bitcoin transaction. It's only described in the input’s witness field (the Spell) and interpreted off-chain by Charms-aware clients. Charm state transitions are initiated via on-chain Bitcoin transactions, but the actual tracking and validation of those state transitions happen off-chain via the Charms protocol. Charm state transitions are valid per application. The Charms parser finds the application (via its identity and verification key) in the spell and uses that to: Interpret the spell’s state and token changes. Validate the transition using that app’s logic. Update the state and/or token ownership accordingly. The next user must retrieve the current valid off-chain state (as understood by the Charms client), then use it to construct a new Bitcoin transaction with a new Spell that describes the next valid state transition. Put differently, every new transaction that moves or modifies charms must be built on the currently valid off-chain state, and anchored with a new on-chain Bitcoin transaction that includes a verifiable spell. If a spell is correct, then the tokens and state changes it describes are applied: the outputs of that Bitcoin transaction are now considered “enchanted” with those charms (the new state). Incorrect or malformed spells are simply ignored – in that case, the transaction is treated as having no Charms effect (just a normal BTC transaction). From my understanding, Bitcoin alone cannot prevent double-spending of Charms tokens unless those tokens are bound to specific UTXOs (e.g., specific satoshis). If Charms tokens are not tied to specific satoshis, then two valid Bitcoin transactions could exist with different inputs (different UTXOs) and conflicting Charm spells — both valid from Bitcoin’s perspective. Only the Charm application logic and client validation can detect and reject such misuse. If Charm tokens were explicitly associated with specific satoshis, then Bitcoin's own consensus rules could prevent double-spending of those tokens. Because spells are validated on the client side, participants are free to ignore Charms if they’re not interested – Bitcoin nodes and other wallets see nothing but an innocuous piece of witness data. But users who opt-in by running the Charms software gain the ability to interpret these spells and thus track and transact smart tokens on Bitcoin. In short, “Spells are the magic that creates Charms”, enabling Bitcoin transactions to carry tokens, NFTs, and arbitrary app state very much like Cardano transactions carry multiple assets and Datums. The big difference is who enforces the rules, as we explore next. Preserving and Updating State: Cardano vs. Charms Both Cardano and Charms treat the blockchain as a ledger of stateful UTXOs, but they handle state updates differently in practice: Cardano (eUTxO) The state is an integral part of the ledger. A Datum lives inside a UTXO; when that UTXO is spent, the state is destroyed on-chain and must be recreated in a new UTXO if it is to persist. The Cardano ledger itself ensures that only a valid state transition can occur by running the contract script. For a dApp developer, this means modeling the application’s state as one or more UTXOs. For example, an auction’s state (current highest bid, bidder, etc.) would reside in a single UTXO Datum. To update the state (e.g. a new bid), a transaction must consume that UTXO and produce a new one with the updated Datum. The continuity of state is often enforced by including a unique token in the state UTXO (so it can’t be duplicated elsewhere), and the Plutus script will check that exactly one output carries that token forward. State is preserved by explicitly carrying data (and often an identifying token) from one output to the next. If no transaction spends a UTXO, that piece of state simply remains in place (inactive but available) until someone interacts with it. Charms State in Charms is also tied to UTXOs (called enchanted outputs), but here the Bitcoin ledger is unaware of the state. The state is stored as charms data off-chain, interpreted via the spells. Each enchanted UTXO holds a mapping of App → Data, potentially containing multiple independent pieces of state (multiple charms) in one output. For example, a single Bitcoin output could simultaneously hold an NFT representing an auction state and some fungible token balance – Charms calls this a “string of charms” when multiple entries are bound together in one UTXO. To update the state, a transaction must spend the underlying Bitcoin UTXO and create a new one, similarly to Cardano. The spell attached to that transaction will describe how the charms from the input UTXO map are mapped to charms in the new output(s). State continuity is ensured by the app logic and proofs: e.g., the spell must prove that whatever the app expected from the previous state x has been correctly transformed into the new state x' in the outputs. Each app has an identity and a verification key in its definition; this effectively plays a role similar to Cardano’s policy IDs or script hashes, tying state to a particular contract logic. As long as a charm (say, our auction NFT) appears in an output with the same app identity and verification key, Charms clients know it’s the same logical state carried forward. In Charms, multiple apps’ states can be updated in one go (since a single spell can cover many charms at once), enabling composability. For instance, an auction app’s state NFT and a fungible token app could interact in one transaction – perhaps the winning bidder’s payment in a token is transferred while the NFT state is updated to “closed.” In Cardano, achieving a similar multi-contract interaction might require multiple transactions or a single script that encompasses all assets, since each UTXO is guarded by one script. Cardano outputs can hold multiple native tokens, but the script logic is usually tied to one contract at a time, whereas Charms allows each token/state to carry its own contract logic (the zkVM will validate all relevant app rules together). State Update Example Suppose an auction on Cardano uses a UTXO with datum {highestBid: 100, highestBidder: Alice}. If Bob bids 150, a transaction will consume that UTXO and produce a new one with datum {highestBid: 150, highestBidder: Bob}. The Plutus script in the consumed UTXO checks that Bob’s bid is indeed higher (150 > 100) and that Bob’s transaction includes the 150 ADA payment, etc., before allowing it. On Charms, an equivalent auction state might be an NFT charm with data {highestBid: 100, bidder: Alice} on a Bitcoin UTXO. Bob’s bid would be a Bitcoin transaction where a spell describes taking the NFT charm from the input and putting it into an output with data {highestBid: 150, bidder: Bob}. The spell’s proof would certify that the rules of the auction contract (written in, say, Rust and compiled to a zkVM circuit) were followed – e.g., it checked 150 > 100 and that the appropriate payment was made. From the perspective of the Bitcoin blockchain, it’s just an ordinary spend of a BTC output (perhaps with Bob paying some BTC to Alice as the refund of her deposit, and moving some BTC to a new output as Bob’s deposit). But to Charms users, the NFT’s state has updated to the new bid. Bottom line: Cardano and Charms both preserve application state across transactions by threading it through UTXOs. Cardano does it with on-chain Datums and strict script validation by every node, whereas Charms does it with off-chain metadata (spells) and cryptographic proofs validated by each user’s wallet. In Cardano, application state is part of the ledger itself (all nodes know the datum, even if they don’t interpret its meaning), while in Charms, the state is inferred by clients from the enchanted transaction history. Adding Data to Transactions: Datum & Redeemer vs. Charms Metadata Cardano’s approach to extending UTXOs involves attaching explicit data fields to transactions: the Datum (on outputs) holds state, and the Redeemer (on inputs) provides input parameters for scripts. These pieces are included in the transaction body or witnesses and are known to the blockchain. By design, Cardano nodes understand and use these fields during validation – for instance, a node will retrieve the Datum associated with an output and feed it, along with the redeemer, into the Plutus script for execution. Charms, on the other hand, adds data to transactions in the form of the Spell, which is purely for off-chain consumption. The spell contains the descriptions of charms (like mini-datums for each asset) and can be thought of as combining the roles of Datum and redeemer in one structure: It describes the current state being spent (similar to a Datum from the inputs). It carries the parameters or actions (similar to redeemers) needed to produce the new state. It even includes the logic validation in the form of a zero-knowledge proof (something Cardano achieves by actually running the script on-chain). In effect, Cardano’s data fields are utilized by the on-chain interpreter, whereas Charms’ data is interpreted by an off-chain zkVM. Both systems allow arbitrary data to be included in transactions, but Cardano’s data becomes part of the permanent on-chain record and consensus validation, while Charms’ data is also on-chain (embedded in the witness) but ignored by consensus and only relevant if you’re running a Charms client. This means Charms can include richer or larger data (thanks to Taproot’s flexibility) without burdening all network nodes – only those interested will process it. Another similarity is that both allow transactions to carry multiple assets and data fields: Cardano outputs natively support multi-asset values (you can have a bundle of different tokens in one output), and one Datum can represent the combined state or any additional info needed for those assets. Charms likewise allows a single output to hold a bundle of charms (each with its own app-specific data). For example, an output might contain {TokenA: 50, TokenB: 100, AuctionNFT: {highBid: 150}} all at once. Under the hood, the spell will list multiple app entries for that output. In Cardano, validation logic is separate from the data (the script is a separate entity, referenced by a hash). The Datum and redeemer are fed into the script. In Charms, the logic comes attached with the data in a sense – the verification key (vk) of each app points to the logic (which might be known to the client via a library or fetched separately), and the spell’s proof proves that logic was executed correctly. There isn’t a direct “script” field on-chain equivalent to Cardano’s script hash; instead, the logic is identified by the app’s vk and enforced via the proof. To illustrate, Cardano might say: “Output X is locked by script hash H. Datum = 42. Redeemer = ‘increment’. The node will run script H with those inputs to decide validity.” Charms would say: “Output X is enchanted with app (vk = V) whose state = 42. A spell is cast with an operation ‘increment’ and a proof that the app V’s rules allow state 42 to go to 43.” The end result (state = 43 in a new output) is analogous, but Cardano had the chain execute the script, whereas Charms had the user’s machine execute the logic (off-chain or in a ZK circuit) and merely record the outcome + proof on-chain. Transaction Validation and Execution In Cardano, smart contract execution happens during transaction validation. When a Cardano node (block producer or validator) processes a transaction containing script-locked inputs, it will invoke the Plutus interpreter on each such input. The transaction is only included in a block if all script validations return True. This means Cardano’s ledger itself guarantees the correctness of contract interactions. The upside is strong security and consistency: if a transaction appears on-chain, you know it satisfied the contract’s rules. There is no way for an invalid state transition to “slip through” – it simply would not make it into a block. However, this approach has downsides in terms of performance and complexity. Every validating node does the work of running the script, which is why Plutus scripts have strict resource limits (memory, CPU steps) and why there’s a limit to how many complex contracts can run in a single block. On-chain execution also means all details of the contract’s computation are public (though data can be hashed to hide contents, at the cost of requiring out-of-band communication for the actual Datum). In Charms, transaction validation is split between the base layer and the client layer. Bitcoin miners only validate the normal Bitcoin aspects: signatures, UTXO spends, and that the dummy script (with OP_FALSE, OP_IF ... OP_ENDIF) is correctly formed (which it always will be if used as specified). The smart contract side of things is validated by the Charms client using the zkVM proof in the spell. Thus, when a Charms transaction is mined in Bitcoin, the base chain has not executed any of the app logic – it has merely included the spell data. It’s up to each user to verify the cryptographic proof to be confident that the transaction was legitimate in terms of Charms rules. The Charms protocol is designed such that this proof is succinct (a few hundred bytes) and quick to verify, thanks to zero-knowledge proof technology. Charms uses recursive zkSNARKs: each new spell proof also attests that all previous related state transitions were valid. This means a client syncing the state of a token doesn’t need to re-validate the entire history from genesis – it can trust the latest proof, which recursively covers the correctness of prior transactions. Pros and Cons – Cardano’s approach: Pros: Security is rooted in the blockchain’s consensus. Users don’t need any extra verification software to trust outcomes – if it’s on the ledger, it followed the rules. This reduces the risk of users accepting invalid states by mistake. Also, the code is transparent and part of the system’s integrity. Cons: Limited throughput and high execution cost, since every node executes every contract (scaling requires either layer-2 solutions or careful design). Developers are constrained by the execution model (must fit within strict resource units) and programming model (Plutus and its determinism restrictions). Upgrades to the contract logic require on-chain redeployment or new scripts, which involve coordination on-chain. Pros and Cons – Charms’ approach: Pros: No additional burden on the base chain – Bitcoin continues to handle only basic UTXO and signature checks, which are trivial. This means Charms transactions have minimal impact on Bitcoin’s performance (aside from adding some extra bytes in blocks). The heavy lifting of contract execution is done off-chain by the party creating the transaction, who generates a proof of correctness. This opens the door to much more complex logic than would be feasible on-chain, since a user can take as long as needed to compute a proof, and the verification remains fast. It also naturally provides privacy in some cases: the proof can attest to a condition without revealing all details. For example, an app could use a private input (w in the app contract) that doesn’t appear on-chain; the proof might confirm “the user has provided a correct secret” without the secret itself being published. Cons: Security and trust are shifted to the client side. If a user does not run a Charms client (or some verifying service), they could be fooled by a transaction that claims to transfer a token but has an invalid spell. Bitcoin’s network won’t invalidate such a transaction – it’s up to you to check the proof. This introduces a slight trust model nuance: you trust math (the zk proof) and your software, instead of the global consensus, to enforce rules. In practice, this means users must run the Charms wallet software (or a light client that at least verifies proofs) to safely use Charms tokens, whereas Cardano users implicitly rely on the Cardano node to handle validation. Another con is the complexity of setting up these zkVM circuits and proofs. While Charms aims to make it developer-friendly, writing a smart contract in Rust that compiles to a zk circuit may be a higher bar for developers than writing a Plutus script. The proving process also means transaction creators might need significant computation (depending on the app complexity) to produce a proof, though verification for others remains fast. In short, Cardano’s model is fully on-chain execution, maximizing security at the cost of scalability, whereas Charms is off-chain execution with on-chain proofs, aiming for scalability and cross-chain flexibility at the cost of making validation a local responsibility. Both approaches seek to bring programmability to UTXOs, but they lie at different points on the spectrum of on-chain vs. off-chain workload. Conclusion Each approach has its merits: Cardano offers simplicity of trust (trust the chain), whereas Charms offers broad flexibility (any UTXO chain, any logic via zkVM) and scalability through client-side work. For blockchain enthusiasts, Charms represents an intriguing hybrid of Bitcoin’s robustness and Cardano’s programmability – essentially bringing the concepts of Datum and Redeemer to Bitcoin, but executing them in a novel way. As these technologies evolve, we may even see them complement each other: Charms tokens appearing on Cardano and Cardano’s stablecoins or NFTs finding their way onto Bitcoin, all through this “spellbound” UTXO model. The end goal shared by both systems is to marry Bitcoin’s UTXO security with Ethereum-like flexibility, either by upgrading the nodes (Cardano’s path) or by upgrading the clients (Charms’ path) – a magical convergence of ideas in the blockchain space.