# Introduction

<div data-with-frame="true"><figure><picture><source srcset="/files/RozgtVWw4J2s8qEOPHVR" media="(prefers-color-scheme: dark)"><img src="/files/aM78109bgpxHJ0ABGB3v" alt=""></picture><figcaption></figcaption></figure></div>

{% hint style="info" %}
For the official Stacks whitepaper: <https://stacks-network.github.io/stacks/stacks.pdf>
{% endhint %}

### Stacks: The TL;DR

Stacks activates the Bitcoin economy. Bitcoin is the most adopted, most valuable, and most decentralized cryptocurrency. The Stacks L2 enables fast, cheap BTC and full-featured smart contracts on the L2 without modifying Bitcoin itself. Users and developers can use BTC in their apps and pay gas fees with BTC. All transactions on Stacks L2 are secured by Bitcoin L1 with 100% finality, enabling you to build apps and digital assets that are integrated with Bitcoin security.

The Stacks layer for smart contracts has the following innovations that make it unique:

**S**: Secured by the entire hash power of Bitcoin (Bitcoin finality).\
**T**: Trust-minimized Bitcoin peg mechanism; write to Bitcoin.\
**A**: Atomic BTC swaps and assets owned by BTC addresses.\
**C**: Clarity language for safe, decidable smart contracts.\
**K**: Knowledge of full Bitcoin state; read from Bitcoin.\
**S**: Scalable, fast transactions that settle on Bitcoin.

***

### Why learn the fundamentals of Stacks?

Stacks fundamentals give you the intuition to build apps that are safer, more Bitcoin-aligned, and more future-proof. A developer who learns the basics doesn’t just write Clarity—they build apps that actually *feel like* Bitcoin apps.

1. You'll build apps that actually leverage Bitcoin
2. You'll avoid costly design mistakes
3. You'll write better smart contracts
4. You'll use sBTC and Bitcoin writes correctly

***

### What to learn next?

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Stacks 101</strong></td><td>Really dive into the nuts and bolts of how Stacks is built on Bitcoin.</td><td><a href="/pages/643519d810aae8863847c383ff30a7adf7c70792">/pages/643519d810aae8863847c383ff30a7adf7c70792</a></td></tr><tr><td><strong>Network Fundamentals</strong></td><td>Learn about accounts, testnets, SIPs, authentication, BNS, and more.</td><td><a href="/pages/0878b4307d0c8019e43e58fd71801846abf828e0">/pages/0878b4307d0c8019e43e58fd71801846abf828e0</a></td></tr><tr><td><strong>Block Production</strong></td><td>How do Stacks blocks get validated and mined?</td><td><a href="/pages/ffbe6ba2bfa767879fe114dc8037af0ce9c85ba3">/pages/ffbe6ba2bfa767879fe114dc8037af0ce9c85ba3</a></td></tr><tr><td><strong>Transactions</strong></td><td>Learn about the lifecycle of a transaction on Stacks.</td><td><a href="/pages/6d973e6d65096fc5037865ce0fd55b653b921905">/pages/6d973e6d65096fc5037865ce0fd55b653b921905</a></td></tr><tr><td><strong>Clarity</strong></td><td>Discover the philosophy and design principles of the Clarity smart contract language.</td><td><a href="/pages/9bd76593b211e5160238505b84135ebbeeb42ddb">/pages/9bd76593b211e5160238505b84135ebbeeb42ddb</a></td></tr><tr><td><strong>sBTC</strong></td><td>Understand how bitcoin is unwrapped into a productive and programmable asset.</td><td><a href="/pages/5fe9d375914f8feb7f8a95ae3ac1df4de7e32df9">/pages/5fe9d375914f8feb7f8a95ae3ac1df4de7e32df9</a></td></tr><tr><td><strong>Dual Stacking</strong></td><td>A financial innovation on top of the core foundation of Stacking. Earn bitcoin with bitcoin.</td><td><a href="/pages/u8qnnWslWSgIiQPgg4eM">/pages/u8qnnWslWSgIiQPgg4eM</a></td></tr><tr><td><strong>Bridging</strong></td><td>Explore how cross-chain interoperability works with Stacks and other major networks.</td><td><a href="/pages/i07SAdOUl0FhW30XTHfh">/pages/i07SAdOUl0FhW30XTHfh</a></td></tr></tbody></table>

***

### Additional Resources

* \[[Stacks YT](https://youtu.be/0erpW7IEo6Y?si=Ldu4RlVVnLqOL4eP)] How Stacks Will Grow In 2025 With Stacks Founder Muneeb Ali
* \[[Token2049 Dubai](https://youtu.be/DFTXAOmi0es?si=sMOO6Yfj_TCVdFTF)] Muneeb Ali - Building Bitcoin’s Future: The Role of Stacks L2


# Stacks 101

Stacks has a very unique technical model in the Bitcoin ecosystem. This section will help you get a high-level overview of the essential components to understand how Stacks works.

We'll cover the basics of what Stacks is and how it works from both a philosophical and technical level, and you can dive into the further sections for more details.

First up, let's get an overview of exactly what Stacks is.


# What Is Stacks?

<div data-with-frame="true"><figure><img src="/files/Nq7XzRGJbx4NnmksWJ2L" alt=""><figcaption></figcaption></figure></div>

Stacks is a Bitcoin layer for smart contracts; it enables smart contracts and decentralized\
applications to use Bitcoin as an asset in a trust-minimized way and settle transactions on the\
Bitcoin blockchain.

Stacks is a different type of Bitcoin layer for smart contracts than sidechains, with a deeper,\
ongoing connection to Bitcoin. Stacks enables applications and smart contracts to use\
BTC as their asset or money and to settle their transactions on the Bitcoin main chain. **The goal**\
**of Stacks is to grow the Bitcoin economy, by turning BTC into a productive rather**\
**than passive asset, and by enabling various decentralized applications.**

The Stacks layer has its own global ledger and execution environment, to support smart contracts and to not overwhelm the Bitcoin blockchain with additional transactions. However, the Stacks layer is unique as it has most of the ideal properties that native Bitcoin smart contracts would have, but it does this without needing to add additional functionality or complexity to Bitcoin. It also provides mechanisms for higher performance and additional functionality, such as fast block times and the decentralized peg.

As a Bitcoin layer, Stacks has the following innovations that make it unique:

<details>

<summary><strong>Secured by Bitcoin</strong></summary>

Secured by Bitcoin: enables Bitcoin finalization for Stacks transactions; transactions that\
happen on the Stacks layer are secured by the entire hash power of Bitcoin. Meaning that to\
reverse these transactions, an attacker will need to reorg Bitcoin. Such transactions settle on\
Bitcoin and have Bitcoin finality. Further, the Stacks layer forks with Bitcoin, so any state\
on Stacks automatically follows the Bitcoin forks.

</details>

<details>

<summary><strong>Trust-minimized Bitcoin peg</strong></summary>

Trust-minimized Bitcoin peg: lays the foundation for a novel decentralized, Bitcoin-pegged asset, sBTC, so smart contracts can run much faster and more\
cheaply using the Bitcoin-pegged asset with minimal counterparty risk. This also enables\
contracts on the Stacks layer to write to Bitcoin through the peg-out transactions without\
needing to rely on a centralized, closed set of entities. Atomic swaps and assets: Stacks\
already has atomic BTC swaps and enables Bitcoin addresses to own and move assets\
defined on the Stacks layer. Magic swaps and Catamaran swaps are examples of\
decentralized atomic swaps between BTC on Bitcoin L1 and assets on the Stacks layer that\
are already live. Further, users can own Stacks layer assets like STX, stablecoins, and NFTs\
on Bitcoin addresses and transfer them using Bitcoin L1 transactions if they prefer.

</details>

<details>

<summary><strong>Clarity language</strong></summary>

Clarity language: supports Clarity, a safe, decidable language for provable smart\
contracts. With Clarity, developers can know with mathematical certainty what a contract\
can and cannot do, even before executing it. The decentralized peg contract will benefit\
from the safety properties of the Clarity language. Of particular note, Clarity WASM is a\
change being made to the Clarity VM that provides significantly faster execution times,\
along with creating a potential path to Rust and Solidity developers being able to write\
smart contracts on Stacks, although this work is not part of the Nakamoto release.

</details>

<details>

<summary><strong>Knowledge of Bitcoin state</strong></summary>

Knowledge of Bitcoin state: has knowledge of the full Bitcoin state; it can trustlessly read\
Bitcoin transactions and state changes and execute smart contracts triggered by Bitcoin\
transactions. The Bitcoin read functionality helps to keep the decentralized peg state\
consistent with BTC locked on Bitcoin L1, amongst other things.

</details>

<details>

<summary><strong>Scalable, fast transactions</strong></summary>

Scalable, fast transactions: will provide high performance and scalability through several\
mechanisms, including faster Stacks layer blocks. Further, scalability layers like subnets\
can make different tradeoffs between performance and decentralization than the main\
Stacks layer.

</details>

We can get an idea of the goal and ethos behind Stacks by looking at how Satoshi envisioned generalizing Bitcoin back in 2010:

> *"...to be a completely separate network and separate block chain, yet share CPU power with Bitcoin...all networks in the world would share combined CPU power, increasing the total strength."*

This is a major theme in the design decisions for Stacks. A bit of a contradiction in the Bitcoin world, the Stacks network is a Bitcoin L2, but it does have its own token. This is an intentional and critical design decision primarily for the purpose of maintaining decentralization, rather than needing to rely on a federation. If that's confusing or you are skeptical, that's understandable — we'll be diving deeper into these ideas as we go through the docs.

### Core technical components of Stacks

{% stepper %}
{% step %}
**Proof of Transfer**

Proof of Transfer (PoX) is the block production mechanism of the Stacks chain. Essentially, it attempts to recreate the block production patterns of PoW programmatically. Stacks miners spend BTC for a chance to mine new Stacks blocks. Under the hood, this block production mechanism anchors Stacks blocks to Bitcoin blocks, making it as hard to reverse a Stacks block as it is to reverse a Bitcoin block. That's a big claim, and we unpack it in further detail in the sections on Nakamoto block production.

[Learn more about PoX](/learn/stacks-101/proof-of-transfer)
{% endstep %}

{% step %}
**Stacks' Native Token: STX**

The Stacks layer’s native token (STX) is essential to PoX consensus: STX is needed for (a) incentivizing Stacks miners to maintain the Stacks layer global ledger outside the Bitcoin L1, and (b) incentives for threshold signers that participate in the peg mechanism. Existing approaches to Bitcoin pegs, which lack a native token, cannot support a permissionless, open system and fallback to using custodians or trusting known federation members.
{% endstep %}

{% step %}
**Clarity**

Clarity is the smart contract language that Stacks uses. It has been designed from the ground up to make it easier for developers to write safe, secure smart contracts. Additionally, since it has been purpose-built for Stacks and Bitcoin, there are built-in functions for reading Bitcoin state, which means you can use Bitcoin state to perform actions in Clarity. For example, you could set up a check to make sure a particular Bitcoin transaction has occurred before executing a mint function in Clarity, which just so happens to be what happens with the third component: sBTC.

[Learn more about Clarity](/learn/clarity)
{% endstep %}

{% step %}
**sBTC**

sBTC is the trust-minimized 2-way Bitcoin peg on the Stacks layer. sBTC is the key to making Bitcoin programmable and bringing full smart contract functionality to Bitcoin via Stacks. sBTC is not a federation, but operates as an open-network, decentralized 2-way peg solution to bring smart contract functionality to Bitcoin with as little counterparty risk as possible.

[Learn more about sBTC](/learn/sbtc)
{% endstep %}
{% endstepper %}

<details>

<summary><strong>Stacks and the Purpose of Blockchain Technology</strong></summary>

When evaluating new blockchain technologies, it's important to keep the original intent and purpose of them intact. If we go back to Bitcoin, it was originally designed to be:

* Decentralized
* Immutable
* Secure

You've likely heard of the blockchain trilemma — the problem of trying to balance decentralization, scalability, and security of a blockchain network. Stacks takes the approach of solving this trilemma by separating out chains into layers.

So at the bottom, you have the foundational layer: **Bitcoin**. Bitcoin is the most decentralized, most secure, and most immutable blockchain network. However, that comes with a few tradeoffs:

* Bitcoin is very slow compared to other networks. Bitcoin only has a new block written once every \~10 minutes, making its throughput negligible compared to networks designed for speed like Solana.
* Bitcoin is also "boring". Ethereum came along after Bitcoin and sought to do the same thing for software that Bitcoin did for money. Ethereum's goal is to be a decentralized supercomputer of sorts, serving as a global compute environment for smart contracts (code that is written to a blockchain).
* Bitcoin is not scalable. Because every new block must propagate to every node on the network, Bitcoin can only run as fast as the slowest node in the network.

Now we are seeing the rise of modular blockchain networks like Cosmos that are designed to make it easy for people to spin up their own blockchain networks. While most new blockchain protocols popping up these days see these properties as negatives and seek to eliminate them, the Stacks community sees things differently.

</details>

### The Stacks Way

{% embed url="<https://www.youtube.com/watch?v=U49tMeCLgnY>" %}

Stacks takes a layered approach: the foundational settlement layer is Bitcoin, and scalability and functionality are added on top of that using layers. There are many different types of L2s and different ways they can be built. They all come with different tradeoffs and have their own way of accomplishing the goals of scalability or functionality.

By taking this layered approach, we are able to have all of the same functionality as chains like Ethereum, but built on Bitcoin.

So Stacks is a Bitcoin layer 2 with some unique properties, like having its own token, that acts as an incentive mechanism to maintain a historical ledger of all of its transactions and operate with its own security budget (in addition to Bitcoin's security budget — more on this in the next section).

This is one of the things that separates Stacks from other Bitcoin layers like Lightning.

* Lightning doesn't add any additional functionality to Bitcoin; it simply helps to scale functionality Bitcoin already has and helps it operate faster. Lightning is also ephemeral — it has no permanent state — and so is unsuitable for things like smart contracts that need to keep track of data and maintain state.
* Contrast this to Stacks, which adds additional functionality to Bitcoin but still ultimately settles to Bitcoin (we'll cover this in the next section as well).

The benefit is that we can maintain a separation of concerns and keep Bitcoin simple and sturdy, chugging along producing blocks, while adding additional layers for functionality and speed. If those other layers were compromised, the foundational layer would remain unaffected. This is important when building systems intended to be a global decentralized money (Bitcoin) and a decentralized economy built on top of that money (Stacks).

With that context, let's dive into exactly how Stacks is connected to Bitcoin.

***

### Additional Resources

* \[[Stacks YT](https://www.youtube.com/watch?v=BmejRmkLxZU)] Muneeb gives a talk at the Stacks 2.0 Mainnet Launch event on January 14, 2021.


# The Bitcoin Connection

<div data-with-frame="true"><figure><img src="/files/73bENJOTfM5QYk24I3Nw" alt=""><figcaption></figcaption></figure></div>

In the previous section, we described Stacks as bringing smart contract functionality to Bitcoin, without modifying Bitcoin itself, and explained a bit about how the chain works. That's a big promise, but how does Stacks actually deliver on it? And what makes Stacks unique among other Bitcoin layers and other blockchains like Ethereum?

Before we get into the technical details of how Stacks works, it's important to get a high-level overview of the problem it's solving and how it actually does that. We'll dive deeper into some of these topics as we go through the docs, but it's good to get a high-level picture to bring everything together. This topic is a bit of a rabbit hole, but it will give you an in-depth understanding of exactly the problem Stacks is looking to solve, and how it solves it.

Let's get into it.

### What's the purpose of a Bitcoin layer?

The decentralization of trust is the primary innovation and promise of blockchains. Even in the\
world of cryptocurrencies, recent failures in 2022 have been of centralized entities, further\
highlighting the importance of systems that don’t rely on “trusted” centralized intermediaries.\
Bitcoin is the most secure, durable, and valuable blockchain; it is already used as a store of\
value by millions of people. It is robust, "hard" money, with unprecedented non-custodial\
ownership and lack of inflation. The Bitcoin blockchain is also the best settlement layer for\
transactions, as it is the most decentralized, censorship-resistant, and durable blockchain.

However, Bitcoin is relatively slow and minimal by design and conservative in its evolution to\
preserve these powerful properties. It produces blocks on average every 10 minutes, with only\
5-7 transactions per second. It does not provide native support for fully-expressive smart\
contracts and hence for sophisticated applications that can utilize its properties. The result is\
that Bitcoin has remained a passive rather than a productive asset. Despite its attractive and\
unique properties, it has not been a platform for applications besides a store of value and\
infrequent money movement.

Bitcoin layers change this. Bitcoin layers extend the functionality and performance of the\
Bitcoin blockchain without requiring any changes to it.

### How would we define what a Bitcoin layer is?

It is important to define what is meant by a Bitcoin layer. While there are several nuanced opinions on what makes a system a Layer 2 on top of a Layer 1, these are the properties we believe comprise an ideal Bitcoin L2 and the assumptions we make:

1. Open-source and decentralized development process
2. Full VM support and ability to program with expressive, high-level languages
3. Fast transaction and block times (don’t need to wait 10-30 minutes for Bitcoin blocks)
4. A trust-minimized way to move BTC between L1 and L2
5. BTC as the primary asset deployed in L2 apps
6. The ability to pay for L2 transactions in BTC
7. The ability to unilaterally withdraw your BTC back from the L2 with no counterparty risk

Stacks V1 had properties 1 and 2, but was missing the rest. The Nakamoto upgrade brings properties 3, 4, and 5, with discussions and work currently underway to accomplish 6. Currently, Lightning is the only L2 that has property 7, and the only way to truly take advantage of this is to run your own Lightning node, a complex undertaking few users engage in. Furthermore, Lightning is missing property 2, which means we cannot unlock any additional functionality beyond what that Bitcoin L1 is already capable of.

It’s important to acknowledge that Bitcoin L2s have fundamentally different goals than L2s on other L1s like Ethereum. While the primary motivation for L2s on Ethereum is to enhance\
scalability, Bitcoin L2s serve the purpose of enhancing both scalability and functionality.\
This means that the Bitcoin layer cannot verify the validity of transactions that occur on L2s\
like Stacks. Instead the VM for that layer is responsible for transaction processing and\
verification, and settling those transactions down to Bitcoin so that they share the same history\
and finality.

{% embed url="<https://www.youtube.com/watch?v=HUyFnGnA4FU>" %}

### Is Stacks a Bitcoin L2?

Stacks is a Bitcoin layer for smart contracts. The classification as a layer-1 (L1) or layer-2 (L2) or sidechain really depends on the definition used. With that said, generally speaking L1 chains are sovereign meaning that (a) they have their own security budget, and (b) they can survive without the need for any other L1 chain. L2 chains typically do not have their own security budget and share the security of the underlying L1 chain, and they cannot live without the underlying L1 chain. There are many different design mechanisms that L2s can use.

The initial release of Stacks in early 2021 had a separate security budget from Bitcoin L1. Even though the Stacks layer could not function without Bitcoin L1, the developers working on the project described it as a different system that does not fit neatly into existing classifications, sometimes using the term layer 1.5 (see [this Decrypt article](https://decrypt.co/82019/bitcoin-defi-thing-says-stacks-founder-muneeb-ali) for example).

The Nakamoto release in 2024 enabled Stacks to share the same security budget from Bitcoin. Instead, 100% of Bitcoin hashpower will determine finality on the Stacks layer. To reorg Stacks blocks/transactions the attacker will need to reorg Bitcoin L1 itself (which is very hard to do and therefore a great security property for a Bitcoin layer to have).

The definition of L2 used in Ethereum and other newer ecosystems is different and focuses on the ability to withdraw assets using only L1 security and L1 miners. According to that definition Stacks layer is not a clear L2, given the set of peg-out signers determine if users can withdraw sBTC. Bitcoin cannot support such verification without changes to Bitcoin L1 (which may happen in the future). The Ethereum L2 definition also does not apply that cleanly to Bitcoin L2s, given new assets are issued on L2s when it comes to Bitcoin and not issued on L1 (only BTC is the L1 asset). Therefore, using the definition of security of withdrawing assets is not directly applicable given assets are defined and used on L2s and not withdrawn out to Bitcoin L1 anyway (with the exception of BTC itself). Rather, what becomes more important is "settlement on Bitcoin" i.e., is contract data and state secured by 100% of Bitcoin's hashpower or not.

Remember that L2s on Bitcoin also have to serve the additional purpose of expanding both functionality and scalability, which means L2s accomplish fundamentally different goals depending on the functionality of the L1.

Users and developers organically call Stacks a Bitcoin L2, since it is a simpler concept to understand. There are certain properties of Stacks layer that also help the concept of Stacks as a Bitcoin L2:

{% stepper %}
{% step %}
**Bitcoin finality**

100% of the Bitcoin hashpower decides block ordering and transaction finality.
{% endstep %}

{% step %}
**Consensus runs on Bitcoin**

Stacks consensus runs on Bitcoin L1, and Stacks L2 cannot operate or survive without Bitcoin L1.
{% endstep %}

{% step %}
**sBTC and economic unit**

With the decentralized Bitcoin peg, sBTC, most of the economy on Stacks layer will use BTC as the unit of economy. It is expected that most users will simply use Bitcoin in wallets and apps and then peg out their BTC to Bitcoin L1.
{% endstep %}

{% step %}
**Data hashed and stored on Bitcoin**

All data and transactions on Stacks are automatically hashed and permanently stored on Bitcoin L1 on every Bitcoin block. Anyone can verify that some data on Stacks is valid by checking the corresponding hash on Bitcoin. This compact storage of hashes on the L1 is somewhat similar to rollups (although there are other differences). You can read more about this process in the [Block Production](/learn/block-production) section.
{% endstep %}

{% step %}
**Contracts can read Bitcoin state**

Contracts on Stacks layer can read Bitcoin L1 transactions and respond to them. Assets on Stacks layer can be moved simply through Bitcoin L1 transactions.
{% endstep %}
{% endstepper %}

<details>

<summary><strong>Addressing the skeptics and critics</strong></summary>

Given all the details above, why would some people think that Stacks is not a Bitcoin L2? There are a couple of reasons this question comes up often:

* **Old security-budget material**: The initial version of Stacks (released early 2021) had a separate security budget which changed to inherit 100% Bitcoin hashpower with the Nakamoto release.
* **Ethereum L2 withdrawal definition doesn't map cleanly**: According to the Ethereum definition of L2s a user should be able to withdraw their base-layer assets purely by doing an L1 transaction and relying only on L1 security (this is true for Lightning for example). This definition does not apply cleanly to Bitcoin L2s because assets are not defined at Bitcoin L1 but are defined in L2s instead. The only asset where this matters is the pegged BTC asset from Bitcoin L1, given all other assets are native to L2s anyway. In the upcoming Stacks release, users can withdraw their BTC by sending just a Bitcoin L1 transaction but Bitcoin L1 cannot validate that complex transaction and a majority of peg-out signers will need to sign on the peg-out request. In an ideal world Bitcoin miners can validate such transactions but that would require a change to Bitcoin L1. Therefore, Stacks design optimizes for a method that is decentralized and can be deployed without any changes to Bitcoin L1. If in the future it is possible to make changes to Bitcoin L1 then Stacks layer security can benefit from that as well.
* **Healthy Bitcoin skepticism**: Bitcoin community members are generally skeptical of claims and on the lookout for people making any false marketing claims. This is generally a healthy thing for the Bitcoin ecosystem and builds up the immune system. Some such community members might be skeptical about Stacks as a Bitcoin layer or L2 until they fully read the technical details and reasoning. There is a good Twitter thread about this topic as well.

</details>

Why don't we use the term 'sidechain' for Stacks then? Sidechains in Bitcoin typically have a different security budget from the Bitcoin L1, typically as a subset of Bitcoin miners who participate in the sidechain (they don't follow 100% Bitcoin finality), their consensus runs on the sidechain (vs running on Bitcoin L1), and they don't publish their data/hashes on Bitcoin L1. The Stacks layer does not fit that definition cleanly given the consensus runs on Bitcoin L1, it follows Bitcoin finality, and publishes data/hashes on L1.

### The Symbiotic Relationship Between Stacks and Bitcoin

Stacks and Bitcoin complement each other. Stacks leverages the extreme decentralization of Bitcoin, its PoW consensus mechanism, and its value as a cryptocurrency.

But Stacks also complements Bitcoin by unlocking additional use cases, thereby increasing its value over time. This also helps to solve the additional problem of the future maintainability of Bitcoin after the coinbase rewards are gone and Bitcoin has to function on transaction fees alone.

{% embed url="<https://twitter.com/muneeb/status/1506976317618728963>" %}

If Bitcoin is seen as only a store of value, the economic density, meaning how much value is being exchanged, of each transaction will be minimal. But if Bitcoin is the underlying foundation for an entire decentralized economy, those transactions become much more valuable, increasing transaction fees. This is a crucial incentive for miners to continue securing the network as coinbase rewards drop.

### On Crafting a Bitcoin-First Developer Experience

One of the things that gives the Stacks network its superpowers in connecting with Bitcoin is not only how it connects to Bitcoin at a protocol level, discussed above, but also how we can utilize that Bitcoin at a programmatic level.

The DevEx for a Bitcoin L2 should abstract away Bitcoin’s complexity but also maintain the *feeling* of building on Bitcoin. Sounds like a contradiction but here's how Stacks pulls it off:

{% stepper %}
{% step %}
**Sustain bitcoin movements with sBTC**

<div data-with-frame="true"><figure><img src="/files/jiVjoh6RASj8WogIkODa" alt=""><figcaption></figcaption></figure></div>

sBTC unlocks Bitcoin’s programmability. You get L2 expressivity without losing Bitcoin’s familiar properties: denomination, representation, and trust model.
{% endstep %}

{% step %}
**Plug directly into BTCFi**

<div data-with-frame="true"><figure><img src="/files/6VSq0XcEAwCS0MQvuTvX" alt=""><figcaption></figcaption></figure></div>

Zest, Bitflow, StackingDAO, Dual Stacking, and other major DeFi protocols on Stacks offer developer tooling for smart, composable, and Bitcoin-first applications.
{% endstep %}

{% step %}
**One cryptographic identity**

<div data-with-frame="true"><figure><img src="/files/6s7rBOaJli1dOcxYeiM3" alt=""><figcaption></figcaption></figure></div>

Stacks uses the *same* cryptographic primitive — same curve (secp256k1), same `hash160` construction — to derive Stacks addresses. They’re formatted differently (different version bytes / encoding), but underneath: the identity anchor is the same 20-byte public key hash.

Different layers. Same cryptographic private key.
{% endstep %}

{% step %}
**React to Bitcoin state**

<div data-with-frame="true"><figure><img src="/files/5wGByb0bgotLEMVXDrbe" alt=""><figcaption></figcaption></figure></div>

One of the often-touted features of Clarity is that it has access to the state of the Bitcoin chain built in, but how does it actually do that? Because of Stacks' PoX mechanism, every Stacks block is connected to a Bitcoin block, and can query Bitcoin block header hashes with the `get-burn-block-info?` function.

Clarity can read Bitcoin state directly. Parse BTC transactions. Trigger logic based on Bitcoin activity.
{% endstep %}

{% step %}
**Capture time on the L2 at Bitcoin speed**

<div data-with-frame="true"><figure><img src="/files/5fgOPxeU41TdyAJ6OlPI" alt=""><figcaption></figcaption></figure></div>

Clarity contracts can measure time by Bitcoin blocks. This is not just technical — it's symbolic: Like tracking time by the sun, we trust Bitcoin’s cadence.
{% endstep %}
{% endstepper %}

***

### Additional Resources

* \[[Hiro Blog](https://www.hiro.so/blog/building-on-bitcoin-project-comparison)] Building on Bitcoin: a Comparison of Bitcoin Projects
* \[[Hiro Books](https://www.hiro.so/books/a-beginners-guide-to-bitcoin-layers)] A Beginner's Guide to Bitcoin Layers
* \[[Stacks YT](https://www.youtube.com/watch?v=F31B-my510A)] The Stacks & Bitcoin Miners Relationship


# Proof of Transfer (PoX)

<div data-with-frame="true"><figure><picture><source srcset="/files/eEXaz8fjg3UCeKOJGGhT" media="(prefers-color-scheme: dark)"><img src="/files/znUwMWwgmZklKy1QbUPt" alt=""></picture><figcaption></figcaption></figure></div>

In the previous sections, we took a look at the vision and ethos of Stacks and talked a lot about it being connected to Bitcoin and how it enables expanding functionality without modifying Bitcoin itself. In this section, we'll run through the block production mechanism that makes that happen, Proof of Transfer.

{% hint style="info" %}
This section will be a conceptual overview of Proof of Transfer. For more details on exactly how block production happens at a technical level, check out the section on [Block Production](/learn/block-production).
{% endhint %}

### What is Proof of Transfer?

The Stacks layer relies on STX and on BTC for its novel consensus mechanism, called Proof\
of Transfer (PoX), that utilizes both the Stacks and Bitcoin layers. PoX is similar in spirit to\
Bitcoin’s Proof of Work (PoW) consensus: Like how Bitcoin PoW miners spend electricity and\
are rewarded in BTC, Stacks PoX miners spend (already mined) BTC and are rewarded in STX.

Like PoW, PoX uses a single-leader election: PoX miners bid by simply spending BTC, and they have a bid-weighted random probability of becoming a leader. Leader election happens on the Bitcoin chain and new blocks are written on the Stacks layer. In this way, PoX reuses work already done by Bitcoin miners, and does not consume any significant amount of additional electricity: only the cost of running normal laptops/computers for Stacks nodes to bid using BTC.

Like PoW, PoX is permissionless: Anyone can be a Stacks miner, as long as they are willing\
to spend BTC. Also, any STX holder can lock their STX (called “stacking”) to participate in\
PoX consensus, and earn Bitcoin rewards for doing useful work for the system, i.e., for being a\
signatory for the decentralized Bitcoin peg. In keeping with Bitcoin ethos, Stackers are\
rewarded for their positive contributions to the system and inhibited by economic disincentives\
from behaving poorly (but unlike in bonded Proof of Stake systems, they are not "slashed").

Finally, the nature of PoX consensus is such that the price ratio between BTC and STX is\
continually recorded and available on-chain, serving as an on-chain Bitcoin price oracle. This is\
valuable for the decentralized peg, removing the need for an external oracle, as described in the\
companion paper about the peg.

The below diagram flowcharts the PoX consensus mechanism amongst its relevant participants.

<div data-with-frame="true"><figure><img src="/files/fL0ACP0eOnhv5R0S8KLH" alt=""><figcaption></figcaption></figure></div>

As depicted in the flowchart, Proof of Transfer also provides two critical dynamics that work together to secure and operate the network.

1. **Economic** – BTC is transferred from miners to stackers, creating a bidirectional incentive structure rooted in Bitcoin itself. Miners commit BTC to participate in block production, effectively competing for the right to produce the next Stacks block. In return, successful miners earn newly minted STX and transaction fees. Stackers, on the other hand, lock their STX to support consensus and receive the BTC committed by miners as a reward. This mechanism ties the Stacks economy directly to Bitcoin, aligning incentives across participants and anchoring security in a real, external asset rather than relying solely on inflation or internal token mechanics.
2. **Programmatic** – Beyond economic incentives, PoX provides the technical coordination layer that determines how blocks are produced, validated, and finalized. Miner BTC commitments on Bitcoin serve as inputs into leader selection, which determines who can construct the next Stacks block. Once produced, blocks are cryptographically linked and anchored to Bitcoin, inheriting its settlement assurances. In this way, PoX is not just an economic exchange mechanism — it is the consensus engine that orchestrates block construction, ordering, and finality while maintaining a verifiable connection to Bitcoin L1.

### Who are the participants in Proof of Transfer?

<div data-with-frame="true"><figure><img src="/files/gVOJmyBP21UYGKGgknPK" alt=""><figcaption></figcaption></figure></div>

***

### Breakdown of PoX's Core Components

<details>

<summary>Leader Election (Miners)</summary>

**Who gets to mine the next tenure of Stacks blocks?**

**Participants: Miners**

* Idea: Spend BTC to win a chance at producing blocks
* Single-leader election through *cryptographic sortition*
* Embed *verifiable random function* (VRF) state in Bitcoin transactions
* Deterministic but unpredictable winner at each Bitcoin block
* Mining through block commits: (block hash, VRF seed) pair
* VRF seed = hash(VRF proof)

</details>

<details>

<summary>Reward Set (Stackers)</summary>

**But where does the BTC spent by miners go?**

**Participants: Stackers that are either solo stacking or pool stacking**

* Idea: Spent BTC (from miners) are sent to STX holders
* Expected BTC payout is a function of your-lockup over total-lockup
* Locked STX never leave your account, and will unlock automatically
* Takes unproductive STX our of circulation
* Reward Cycle: 2100 Bitcoin blocks
* Reward Phase: first 2000 Bitcoin blocks
* Prepare Phase: last 100 Bitcoin blocks
* Anchor block: first Stacks block confirmed in prepare phase
* Reward Set: snapshot of locked STX in anchor block

<div data-with-frame="true"><figure><img src="/files/WRwCVGqPHRHUejmodtCs" alt=""><figcaption></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/OSXakemGFsNwdFFZIk7J" alt=""><figcaption></figcaption></figure></div>

</details>

<details>

<summary>Block Signers (Signers)</summary>

**Can locked STX secure the network as well?**

**Participants: Stackers that are taking on the role of a Signer**

* Idea: Use PoX yield to incentivize good chain QoS
* PoX yield as a salary to replicate and sequence blocks
* Stacks select Signer public key when they stack
* Signers sign blocks from miner with weighted signature (by # reward slots)
* Once 70%+ of reward slots sign off, block is appended
* Block signer set changes once per reward cycle
* 70%+ or more signers assumed to be online and honest
* Honest Signers vote to withhold (burn) faulty Stackers' subsequent BTC

<div data-with-frame="true"><figure><img src="/files/tcSuXIIUV9XBUWd9DGgo" alt=""><figcaption></figcaption></figure></div>

</details>

***

### Technical Implementation Details

The Proof of Transfer functionality is implemented on the Stacks network as a Clarity smart contract.

Proof of Transfer has went through multiple iterations over the years. Below lists the different smart contract implementations of Proof of Transfer.

<table><thead><tr><th width="107.99609375">Version</th><th width="131.1015625">Date</th><th width="228.8671875">Mainnet Contract</th><th data-type="content-ref">SIP</th></tr></thead><tbody><tr><td>PoX 4</td><td>2024-04-22</td><td><a href="https://explorer.hiro.so/txid/SP000000000000000000002Q6VF78.pox-4">SP000000000000000000002Q6VF78.pox-4</a></td><td><a href="https://github.com/stacksgov/sips/blob/main/sips/sip-021/sip-021-nakamoto.md">https://github.com/stacksgov/sips/blob/main/sips/sip-021/sip-021-nakamoto.md</a></td></tr><tr><td>PoX 3</td><td>2023-05-27</td><td><a href="https://explorer.hiro.so/txid/SP000000000000000000002Q6VF78.pox-3">SP000000000000000000002Q6VF78.pox-3</a></td><td><a href="https://github.com/stacksgov/sips/blob/main/sips/sip-022/sip-022-emergency-pox-fix.md">https://github.com/stacksgov/sips/blob/main/sips/sip-022/sip-022-emergency-pox-fix.md</a></td></tr><tr><td>PoX 2</td><td>2023-03-20</td><td><a href="https://explorer.hiro.so/txid/SP000000000000000000002Q6VF78.pox-2">SP000000000000000000002Q6VF78.pox-2</a></td><td><a href="https://github.com/stacksgov/sips/blob/main/sips/sip-015/sip-015-network-upgrade.md">https://github.com/stacksgov/sips/blob/main/sips/sip-015/sip-015-network-upgrade.md</a></td></tr><tr><td>PoX 1</td><td>2021-01-15</td><td><a href="https://explorer.hiro.so/txid/SP000000000000000000002Q6VF78.pox">SP000000000000000000002Q6VF78.pox</a></td><td><a href="https://github.com/stacksgov/sips/blob/main/sips/sip-007/sip-007-stacking-consensus.md">https://github.com/stacksgov/sips/blob/main/sips/sip-007/sip-007-stacking-consensus.md</a></td></tr></tbody></table>

A walkthrough of the current PoX 4 contract is available in the [Example Contracts](/cookbook/clarity/example-contracts) section.

***

### Wrapping it up: PoX in a nutshell

• PoX selects a randomized single-leader block miner once per BTC block\
• PoX incentivizes miners to make STX blocks and earn STX coinbase + tx fees\
• PoX incentivizes STX holders to lock up STX to get BTC yield from miners\
• PoX disincentivizes BTC L1 miners from interfering\
• PoX incentivizes Stackers, as a Signer, to keep the network healthy

***

### Additional Resources

* \[[SIP-001](https://github.com/stacksgov/sips/blob/main/sips/sip-001/sip-001-burn-election.md)] SIP-001 provides a full list of reasons why Bitcoin was chosen to secure Stacks.
* \[[SIP-007](https://github.com/stacksgov/sips/blob/main/sips/sip-007/sip-007-stacking-consensus.md)] Details of the original design for stacking and Proof of Transfer.
* \[[SIP-021](https://github.com/stacksgov/sips/blob/main/sips/sip-021/sip-021-nakamoto.md)] Nakamoto Upgrade: Fast and reliable blocks
* \[[Stacks Developers YT](https://youtu.be/YynwIJIXJWw?si=9DXsd9PzMN14xt-L)] PoX: Under the Hood
* \[[Stacks Developers YT](https://youtu.be/4UJ3ZK8JsrI?si=m8VSVIuCwIyOe3pe)] How Do Developers Test the Stacks Network?
* \[[Hiro YT](https://youtu.be/2Bmo1cK0C8k?si=uiYaXudIhjxkNaS6)] A Breakdown of Stacks' Proof of Transfer Smart Contract


# Network Fundamentals


# Mainnet and Testnets

<div data-with-frame="true"><figure><img src="/files/oI2mmqFvBzXQXuc8UcWZ" alt=""><figcaption></figcaption></figure></div>

Stacks has both a mainnet and a testnet for different purposes. Mainnet and testnet are two completely different public networks and tokens cannot be transferred between one or the other.

### Tech Specs for Mainnet and Testnet

<table><thead><tr><th width="215.19140625"></th><th width="244.26953125">Mainnet</th><th>Testnet</th></tr></thead><tbody><tr><td>Chain ID</td><td><code>1</code></td><td><code>2147483648</code></td></tr><tr><td>Transaction Version</td><td><code>0</code></td><td><code>128</code></td></tr><tr><td>Magic Bytes</td><td><code>X2</code></td><td><code>T2</code></td></tr><tr><td>Explorer</td><td><a href="https://explorer.hiro.so/">https://explorer.hiro.so/</a></td><td><a href="https://explorer.hiro.so/?chain=testnet">https://explorer.hiro.so/?chain=testnet</a></td></tr><tr><td>Stacks API Base URL</td><td><a href="https://api.hiro.so">https://api.hiro.so</a></td><td><a href="https://api.hiro.so">https://api.testnet.hiro.so</a></td></tr><tr><td>Address Format / Version</td><td><strong>SP</strong>3B108...2DNJA0 / <code>22</code></td><td><strong>ST</strong>3B108P...EQEZY5 / <code>26</code></td></tr><tr><td>Multisig Format / Version</td><td><strong>SM</strong>3RWH...5X9DXM / <code>20</code></td><td><strong>SN</strong>8NKFP...2NAQJA / <code>21</code></td></tr><tr><td>Genesis Block</td><td><a href="https://explorer.hiro.so/block/0x6b2c809627f2fd19991d8eb6ae034cb4cce1e1fc714aa77351506b5af1f8248e?chain=mainnet">Block #1</a></td><td><a href="https://explorer.hiro.so/block/0xc9938007fe5f8cc312d782349a6cfbaee7598e08acc4f4da31c876a4b16d4153?chain=testnet">Block #1</a></td></tr><tr><td>sBTC contract</td><td><a href="https://explorer.hiro.so/token/SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token?chain=mainnet">SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token</a></td><td><a href="https://explorer.hiro.so/txid/ST1F7QA2MDF17S807EPA36TSS8AMEFY4KA9TVGWXT.sbtc-token?chain=testnet">ST1F7QA2MDF17S807EPA36TSS8AMEFY4KA9TVGWXT.sbtc-token</a></td></tr></tbody></table>

### Mainnet

Stacks mainnet is directly anchored to the Bitcoin mainnet and its the network where tokens have actual monetary worth. This is the production network and should be treated as such.

### Testnet

The Stacks testnet serves as a live public sandbox for developers, allowing them to build, test, and iterate on apps and smart contracts in an environment that mimics the mainnet. It provides a risk-free space to experiment with changes or new features before deploying them on the Stacks mainnet, ensuring that everything functions correctly without the risk of real financial loss.

#### Testnet Faucets

Testnet faucets provide you with mock Stacks (STX) tokens to test with. These testnet STX have no value and are not the same as STX on mainnet. There are a couple of different options for getting testnet STX.

{% tabs %}
{% tab title="Platform" %}
You can get testnet STX from the [Platform](https://platform.hiro.so/faucet), which is the recommended way.

To get STX tokens from within the Platform, navigate to the "Faucet" tab at the top. You can then choose either testnet STX or sBTC, and then paste in your desired testnet STX address to receive.

<div data-with-frame="true"><figure><img src="/files/pbai3LoKAprHvNXt9uUG" alt=""><figcaption></figcaption></figure></div>
{% endtab %}

{% tab title="Sandbox" %}
Using the faucet provided by the [Explorer Sandbox](https://explorer.hiro.so/sandbox/deploy?chain=testnet) is another option.

You'll first need to connect your wallet to the Explorer Sandbox and hit 'Request STX'. Be sure your wallet is on the testnet network before requesting.

<div data-with-frame="true"><figure><img src="/files/19xDPUA1qfqrqunG80C6" alt=""><figcaption></figcaption></figure></div>
{% endtab %}

{% tab title="LearnWeb3" %}
Alternatively, you can use the [LearnWeb3 faucet](https://learnweb3.io/faucets).

<div data-with-frame="true"><figure><img src="/files/4YrgagLRsKKy1cLjPHou" alt=""><figcaption></figcaption></figure></div>
{% endtab %}
{% endtabs %}


# Tokens

<div data-with-frame="true"><figure><img src="/files/qZDbk9Ba5XF8d78ST3NT" alt=""><figcaption></figcaption></figure></div>

### STX

Stacks (STX) tokens are the native tokens on the Stacks network. The smallest fraction is one micro-STX: 1,000,000 micro-STX make one Stacks (STX). STX amounts should be stored as integers (8 bytes long), and represent the amount of micro-STX.

STX is central to the consensus mechanism of the Stacks Bitcoin layer, discussed below, and is essential for two key goals: (i) it incentivizes mining of Stacks blocks with a “new block subsidy,” which is critical since transaction fees are not enough to sustain a ledger at least in the early days (as is the case with Bitcoin itself), and (ii) it serves as a liveness incentive and the basis for the economically secured decentralized Bitcoin peg.

<details>

<summary>Why Does Stacks Need a Token?</summary>

This brings us to a central philosophical conversation in the world of crypto and Bitcoin, whether or not blockchains need tokens. Let's start by looking at the fundamental reason why tokens exist: to fund the maintenance and forward progress of a blockchain.

Bitcoin is a token. It is a cryptocurrency that is used to incentivize miners to add new blocks to the chain. In Bitcoin's case, mining rewards are set on a predefined schedule, and once those mining rewards run out, the chain will need to survive on transaction fees alone.

The purpose of a blockchain is to have a permanent historical record of every transaction that has ever occurred on the chain. Blockchains are basically ledgers. The token aspect is used as an incentive mechanism to secure and maintain the chain.

This is why networks like Lightning and other P2P networks don't need tokens, they don't need to maintain a historical record. Channel-based solutions like Lightning rely on users opening 2-of-2 multisigs with each other. Once those channels are closed, the state disappears. When we are talking about a system that is supposed to maintain a global financial system, it is important for the maintenance of that system to be incentivized correctly.

Let's look at this concept in the context of Stacks and its goals. Stacks seeks to provide smart contract functionality to Bitcoin, to serve as the programming rails for building a decentralized economy on top of Bitcoin.

Many Bitcoin community members are skeptical of new tokens and rightly so. There are countless projects out there that force the use of a token on their project and in many cases a token is actually not needed. The Stacks project was started by Bitcoin builders who have a long history of building apps & protocols on Bitcoin L1 without any token (e.g., BNS launched in 2015 on Bitcoin L1 which was one of the largest protocols using OP\_RETURN on Bitcoin L1). So why did a bunch of Bitcoin builders decide to have a separate token for Stacks L2? Great question! Let's dig into the details.

The Stacks token (STX) is primarily meant to be used for two things:

1. **Incentives for Stacks L2 miners**: Newly minted STX are used to incentivize decentralized block production on Stacks L2.
2. **Incentives for peg-out signers**: Signers participating in peg-out operations receive incentives in STX to economically align them with protocol rules.

The only way to remove the token is to build Stacks as a federated network like Liquid. In a federation the pre-selected group of companies control the mining and block production and a pre-selected group of companies need to be trusted for peg-out transactions.

Stacks developers wanted to design an open and permissionless system. The only way to have a decentralized mining process is through incentives. As mentioned above, this is how Bitcoin works as well, where newly minted BTC are used as incentives to mine new blocks and anyone in the world can decide to become a miner. Anyone with BTC can mine the Stacks L2 chain, it is open and permissionless.

Similarly, the way sBTC is designed is that the group of signers is open and permissionless (unlike a federation). These signers have economic incentives to correctly follow the protocol for peg-out requests. In a federation, users need to blindly trust the pre-set federation members to get their BTC out of the federation and back on Bitcoin L1. Stacks developers wanted to have an open, permissionless, and decentralized way to move BTC from Bitcoin L1 to Stacks L2 and back. This is made possible through economic incentives i.e., need for a token.

Other than these two reasons, STX is also used to pay gas fees for transactions. However, once the upcoming sBTC peg is live most of the economy of Stacks L2 is expected to follow a Bitcoin standard and work using BTC as the economic unit. It is expected that users will mostly interact just with Bitcoin and use BTC in wallets and apps (gas fees can be paid with BTC using atomic swaps in the background). It is important to note that BTC cannot be used for mining incentives on Stacks L2 because the only way to incentivize decentralized block production is through newly minted assets by the protocol (similar to how Bitcoin works itself) i.e., need for a token.

</details>

<a href="https://youtu.be/Khfl50J7v6s?si=AkG2x9VIWsrCUoSL" class="button primary">How to get STX</a>

### sBTC

sBTC is a decentralized, trust-minimized two-way Bitcoin peg between Bitcoin and the Stacks\
blockchain. Implemented as a SIP-010 compliant fungible token on Stacks, sBTC enables\
Bitcoin holders to securely represent their BTC as tokens on the Stacks chain without relying\
on a single trusted entity. This bridge allows Bitcoin to be seamlessly integrated into the Stacks\
ecosystem, significantly expanding Bitcoin’s utility through programmable smart contracts\
while maintaining its fundamental security properties.

<a href="/pages/5fe9d375914f8feb7f8a95ae3ac1df4de7e32df9" class="button primary">Learn more about sBTC</a>

### SIP-010 Fungible Tokens

[SIP-010](https://github.com/stacksgov/sips/blob/main/sips/sip-010/sip-010-fungible-token-standard.md) is the standard for defining fungible tokens on Stacks. Defining a common interface (known in Clarity as a "trait") allows different smart contracts, apps, and wallets to interoperate with fungible token contracts in a reusable way.

<a href="/spaces/Zz9BLmTU9oydDpL3qiUh/pages/2ada92fea142818fc430f159e743491371454aa3" class="button primary">Create a fungible token</a>

### SIP-009 Non-Fungible Tokens

[SIP-009](https://github.com/stacksgov/sips/blob/main/sips/sip-009/sip-009-nft-standard.md) is the standard for defining fungible tokens on Stacks. Defining a common interface (known in Clarity as a "trait") allows different smart contracts, apps, and wallets to interoperate with non-fungible token contracts in a reusable way. Its primary purpose is to ensure that NFTs are composable and different tools know how to interact with them.

<a href="/spaces/Zz9BLmTU9oydDpL3qiUh/pages/bd58e1eac29d5759d461845b382eae320b7ec9a0" class="button primary">Create a non-fungible token</a>

### SIP-013 Semi-Fungible Tokens

Semi-fungible tokens (SFTs) are a hybrid token structure that embraces parts of both FTs (fungible tokens) and NFTs. SFTs are interchangeable (like FTs) and can be traded between users like cash—1 SFT has the same value as another SFT in the same collection. But each SFT also has a unique identifier (like NFTs).

[SIP-013](https://github.com/stacksgov/sips/blob/main/sips/sip-013/sip-013-semi-fungible-token-standard.md) is the standard for defining semi-fungible tokens on Stacks. Defining a common interface (known in Clarity as a "trait") allows different smart contracts, apps, and wallets to interoperate with semi-fungible token contracts in a reusable, standard way.

<a href="/spaces/Zz9BLmTU9oydDpL3qiUh/pages/wUVy26Q0w65RaDKGt3lG" class="button primary">Create a semi-fungible token</a>


# Wallets & Accounts

<div data-with-frame="true"><figure><img src="/files/79GKZXBXaLop4EGQcSGc" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
In Stacks, the terms 'address' and 'principal' are used interchangeably.
{% endhint %}

## Introduction

Stacks wallets are software or hardware tools for storing cryptocurrencies, NFTs, and other digital assets. They are also used for establishing on-chain identity in decentralized applications (dApps). These wallets cryptographically store and manage each user’s identity and funds through a single blockchain address, which leverage public-key cryptography.

### Purpose of a Stacks wallet

* Establish User Identity
* Store Assets
* Display Balances
* Sign Transactions
* Sign Messages
* Participate in the Bitcoin Economy

Wallets in Stacks consists of accounts, which uses an accounts-based model, rather than a UTXO model like Bitcoin. This model is simpler than the UTXO model and has a more traditional concept of “balance”, similar to what you would encounter at a bank. In this model, each address has a single “balance” figure for a given token that increases/decreases as transactions are sent to/from that account. This is what most Web3 ecosystems use. In a UTXO model, the network operates as a ledger, with each UTXO being analogous to a cash bill.

### Components of a Stacks account

<div data-with-frame="true"><figure><img src="/files/QW9Z6UjJO3oB4PTia8N0" alt=""><figcaption></figcaption></figure></div>

* **Private Key** - The private key is an alphanumeric code that is paired to a single public key on a 1:1 basis. Never share your private key with anyone. A private key is how you prove ownership of a public key and how you can spend assets held by that particular key-pair.\
  \
  Example private key in Stacks (32 bytes appended with a 0x01 byte):\
  `5a4133fec2cf923d37238d3ba2fcd2ee9c8dce882c22218fd210d8a02ceb2c7401`
* **Public Key** - The public key is derived mathematically from the private key. It can be shared safely and is used by the network to verify signatures created by the private key, without revealing the private key itself.\
  \
  Example public key in Stacks (compressed format):\
  `02e8eb87862945d369511fdcce326ffef9a01b68c7d070e3ce685a5cbb9b1ecfc5`
* **Address (Principal)** - The address is a shorter, user-friendly representation derived from the public key. It’s what you share to receive sBTC, STX, tokens, or NFTs on Stacks, and it acts as the on-chain identifier for the user.\
  \
  Example public address in Stacks (c32check encoding):\
  `SPM9G3CNGSCTB4956290NESM0MR9W9CCEPVEPSQC`

{% hint style="info" %}
The private/public key generation uses the cryptographic **secp256k1** curve.

The cryptographic signature algorithm used in Stacks is **ECDSA** over **secp256k1**.

Addresses are created by generating the **RIPEMD-160** hash of the **SHA256** of the public key. BTC addresses are encoded with **Base58Check**. For Stacks addresses, [**c32check**](https://github.com/stacks-network/c32check) is used.
{% endhint %}

Stacks accounts are entities that own assets, like Stacks (STX) tokens. An account has an address, private key, nonce, and one or more asset balances. Assets cannot leave an account without an action from the account owner. All changes to assets (and the balances of the account) require a corresponding transaction.

All Stacks wallets also support Bitcoin addresses, enabling seamless participation across both the Stacks and Bitcoin ecosystems.

#### Address formats <a href="#address-formats" id="address-formats"></a>

Stacks addresses use different prefixes to indicate the network they belong to, making it easy to distinguish between mainnet and testnet addresses.

```typescript
// Mainnet address starts with 'SP'
const mainnetAddress = 'SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159';

// Mainnet multisig address starts with 'SM'
const multisigMainnetAddress = 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4'

// Testnet multisig address starts with 'SN'
const multisigTestnetAddress = 'SNJSPGVBFZHPXGESC9ZQWVFSNF4RHNNRTW2HYYJ7'

// Testnet address starts with 'ST'
const testnetAddress = 'ST2F4BK4GZH6YFBNHYDDGN4T1RKBA7DA1BJZPJEJJ';
```

***

## How to create a Stacks account?

A wallet's account are generated from a 24-word mnemonic phrase conforming to the BIP39 standard. This is often referred to as the **seed phrase**. The seed phrase provides access to Stacks accounts.

{% hint style="danger" %}
If the seed phrase is lost, access to the associated accounts cannot be restored. No person or organization can recover a lost seed phrase.
{% endhint %}

There are a few different ways to create a Stacks account as both a developer and non-developer.

{% stepper %}
{% step %}

#### Using Stacks.js

For programmatic wallet generation or when restoring accounts from backup, you can derive addresses from a mnemonic seed phrase. Each wallet can contain multiple accounts, all derived from the same seed phrase using different derivation paths.

{% code expandable="true" %}

```typescript
import { generateWallet, generateSecretKey, type Wallet, Account } from '@stacks/wallet-sdk';
import { privateKeyToAddress, privateKeyToPublic } from '@stacks/transactions'

// Generate a new 24-word seed phrase
const secretKey: string = generateSecretKey();

// Or use an existing seed phrase
// const secretKey = 'already owned seed phrase ...';

const wallet: Wallet = await generateWallet({
  secretKey,
  password: 'optional-encryption-password',
});

// Get the first account's public key and address
const account: Account = wallet.accounts[0];
const publicKey = privateKeyToPublic(account.stxPrivateKey);
const mainnetAddress = privateKeyToAddress(account.stxPrivateKey, 'mainnet');

console.log('Private key:', account.stxPrivateKey);
console.log('Address:', mainnetAddress);
// Private key: 97ff523937735dc6c9e3180f98a6aa94f526fbe072230b99e07482260f59988c01
// Address: SP1WNA65XE3M665RJ9AC81J18XPMJ5QC5XJDHWXE
```

{% endcode %}

For more ways on programmaticly generating keys and accounts, check out the guide [here](/stacks.js/accounts-and-addresses).
{% endstep %}

{% step %}

#### Using the Stacks CLI tool

Using the Stacks CLI tool allows you to manage wallets on the command line.

**`make_keychain`**

```bash
# Install CLI globally
npm install --global @stacks/cli

# Generate a new account and store details in a new file.
# '-t' option makes this a testnet account
stx make_keychain -t > cli_keychain.json

# make_keychain outputs the following:
{
  "mnemonic": "aaa bbb ccc ddd ...",
  "keyInfo": {
    "privateKey": "5a3f1f15245bb3fb...",
    "address": "STJRM2AMVF90ER6G3RW1QTF85E3HZH37006D5ER1",
    "btcAddress": "biwSd6KTEvJcyX2R8oyfgj5REuLzczMYC1",
    "wif": "L4HXn7PLmzoNW...",
    "index": 0
  }
}
```

**`get_address`**

```bash
# Get the address of a private key or multisig private key bundle.
# Gives the BTC and STACKS addresses

stx get_address f5185b9ca93bdcb5753fded3b097dab8547a8b47d2be578412d0687a9a0184cb01
{
  "BTC": "1JFhWyVPpZQjbPcXFtpGtTmU22u4fhBVmq",
  "STACKS": "SP2YM3J4KQK09V670TD6ZZ1XYNYCNGCWCVVKSDFWQ"
}

stx get_address 1,f5185b9ca93bdcb5753fded3b097dab8547a8b47d2be578412d0687a9a0184cb01,ff2ff4f4e7f8a1979ffad4fc869def1657fd5d48fc9cf40c1924725ead60942c01
{
  "BTC": "363pKBhc5ipDws1k5181KFf6RSxhBZ7e3p",
  "STACKS": "SMQWZ30EXVG6XEC1K4QTDP16C1CAWSK1JSWMS0QN"
}
```

For more usage examples, check out the Stacks CLI repo [here](https://github.com/stx-labs/stacks.js/tree/main/packages/cli).
{% endstep %}

{% step %}

#### Using Bitcoin L2 wallet extensions/apps

There are many popular Bitcoin wallets that support Bitcoin layers and metaprotocols. Leather and Xverse are popular options for getting started with Stacks.

{% embed url="<https://youtu.be/RvTuex1jbGY?si=KGEGESS3sr38G_Tj>" %}
{% endstep %}

{% step %}

#### Using other community built tools

Check out the [Stacks Devtools Catalog](/stacks-devtools-catalog) for other creative devtools for creating and managing Stacks wallets.
{% endstep %}
{% endstepper %}

***

## How are Clarity contract addresses formatted?

On Stacks, a **contract address/principal** uniquely identifies a deployed smart contract and is structured as an account principal plus a contract namespace, forming a unique on-chain identity:

```
<deployer-address>.<contract-name>
```

#### Structure Breakdown

1. **Deployer Address**\
   A standard Stacks principal (derived from a hash160 of a public key), such as:
   * `SP...` → mainnet
   * `ST...` → testnet
2. **Contract Name**\
   An ASCII identifier chosen at deployment time (e.g., `my-token`, `amm-v1`, `nft-market`).

#### Why It’s Structured This Way

Because contract identifiers are namespaced by the deployer’s address:

* Two different accounts can deploy contracts with the same name.
* A single account cannot deploy two contracts with the same name.
* The identifier is deterministic and globally unique.

***

## Handling different formats

It's common for new Stacks developers to get tripped up on the different ways when specifying Stacks' principals (aka addresses) in their development.

Here's a breakdown of dealing with principals in 3 different use cases.

<div data-with-frame="true"><figure><img src="/files/aPoXlupogLQSU6ubkWQ2" alt=""><figcaption></figcaption></figure></div>

***

### The Stacks and Bitcoin address connection

What makes Stacks beautifully connected to its L1 settlement layer, Bitcoin, is their many shared aspects. One being how both utilize a similar address generation scheme based on the P2PKH format, which allows for both a Bitcoin & Stacks address to share the same public key hash. If you base58check decode a legacy bitcoin address, you can reveal the public key hash, which can then be used to generate its respective c32check encoded Stacks address.

Programmatically, you could also use a method called `b58ToC32`, from the `c32check` javascript library, which can abstract the conversion for you.

<div data-with-frame="true"><figure><img src="/files/kBDMARKJ3QRLuQeFF8Qk" alt=""><figcaption></figcaption></figure></div>

***

### Additional Resources

* \[[Hiro Blog](https://www.hiro.so/blog/understanding-the-differences-between-bitcoin-address-formats-when-developing-your-app)] Understanding the Differences Between Bitcoin Address Formats
* \[[Hiro Blog](https://www.hiro.so/blog/how-every-stacks-address-has-a-corresponding-bitcoin-address)] How Every Stacks Address Has a Corresponding Bitcoin Address
* \[[Hiro Blog](https://www.hiro.so/blog/an-intro-to-web3-wallets-for-web3-founders)] An Intro to Web3 Wallets for Web3 Founders
* \[[Hiro Blog](https://www.hiro.so/blog/why-web3-needs-bitcoin-centric-wallet-standards)] Why Web3 Needs Bitcoin-Centric Wallet Standards
* \[[Stacks YT](https://youtu.be/RvTuex1jbGY?si=KGEGESS3sr38G_Tj)] How to Set Up Your First Bitcoin L2 Wallet
* \[[SIP-005](https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md)] For the technical breakdown and standard on how wallets/accounts are generated.


# Bitcoin Name System

<div data-with-frame="true"><figure><img src="/files/miWMS7leIGKoK3HzG4fI" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
**Builder Resources**

* Official BNSv2 website for stats, [here](https://www.bnsv2.com/).
* BNSv2 mainnet contract, [here](https://explorer.hiro.so/txid/SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF.BNS-V2).
* BNSv2 SDK, [here](https://github.com/Strata-Labs/bns-v2-sdk).
* BNSv2 contracts repo, [here](https://github.com/Trust-Machines/BNS-V2).
  {% endhint %}

#### At a Glance

* BNS is the live naming system on Stacks
* Human-readable names like `alice.id` or `muneeb.btc` map to on-chain data
* Names are SIP-009 compliant NFTs: transferable, tradeable, composable
* Built-in marketplace for listing, buying, and selling names
* Supports both open (unmanaged) and governed (managed) namespaces
* Each address can own multiple names and designate a primary name
* Fully implemented as Clarity smart contracts
* The current BNS implementation uses the BNS V2 contract, deployed in September 2024. It succeeded the V1 contract from Stacks mainnet launch in 2021.

***

## What is BNS?

The **Bitcoin Name System (BNS)** is a decentralized naming system built on Stacks and secured by Bitcoin. It enables human-readable names (e.g., `alice.id`) that map to on-chain identities, addresses, and arbitrary records.

Bitcoin Name Service (BNS) is a decentralized identity protocol that originally started on Bitcoin as Namecoin in 2014 before migrating to Bitcoin in 2015, and eventually Stacks when its mainnet launched in 2021.

That means BNS predates ENS by multiple years!

BNS is represented by the popular .btc namespace but has many others including .id, .locker, .app and more. Anyone can create a new namespace and have users register names within that. Currently there are 97 namespaces and over 360,000 names registered on BNS \[as of March 2026]!

| Top Namespaces \[as of March 2026] | Names registered under the namespace |
| ---------------------------------- | ------------------------------------ |
| .btc                               | 302,999                              |
| .stx                               | 21,861                               |
| .app                               | 12,445                               |
| .id                                | 12,053                               |
| .stacks                            | 3,961                                |

The benefit of a BNS name is simple: Rather than sending crypto to a long STX or BTC address, you can use a human-readable name like muneeb.btc instead.

BNS names are compatible with Stacks wallets like Leather and Xverse and support both Stacks L2 and Bitcoin L1 for payments.

BNS replaces complex blockchain addresses with names that:

* Can resolve to Stacks principals
* Can store structured metadata
* Names can store zonefiles containing profile data (bio, PFP, social links), wallet addresses across chains (BTC, ETH, etc.), subdomain definitions, and arbitrary key-value metadata. All stored on-chain via the zonefile-resolver contract.
* Can integrate directly with smart contracts
* Are owned and managed entirely on-chain

Stacks currently runs **BNSv2**, an upgraded implementation designed for improved composability, clarity, and developer ergonomics. It allows users to register, manage, and transfer names within different namespaces. It also introduces a native marketplace, managed namespaces with custom governance, multi-name ownership per address, primary name designation, and on-chain zonefile storage decoupled from the main contract.

***

{% embed url="<https://youtu.be/Ua4i-FxPsoE?si=sU0q2MceU51N0CYZ>" %}

***

## Additional Resources

* [\[BNSv2 Official\]](https://www.bnsv2.com/) Official BNSv2 site
* [\[BNS One\]](https://bns.one/) Register, trade, discover BNS namespaces and names
* \[[Trust Machines Github](https://github.com/Trust-Machines/BNS-V2)] BNSv2 contracts repository
* [\[Stacks Forum\]](https://forum.stacks.org/t/megathread-bns-upgrade-discussion/14899) Previous upgrade discussion thread
* [\[BNSv1\]](https://explorer.hiro.so/address/SP000000000000000000002Q6VF78.bns?chain=mainnet) The previous BNSv1 implementation boot contract
* [\[BNS Community\]](https://x.com/bns_community) Twitter community page for all things BNS
* [\[Gamma\]](https://gamma.io/stacks/collections/bns-v2/items) Marketplace for trading BNS
* [\[BTC US\]](https://btc.us/) Register BNS names


# History of BNS

#### Origins on Namecoin (2014)

The Bitcoin Name System (BNS) traces its roots back to 2014, when it began as a naming and identity layer built on top of Namecoin through the OneName project.

<div data-with-frame="true"><figure><img src="/files/pHckx2VQHipcrAnU8T6Y" alt=""><figcaption></figcaption></figure></div>

The idea was simple but powerful: allow users to register globally unique, human-readable names that were cryptographically tied to private keys. Early adopters claimed names in formats like `u/ryan`, using them as portable digital identities. However, Namecoin’s limitations—including spam, weaker security guarantees, and slower confirmations—made long-term scalability difficult.

#### Migration to Bitcoin (2015)

In 2015, the project migrated to the Bitcoin blockchain itself, anchoring the `.id` namespace by burning approximately 40 BTC in a public commitment. This move dramatically increased the security model by leveraging Bitcoin’s durability and decentralization. Name registrations were recorded directly in Bitcoin transactions, often using `OP_RETURN`, while richer state data lived off-chain. This hybrid approach allowed BNS to inherit Bitcoin’s security while still supporting flexible identity metadata.

#### Stacks Era (2021)

The next major chapter began in 2021 with the launch of Stacks. With Stacks introducing smart contract functionality anchored to Bitcoin, BNS was deployed as a smart contract at the genesis of Stacks 2.0. All prior BNS names were migrated over, preserving ownership history while enabling more expressive on-chain logic. Names such as `.btc` quickly gained popularity, and BNS evolved into a core identity primitive within the Stacks ecosystem. Each name became globally unique and strongly owned by a private key, with zone files enabling up to roughly 40KB of off-chain data for profiles, address mappings, and decentralized identifiers (see BNSv2 changes below). BNS supported both fully on-chain names and off-chain subdomains anchored to blockchain state, giving developers flexibility in how they structured identity systems.

{% embed url="<https://www.youtube.com/watch?v=5IkK5T9NDqU>" %}

#### **BNS has evolved into a cornerstone of the Bitcoin ecosystem.**

BNS names have generated substantial marketplace activity, with sales volume reaching 1.5 million STX (an estimated $2 million). The launch of the BNS marketplace on [Gamma.io](http://gamma.io) in October 2022 gave the community a dedicated space to buy, sell, and trade names. This has helped to solidify BNS' status as a leader in the decentralized domain market.

In February 2024, BNS celebrated its 10th anniversary, marking a decade of progress in decentralised naming and identity on the Bitcoin blockchain.

#### Limitations of BNS V1

The original implementation of BNS on Stacks, often referred to as V1, worked reliably but had structural constraints. A single address could maintain only one primary name at a time, which limited composability and made trading or collecting names more cumbersome. Additionally, names were not implemented as SIP-09 NFTs, which meant they did not automatically interoperate with the broader NFT tooling ecosystem. Over time, as Stacks matured and NFT standards solidified, the community began pushing for a more flexible and interoperable redesign.

#### Evolution Toward BNS V2

That redesign materialized in September 2024 as BNSv2. The migration from BNSv1 to BNSv2 saw names airdropped to the account that owned them as of the migration snapshot on September 11, 2024. Users didn’t need to do anything...their BNSv2 name simply appeared in their wallet. The BNSv1 contract still exists on-chain but changes to names via V1 are NOT reflected in V2 and vice versa.

The new implementation fundamentally re-architected how names are represented and managed. Most notably, every top-level name is now a SIP-09 compliant NFT. This change allows BNS names to plug directly into wallets, marketplaces, and smart contracts without requiring custom handling logic. It also means names behave like standard digital assets: they can be transferred, listed, escrowed, or integrated into DeFi protocols with minimal friction.

BNSv2 also removed the single-name limitation, enabling addresses to own multiple names simultaneously. This seemingly simple change dramatically improves usability and unlocks more complex application patterns, from identity portfolios to namespace-based branding strategies. Namespaces themselves have become more flexible under V2. Developers or communities can create either unmanaged namespaces that operate permissionlessly or managed namespaces with designated authorities who can define pricing rules, verification requirements, or other constraints. Managed namespaces are controlled by a **contract principal** (not a standard wallet), and that this manager can be permanently frozen for full decentralization. This flexibility opens the door for curated identity layers, branded ecosystems, and experimental naming economies.

<details>

<summary><strong>What happens to BNSv1?</strong></summary>

The BNSv1 smart contract will continue to exist. But any changes made to names via the BNSv1 contract won't be reflected in BNSv2 and vice versa going forward.

</details>

The registration flow in BNSv2 continues to use a preorder-and-reveal mechanism to prevent front-running, where a salted hash of the name is committed before the actual name is revealed. Zonefiles remain part of the architecture, allowing names to reference external data such as wallet addresses, profiles, or decentralized identity records. But V2 zonefiles are fundamentally different from V1. In V1, zonefiles were off-chain data replicated via the Atlas network. In V2, zonefiles are stored on-chain in a separate zonefile-resolver contract. Because names are now NFTs, they integrate more naturally with marketplaces and infrastructure across the Stacks ecosystem, while still inheriting Bitcoin’s security guarantees through Stacks’ anchoring model.

Today, BNSv2 stands as both an identity system and a digital asset framework built on Stacks. It preserves the original vision of globally unique, user-owned names secured by Bitcoin, while modernizing the architecture to align with NFT standards, multi-asset ownership, and programmable namespace management.

***

#### Additional Resources

* A deeper historical walkthrough of BNS: <https://mythbtc.xyz/bns-history/>


# How BNSv2 Works

## Architecture Overview

BNSv2 is implemented amongst two Clarity contracts: `.BNS-V2` and `.zonefile-resolver` . These two Clarity contracts collectively manage:

1. Namespace registration and management
2. Name registration (preorder/reveal and fast-claim)
3. Record storage (via zonefile-resolver)
4. Ownership transfers
5. Renewals
6. Marketplace (list, unlist, buy)
7. Primary name designation

All state lives on-chain and is publicly verifiable.

<table><thead><tr><th width="162.8984375"></th><th>Mainnet</th><th>Testnet</th></tr></thead><tbody><tr><td>BNSv2</td><td><code>SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF.BNS-V2</code></td><td><code>ST2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D9SZJQ0M.BNS-V2</code></td></tr><tr><td>Zonefile Resolver</td><td><code>SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF.zonefile-resolver</code></td><td><code>ST2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D9SZJQ0M.zonefile-resolver</code></td></tr></tbody></table>

#### Resolution of names

Resolution works as follows:

1. A user queries the zonefile-resolver contract with a name and namespace
2. The resolver checks the name is valid, not revoked, and within its renewal period (cross-contract call to BNS-V2)
3. Returns the zonefile data (owner, zonefile buffer, revoked status)
4. Applications parse the zonefile JSON to extract addresses, profiles, etc.

For name ownership/properties (without zonefile data), you query the BNS-V2 contract directly. There are no centralized DNS servers or off-chain dependencies required for correctness.

{% hint style="info" %}
BNSv2 discontinued V1-style off-chain subdomains (Atlas network / TXT records) and DID compliance. Subdomains are now defined within a name's zonefile, stored on-chain. For legacy documentation on BNSv1, navigate [here](https://docs.stacks.co/learn/network-fundamentals/bitcoin-name-system).
{% endhint %}

***

## Zonefiles

Zonefiles also look significantly different in this upgrade.

Previously, BNS zonefiles are built on top of the “atlas” network. Atlas is a protocol built in to Stacks node’s software for replication and distribution of zonefiles. In BNSv1, BNS apps and APIs only recognized zonefiles that are part of the Atlas network.

The `zonefile-resolver` contract stores a `(optional (buff 8192))`. The contract itself has no IPFS-specific logic. It stores raw bytes — which at the application layer could be a full JSON zonefile or a CID/URL pointing to external storage.

Overall, this architecture delivers a flexible and scalable solution, combining the security and immediacy of on-chain storage with the extensibility and efficiency of decentralized off-chain storage.

These changes can summarized in two ways:

1. Zonesfiles, or links to zonefiles, now live on-chain
2. Zonefiles are now decoupled from the BNS-V2 contract. Zonefiles now live-onchain & in their own contract: `.zonefile-resolver`. This contract is fairly limited with a single map & only three functions: `resolve-name`, `update-zonefile` & `revoke-name`.

Under this design, a dedicated smart contract is responsible for managing all zonefile-related functionality. The contract supports storing zonefiles of up to 8,192 bytes (8 KB) directly on-chain, associating the zonefile deterministically with its corresponding name and namespace. This ensures that smaller zonefiles are immediately available, tamper-resistant, and secured by the underlying blockchain guarantees.

{% code title="Data map for a name’s zonefile information" %}

```clarity
;; zonefile map: Stores zonefile information for each name in a namespace
;; Key: {name: (buff 48), namespace: (buff 20)}
;; Value: {owner: principal, zonefile: (optional (buff 8192)), revoked: bool}
(define-map zonefile {name: (buff 48), namespace: (buff 20)} 
    {
        owner: principal,
        zonefile: (optional (buff 8192)),
        revoked: bool
    }
)
```

{% endcode %}

Zonefiles are technically stored as a hex-encoded UTF-8 JSON. The maximum length if defined in the contract to be 8,192 bytes (8 KB). The following JSON schema is the standard format used by BNSv2 applications and the official API. The contract itself stores raw bytes and does not enforce this structure.

{% code title="Zonefile structure" expandable="true" %}

```json
{
	"owner": "SP...",
	"btc": "bc1...",
	"bio": "User bio...",
	"website": "www.url.com",
	"pfp": "www.mypfp.com/image.png", // must be a valid image format (e.g. .png, .jpg, .svg)
	"name": "User Name",
	"location": "City, Country",
	"social": [
		{
			"platform": "x", 
			"username": "username"
		},
		{
			"platform": "telegram", 
			"username": "username"
		}
		// ...
	],
	"addresses": [
		{
			"network": "btc",
			"address": "bc1...",
			"type": "payment"
		},
		{
			"network": "btc",
			"address": "bc1...",
			"type": "ordinal"
		},
		{
			"network": "eth",
			"address": "0x123...",
			"type": "wallet"
		}
		// ...
	],
	"meta": [
		{
			"name": "example",
			"value": "custom datas"
		}
		// ...
	],
	"subdomains": [
		{
			"test": {
				"owner": "SP....",
				"bio": "Subdomain bio..",
				"website": "www.url.com",
				"pfp": "www.mypfp.com/image.png",
				"name": "User Name",
				"location": "City, Country",
				"social": [
					{
						"platform": "x",
						"username": "@username"
					}
				],
				"addresses": [
					{
						"network": "Bitcoin",
						"address": "bc1...",
						"type": "payment"
					}
				]
			}
		}
		// ...
	],
	"externalSubdomainsFile": "www.url.com/subdomains.json" // optional: external file containing subdomain definitions
}
```

{% endcode %}

The API layer abstracts the resolution logic, automatically determining whether to retrieve the zonefile data directly from the contract or via IPFS using the stored CID. As a result, clients can resolve zonefile information for any given name and namespace through a consistent interface without needing to manage storage distinctions manually.

Check out the [BNSv2 SDK](https://github.com/Strata-Labs/bns-v2-sdk) for more info on zonefiles.


# Core Concepts

## **Namespaces**

Namespaces are the top-level domains in BNS (e.g., .btc, .id). They have the following lifecycle:

* **Preorder:** A salted hash of the namespace is submitted with a burn payment
* **Reveal:** The actual namespace is revealed, along with pricing information and all of the namespace properties

<details>

<summary>What happens during reveal?</summary>

During reveal, the creator sets: `lifetime` (how long names last before needing renewal, 0 means no renewal), `namespace-import` principal, and the full `price-function` (16 buckets, base, coefficient, nonalpha-discount, no-vowel-discount). These are critical parameters that define the namespace's behavior forever.

Namespace pricing can be updated (via `namespace-update-price`) and can be frozen permanently (via `namespace-freeze-price`). Once frozen, the price function can never be changed. These are important governance decisions.

Also, names can be imported before launch via `name-import`. This allows namespace creators to pre-populate names (e.g., for migration or reserved names) before opening registration to the public.

</details>

* **Launch:** The namespace becomes active, allowing name registrations

#### **Unmanaged vs Managed Namespaces**

BNS-V2 supports two types of namespaces: **Unmanaged** and **Managed**.

Unmanaged namespaces are open for anyone to register names within them, subject to the namespace’s pricing rules. These namespaces operate fully in a decentralized manner, with minimal restrictions on name registration and management.

Managed namespaces, on the other hand, introduce an additional layer of control and customization. These namespaces are overseen by a designated manager who has special privileges and responsibilities. Managed namespaces can implement custom rules for name registration, pricing, transfer and renewals. This allows for use cases such as creating namespaces for specific communities, implementing additional verification processes, or enforcing particular naming conventions.

The key differences between unmanaged and managed namespaces lie in their governance and flexibility. While unmanaged namespaces provide a more open and unrestricted environment, managed namespaces offer greater control and the ability to tailor the namespace to specific requirements or use cases.

#### Creating a Managed Namespace

Managed namespaces are one of the biggest updates in this version of BNSv2. Meant to allow for significant more control & flexibility over a namespace, a "managed" namespace is controlled by a single principal (almost always a *contract* principal). For expected behavior, you must be very careful on setting up this contract principal - if it's not setup correctly, it's possible to to permanently lose control of the namespace.

A few important decisions to make when creating a managed namespace are:

* Will the manager contract *ever* need to be changed?
* How will your mint process work?
* Can managers transfer *any* name?
* Will you names be tradeable?
* Does your namespace require metadata?

These are critical decisions that one must consider to future-proof a managed namespace. For the first question, it's almost guaranteed that you *will* need to update or remove the manager contract, therefore, it's imperative that the manager contract include access to the 'mng-manager-transfer' function. If the initial manager contract does not include this function, it will be impossible to update or remove the namespace to a new manager contract.

Managed namespaces do not require STX burns for name registration. The `mng-name-register` function sets `stx-burned: u0` on the preorder. Pricing is entirely handled by the manager contract (could be free, token-gated, STX-based via the manager's own logic, etc.). This is a fundamental difference from unmanaged namespaces.

Next, the mint process is vastly more customizable in a managed namespace. At a high-level, managed namespaces have access to the same two paths for name registration: 2 steps / mng-name-preorder + mng-name-register, or a single step / fast-claim. Managed contracts **must** have access to one or both of these functions to successfully mint names in a namespace; additionally, the mint process can be customized to a high degree to allow for: free mints, token-gated mints, variable pricing, sip-10 token support, etc...

Once minted, you must take special care to implement the three standard sip-09 market functions: list, unlist & buy. Managed namespaces *are not* tradeable by default, they *must* include wrapped calls into the list,unlist & buy functions in BNSv2 as those functions specifically check against 'contract-caller' (aka the managed contract).

Lastly, the ability to allow for the managed namespace contract *itself* to transfer any name is a critical decision. It's almost guranteed that you **don't** want to allow this, as it would allow the contract to transfer any name to any principal; however, there are some use-cases where much more granular control is required.

Managed namespace names do not expire. The `mng-name-register` function sets `renewal-height: u0`, meaning there's no automatic renewal requirement. The manager controls the full lifecycle.

***

## **Names**

Names are the individual identifiers within a namespace (e.g., alice.btc). They have the following properties:

* Unique within their namespace
* Represented as NFTs
* Can be transferred and renewed
* Associated with a zonefile, which stores additional information related to the name in a separate `zonefile-resolver` contract

A BNS name has two components:

```
<name>.<namespace>
```

Example:

```
alice.id
```

* `alice` → the name
* `id` → the namespace

Namespaces define rules and pricing for name registrations.

***

## Ownership

Names are owned by a Stacks principal.

Ownership allows the holder to:

* Update records
* Set name as the primary name
* List the name for sale on the built-in marketplace
* Transfer the name
* Renew the name
* Configure resolution data

Ownership is enforced entirely by smart contract logic.

***

## Zonefiles

Each name can store structured records. The zonefile JSON supports: owner address, BTC address, bio, website, PFP, name, location, social links (X, Telegram, etc.), multi-chain addresses (BTC payment, BTC ordinal, ETH, etc.), arbitrary key-value metadata, and subdomain definitions.

These records may include:

* Address mappings
* Text metadata
* Application-specific data
* Profile information

Because BNSv2 is implemented in Clarity, other contracts can read name data directly on-chain.


# Operations

### Registering a Name

Name registration is performed by calling the appropriate BNSv2 contract function. The caller becomes the owner of the name.

**High-level flow:**

1. Check availability
2. Submit registration transaction
3. Pay required STX fee
4. Wait for confirmation
5. Name is assigned to caller principal

**Path 1 — Preorder + Register (safe, prevents front-running):**

1. Generate a salted hash of the fully-qualified name: hash160(name.namespace.salt)
2. Submit name-preorder with the hash and STX to burn
3. Wait at least 1 block
4. Submit name-register with the actual name, namespace, and salt
5. Contract verifies hash match, burns STX, mints NFT to caller

**Path 2 — Fast Claim (single tx, vulnerable to front-running):**

1. Submit name-claim-fast with name, namespace, and recipient
2. STX burned in one step, NFT minted immediately
3. Risk: name is visible in the mempool before confirmation, so it can be sniped For managed namespaces: Use `mng-name-preorder` + `mng-name-register` (no STX burn, manager controls pricing).

### Updating Records

Once a name is owned, the owner can update records via contract calls. Updates go through the `zonefile-resolver` contract via `update-zonefile(name, namespace, new-zonefile)`. The caller must be either the name owner OR the namespace manager (for managed namespaces). Mention the 8KB limit.

Example record updates might include:

* Setting a Stacks address
* Updating profile metadata
* Adding custom key-value pairs

Only the current owner can modify records.

### Transferring a Name

Names are transferable digital assets. `transfer(id, sender, recipient)` on the BNS-V2 contract. For managed namespaces, use `mng-transfer(id, sender, recipient)`, but only if manager transfers haven't been turned off via `turn-off-manager-transfers` .

The owner can:

* Transfer ownership to another principal
* Use a name inside other contracts
* Integrate names into marketplaces or identity systems

Because ownership is native to Clarity, transfers are trustless.

### Resolving a Name

Resolution involves querying BNSv2 contracts for a name’s stored record.

`resolve-name(name, namespace)` on `zonefile-resolver`

The corresponding BNSv2 SDK functions: `resolveNameZonefile()`, `getNameInfo()`, `getPrimaryName()`.

Apps can:

* Call the contract directly via RPC
* Use SDK helpers
* Use indexers for convenience

Resolution is deterministic and does not rely on centralized servers.

### **Pricing**

Name prices are calculated based on:

* Length of the name
* Presence of vowels
* Presence of non-alphabetic characters
* Namespace-specific pricing functions
* **For managed namespaces the pricing will be handled directly by the namespace manager contract**

### **NFT Integration**

Each name is minted as an NFT, allowing:

* Easy transfers of ownership
* Integration with NFT marketplaces and other applications

### Renewals

Names in unmanaged namespaces expire after lifetime blocks. Owners have a 5,000 block grace period (\~34 days) after expiration to renew via `name-renewal(namespace, name)`.

* Renewal burns STX based on the current name price.
* If not renewed within the grace period, the name becomes available for anyone to register.
* Managed namespace names do NOT expire (renewal-height = 0).

### Marketplace

BNSv2 has a native marketplace:

* `list-in-ustx(id, price, commission-trait)`, list a name for sale
* `unlist-in-ustx(id)`, remove listing
* `buy-in-ustx(id, commission-trait)`, purchase a listed name Commission is handled via the SIP-009 commission trait.
* For managed namespaces, the manager contract must wrap these functions.

### Setting a primary name

* `set-primary-name(id)` on BNS-V2 lets an owner designate one of their names as their primary identity.
* This is what wallets and apps use for display.
* Only one primary name per address.


# BNSv1 (legacy)

{% hint style="info" %}
The content on this page is relating to the legacy BNS v1.
{% endhint %}

Bitcoin Name System (BNS) is a network system that binds Stacks usernames to off-chain state without relying on any central points of control.

The Stacks V1 blockchain implemented BNS through first-order name operations. In Stacks V2, BNS is instead implemented through a smart-contract loaded during the genesis block.

Names in BNS have three properties:

* **Names are globally unique.** The protocol does not allow name collisions, and all well-behaved nodes resolve a given name to the same state.
* **Names are human-meaningful.** Each name is chosen by its creator.
* **Names are strongly owned.** Only the name's owner can change the state it resolves to. Specifically, a name is owned by one or more ECDSA private keys.

The Stacks blockchain ensures that each node's BNS view is synchronized to all of the other nodes in the world, so queries on one node will be the same on other nodes. Stacks blockchain nodes allow a name's owner to bind up to 40Kb of off-chain state to their name, which will be replicated to all other Stacks blockchain nodes via a P2P network.

The biggest consequence for developers is that in BNS, reading name state is fast and cheap but writing name state is slow and expensive. This is because registering and modifying names requires one or more transactions to be sent to the underlying blockchain, and BNS nodes will not process them until they are sufficiently confirmed. Users and developers need to acquire and spend the requisite cryptocurrency (STX) to send BNS transactions.

### Motivation behind name systems

We rely on name systems in everyday life, and they play a critical role in many different applications. For example, when you look up a friend on social media, you are using the platform's name system to resolve their name to their profile. When you look up a website, you are using the Domain Name Service to resolve the hostname to its host's IP address. When you check out a Git branch, you are using your Git client to resolve the branch name to a commit hash. When you look up someone's PGP key on a keyserver, you are resolving their key ID to their public key.

What kinds of things do we want to be true about names? In BNS, names are globally unique, names are human-meaningful, and names are strongly owned. However, if you look at these examples, you'll see that each of them only guarantees two of these properties. This limits how useful they can be.

* In DNS and social media, names are globally unique and human-readable, but not strongly owned. The system operator has the final say as to what each name resolves to.
  * Problem: Clients must trust the system to make the right choice in what a given name resolves to. This includes trusting that no one but the system administrators can make these changes.
* In Git, branch names are human-meaningful and strongly owned, but not globally unique. Two different Git nodes may resolve the same branch name to different unrelated repository states.
  * Problem: Since names can refer to conflicting state, developers have to figure out some other mechanism to resolve ambiguities.
* In PGP, names are key IDs. They are globally unique and cryptographically owned, but not human-readable. PGP key IDs are derived from the keys they reference.
  * Problem: These names are difficult for most users to remember since they do not carry semantic information relating to their use in the system.

BNS names have all three properties, and none of these problems. This makes it a powerful tool for building all kinds of network applications. With BNS, we can do the following and more:

* Build domain name services where hostnames can't be hijacked.
* Build social media platforms where user names can't be stolen by phishers.
* Build version control systems where repository branches do not conflict.
* Build public-key infrastructure where it's easy for users to discover and remember each other's keys.

### Organization of BNS

BNS names are organized into a global name hierarchy. There are three different layers in this hierarchy related to naming:

* **Namespaces.** These are the top-level names in the hierarchy. An analogy to BNS namespaces are DNS top-level domains. Existing BNS namespaces include `.id`, `.podcast`, and `.helloworld`. All other names belong to exactly one namespace. Anyone can create a namespace, but in order for the namespace to be persisted, it must be *launched* so that anyone can register names in it. Namespaces are not owned by their creators.
* **BNS names.** These are names whose records are stored directly on the blockchain. The ownership and state of these names are controlled by sending blockchain transactions. Example names include `verified.podcast` and `muneeb.id`. Anyone can create a BNS name, as long as the namespace that contains it exists already.
* **BNS subdomains.** These are names whose records are stored off-chain, but are collectively anchored to the blockchain. The ownership and state for these names lives within the P2P network data. While BNS subdomains are owned by separate private keys, a BNS name owner must broadcast their subdomain state. Example subdomains include `jude.personal.id` and `podsaveamerica.verified.podcast`. Unlike BNS namespaces and names, the state of BNS subdomains is *not* part of the blockchain consensus rules.

A feature comparison matrix summarizing the similarities and differences between these name objects:

| Feature                                | **Namespaces** | **BNS names** | **BNS Subdomains** |
| -------------------------------------- | -------------- | ------------- | ------------------ |
| Globally unique                        | X              | X             | X                  |
| Human-meaningful                       | X              | X             | X                  |
| Owned by a private key                 |                | X             | X                  |
| Anyone can create                      | X              | X             | \[1]               |
| Owner can update                       |                | X             | \[1]               |
| State hosted on-chain                  | X              | X             |                    |
| State hosted off-chain                 |                | X             | X                  |
| Behavior controlled by consensus rules | X              | X             |                    |
| May have an expiration date            |                | X             |                    |

\[1] Requires the cooperation of a BNS name owner to broadcast its transactions

### Namespaces

Namespaces are the top-level name objects in BNS. They control a few properties about the names within them:

* How expensive they are to register
* How long they last before they have to be renewed
* Who (if anyone) receives the name registration fees
* Who is allowed to seed the namespace with its initial names

At the time of this writing, by far the largest BNS namespace is the `.id` namespace. Names in the `.id` namespace are meant for resolving user identities. Short names in `.id` are more expensive than long names, and have to be renewed by their owners every two years. Name registration fees are not paid to anyone in particular—they are instead sent to a "black hole" where they are rendered non-spendable (the intention is to discourage ID squatters).

Unlike DNS, anyone can create a namespace and set its properties. Namespaces are created on a first-come first-serve basis, and once created, they last forever.

However, creating a namespace is not free. The namespace creator must burn cryptocurrency to do so. The shorter the namespace, the more cryptocurrency must be burned (that is, short namespaces are more valuable than long namespaces). For example, it cost Blockstack PBC 40 BTC to create the `.id` namespace in 2015 (in transaction `5f00b8e609821edd6f3369ee4ee86e03ea34b890e242236cdb66ef6c9c6a1b281`).

Namespaces can be between 1 and 19 characters long, and are composed of the characters `a-z`, `0-9`, `-`, and `_`.

### Subdomains

BNS names are strongly owned because the owner of its private key can generate valid transactions that update its zone file hash and owner. However, this comes at the cost of requiring a name owner to pay for the underlying transaction in the blockchain. Moreover, this approach limits the rate of BNS name registrations and operations to the underlying blockchain's transaction bandwidth.

BNS overcomes this with subdomains. A **BNS subdomain** is a type of BNS name whose state and owner are stored outside of the blockchain, but whose existence and operation history are anchored to the blockchain. Like their on-chain counterparts, subdomains are globally unique, strongly owned, and human-readable. BNS gives them their own name state and public keys. Unlike on-chain names, subdomains can be created and managed cheaply, because they are broadcast to the BNS network in batches. A single blockchain transaction can send up to 120 subdomain operations.

This is achieved by storing subdomain records in the BNS name zone files. An on-chain name owner broadcasts subdomain operations by encoding them as `TXT` records within a DNS zone file. To broadcast the zone file, the name owner sets the new zone file hash with a `NAME_UPDATE` transaction and replicates the zone file. This, in turn, replicates all subdomain operations it contains, and anchors the set of subdomain operations to an on-chain transaction. The BNS node's consensus rules ensure that only valid subdomain operations from valid `NAME_UPDATE` transactions will ever be stored.

For example, the name `verified.podcast` once wrote the zone file hash `247121450ca0e9af45e85a82e61cd525cd7ba023`, which is the hash of the following zone file:

```bash
$TTL 3600
1yeardaily TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxeWVhcmRhaWx5CiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMXllYXJkYWlseS9oZWFkLmpzb24iCg=="
2dopequeens TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAyZG9wZXF1ZWVucwokVFRMIDM2MDAKX2h0dHAuX3RjcCBVUkkgMTAgMSAiaHR0cHM6Ly9waC5kb3Rwb2RjYXN0LmNvLzJkb3BlcXVlZW5zL2hlYWQuanNvbiIK"
10happier TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxMGhhcHBpZXIKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8xMGhhcHBpZXIvaGVhZC5qc29uIgo="
31thoughts TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzMXRob3VnaHRzCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMzF0aG91Z2h0cy9oZWFkLmpzb24iCg=="
359 TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzNTkKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8zNTkvaGVhZC5qc29uIgo="
30for30 TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzMGZvcjMwCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMzBmb3IzMC9oZWFkLmpzb24iCg=="
onea TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiBvbmVhCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vb25lYS9oZWFkLmpzb24iCg=="
10minuteteacher TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAxMG1pbnV0ZXRlYWNoZXIKJFRUTCAzNjAwCl9odHRwLl90Y3AgVVJJIDEwIDEgImh0dHBzOi8vcGguZG90cG9kY2FzdC5jby8xMG1pbnV0ZXRlYWNoZXIvaGVhZC5qc29uIgo="
36questionsthepodcastmusical TXT "owner=1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH" "seqn=0" "parts=1" "zf0=JE9SSUdJTiAzNnF1ZXN0aW9uc3RoZXBvZGNhc3RtdXNpY2FsCiRUVEwgMzYwMApfaHR0cC5fdGNwIFVSSSAxMCAxICJodHRwczovL3BoLmRvdHBvZGNhc3QuY28vMzZxdWVzdGlvbnN0aGVwb2RjYXN0bXVzaWNhbC9oZWFkLmpzb24iCg=="
_http._tcp URI 10 1 "https://dotpodcast.co/"
```

Each `TXT` record in this zone file encodes a subdomain-creation. For example, `1yeardaily.verified.podcast` resolves to:

```json
{
  "address": "1MwPD6dH4fE3gQ9mCov81L1DEQWT7E85qH",
  "blockchain": "bitcoin",
  "last_txid": "d87a22ebab3455b7399bfef8a41791935f94bc97aee55967edd5a87f22cce339",
  "status": "registered_subdomain",
  "zonefile_hash": "e7acc97fd42c48ed94fd4d41f674eddbee5557e3",
  "zonefile_txt": "$ORIGIN 1yeardaily\n$TTL 3600\n_http._tcp URI 10 1 \"https://ph.dotpodcast.co/1yeardaily/head.json\"\n"
}
```

This information was extracted from the `1yeardaily` `TXT` resource record in the zone file for `verified.podcast`.

Subdomain lifecycle

{% stepper %}
{% step %}
**Creation**

A subdomain-creation operation is created by the subdomain owner and encoded into a `TXT` record in an on-chain name owner's zone file. The on-chain name owner broadcasts the zone file by issuing a `NAME_UPDATE` transaction, which anchors the subdomain-creation on-chain.
{% endstep %}

{% step %}
**Update**

Subdomain updates are done off-chain by creating signed operations from the subdomain owner's private key. Any on-chain name owner can include these signed operations in their zone file and broadcast via `NAME_UPDATE`. Operations are ordered by a sequence number and require a valid signature that links to the previous operation's public key.
{% endstep %}

{% step %}
**Transfer**

To change the address (public key hash) owning a subdomain, the subdomain owner signs a subdomain-transfer operation and asks an on-chain name owner (typically the one who created the subdomain) to broadcast it via `NAME_UPDATE`. The broadcasting on-chain name owner's zone file must be present in the Atlas network to prove absence of conflicting operations.
{% endstep %}
{% endstepper %}

Sequence and validation rules

* Subdomain operations are ordered by sequence number, starting at 0. Each new operation must include:
  * The next sequence number
  * The public key that hashes to the previous subdomain transaction's address
  * A signature from the corresponding private key over the entire subdomain operation
* If two correctly signed but conflicting operations have the same sequence number, the one earlier in blockchain history is accepted. Invalid operations are ignored.

Subdomain creation and management rules

* A subdomain-creation transaction can only be processed by the owner of the on-chain name that shares its suffix (e.g., only the owner of `res_publica.id` can broadcast creations for `*.res_publica.id`).
* A subdomain-transfer transaction can only be broadcast by the owner of the on-chain name that created it.
* To send a subdomain-creation or subdomain-transfer, all of an on-chain name owner's zone files must be present in the Atlas network. This allows proving the absence of conflicting operations.
* A subdomain update can be broadcast by any on-chain name owner, but the subdomain owner needs to find a cooperating on-chain name owner to include and broadcast it.

To create a subdomain, the subdomain owner generates the creation operation and gives it to the on-chain name owner. Once created, the subdomain owner can use any on-chain name owner to broadcast updates by providing signed operations packaged into zone files.

Subdomain registrars

Because subdomain names are cheap, developers may run subdomain registrars for their applications. For example, the name `personal.id` is used to register usernames without requiring users to spend Bitcoin.

A reference implementation is available: <https://github.com/stacks-network/subdomain-registrar>. Users still own their subdomain names; the registrar helps developers broadcast subdomain operations.

### BNS and DID Standards

BNS names are compliant with the emerging Decentralized Identity Foundation (DIF) protocol specification for decentralized identifiers (DIDs): <http://identity.foundation>

Each name in BNS has an associated DID. The DID format for BNS is:

```bash
did:stack:v0:{address}-{index}
```

Where:

* `{address}` is an on-chain public key hash (for example a Bitcoin address).
* `{index}` refers to the `nth` name this address created.

Examples:

* `personal.id` → `did:stack:v0:1dARRtzHPAFRNE7Yup2Md9w18XEQAtLiV-0` (first name created by that address)
* `jude.id` → `did:stack:v0:16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg-1` (the address had created one earlier name before this one)

Purpose: a DID provides an eternal identifier for a public key. The public key may change, but the DID will not.

For a DID to be resolvable, all of the following must be true for a name:

* The name must exist
* The name's zone file hash must be the hash of a well-formed DNS zone file
* The DNS zone file must be present in the Stacks node's data
* The DNS zone file must contain a `URI` resource record that points to a signed JSON Web Token
* The public key that signed the JSON Web Token (and is included with it) must hash to the address that owns the name

Not all names will have DIDs that resolve to public keys. Names created by standard tooling will have DIDs that do.

A RESTful API is under development.

### DID Encoding for Subdomains

Every name and subdomain in BNS has a DID. Encoding differs so software can determine which code-path to take.

* For on-chain BNS names, the `{address}` is the same as the Bitcoin address that owns the name. Currently, both version byte 0 and version byte 5 addresses are supported (addresses starting with `1` or `3`, meaning `p2pkh` and `p2sh` addresses).
* For off-chain BNS subdomains, the `{address}` has version byte 63 for subdomains owned by a single private key, and version byte 50 for subdomains owned by an m-of-n set of private keys. That is, subdomain DID addresses start with `S` or `M`, respectively.

The `{index}` field for a subdomain's DID is distinct from the `{index}` field for a BNS name's DID, even if the same address created both names and subdomains. Example:

* The name `abcdefgh123456.id` → `did:stack:v0:16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg-0` (first name created by that address)
* The subdomain `jude.statism.id` created by the same address → `did:stack:v0:SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i-0`

Note: The address `SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i` encodes the same public key hash as `16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg`—the difference is base58check version byte (63 vs 0).


# SIPs

<div data-with-frame="true"><figure><img src="/files/dYfNf16LjbPQpljBolqZ" alt=""><figcaption></figcaption></figure></div>

### Stacks Improvement Proposals (SIPs)

Stacks improvement proposals (SIPs) are aimed at describing the implementation of the Stacks blockchain, as well as proposing improvements.

The SIP process [(SIP-000)](https://github.com/stacksgov/sips/blob/main/sips/sip-000/sip-000-stacks-improvement-proposal-process.md) describes how to make a SIP and get it ratified.

They should contain concise technical specifications of features or standards and the rationale behind it. SIPs are intended to be the primary medium for proposing new features, for collecting community input on a system-wide issue, and for documenting design decisions.

The SIPs are located in the [stacksgov/sips](https://github.com/stacksgov/sips) repository as part of the [Stacks Community Governance organization](https://github.com/stacksgov).

Anyone in the Stacks community can submit a SIP.

{% hint style="info" %}
Stacks Improvement Proposals Community Calls: Add the [weekly community SIP call](https://www.addevent.com/event/wS15955379) to your calendar.
{% endhint %}

### Ratified SIPSs

* [x] [SIP 000: Improvement Proposal Process](https://github.com/stacksgov/sips/blob/main/sips/sip-000/sip-000-stacks-improvement-proposal-process.md)
* [x] [SIP 001: Burn Election](https://github.com/stacksgov/sips/blob/main/sips/sip-001/sip-001-burn-election.md)
* [x] [SIP 002: Clarity, a language for predictable smart contracts](https://github.com/stacksgov/sips/blob/main/sips/sip-002/sip-002-smart-contract-language.md)
* [x] [SIP 003: Peer Network](https://github.com/stacksgov/sips/blob/main/sips/sip-003/sip-003-peer-network.md)
* [x] [SIP 004: Cryptographic Commitment to Materialized Views](https://github.com/stacksgov/sips/blob/main/sips/sip-004/sip-004-materialized-view.md)
* [x] [SIP 005: Blocks, Transactions, and Accounts](https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md)
* [x] [SIP 006: Clarity Execution Cost Assessment](https://github.com/stacksgov/sips/blob/main/sips/sip-006/sip-006-runtime-cost-assessment.md)
* [x] [SIP 007: Stacking Consensus](https://github.com/stacksgov/sips/blob/main/sips/sip-007/sip-007-stacking-consensus.md)
* [x] [SIP 008: Clarity Parsing and Analysis Cost Assessment](https://github.com/stacksgov/sips/blob/main/sips/sip-008/sip-008-analysis-cost-assessment.md)
* [x] [SIP 009: Standard Trait Definition for Non-Fungible Tokens](https://github.com/stacksgov/sips/blob/main/sips/sip-009/sip-009-nft-standard.md)
* [x] [SIP 010: Standard Trait Definition for Fungible Tokens](https://github.com/stacksgov/sips/blob/main/sips/sip-010/sip-010-fungible-token-standard.md)
* [x] [SIP 012: Burn Height Selection for a Network Upgrade to Introduce New Cost-Limits](https://github.com/stacksgov/sips/blob/main/sips/sip-012/sip-012-cost-limits-network-upgrade.md)
* [x] [SIP 013: Standard Trait Definition for Semi-Fungible Tokens](https://github.com/stacksgov/sips/blob/main/sips/sip-013/sip-013-semi-fungible-token-standard.md)
* [x] [SIP-015: Stacks Upgrade of Proof-of-Transfer and Clarity](https://github.com/stacksgov/sips/blob/main/sips/sip-015/sip-015-network-upgrade.md)
* [x] [SIP-016: Metadata for Tokens](https://github.com/stacksgov/sips/blob/main/sips/sip-016/sip-016-token-metadata.md)
* [x] [SIP-018: Signed Structured Data](https://github.com/stacksgov/sips/blob/main/sips/sip-018/sip-018-signed-structured-data.md)
* [x] [SIP-019: Notifications for Token Metadata Updates](https://github.com/stacksgov/sips/blob/main/sips/sip-019/sip-019-token-metadata-update-notifications.md)
* [x] [SIP-020: Bitwise Operations in Clarity](https://github.com/stacksgov/sips/blob/main/sips/sip-020/sip-020-bitwise-ops.md)
* [x] [SIP-022: Emergency Fix to PoX Stacking Increases](https://github.com/stacksgov/sips/blob/main/sips/sip-022/sip-022-emergency-pox-fix.md)
* [x] [SIP-023: Emergency Fix to Trait Invocation Behavior](https://github.com/stacksgov/sips/blob/main/sips/sip-023/sip-023-emergency-fix-traits.md)
* [x] [SIP-024:](https://github.com/stacksgov/sips/blob/main/sips/sip-024/sip-024-least-supertype-fix.md) Emergency Fix to Data Validation and Serialization Behavior
* [x] [SIP-025](https://github.com/stacksgov/sips/blob/main/sips/sip-025/sip-025-iterating-towards-weighted-schnorr-threshold-signatures.md): Iterating Towards WSTS
* [x] [SIP-027](https://github.com/stacksgov/sips/blob/main/sips/sip-027/sip-027-non-sequential-multisig-transactions.md): Non-sequential Multisig Transactions
* [x] [SIP-028](https://github.com/stacksgov/sips/blob/main/sips/sip-028/sip-028-sbtc_peg.md): Signer Criteria for sBTC, A Decentralized and Programmable Asset Backed 1:1 with BTC
* [x] [SIP-029](https://github.com/stacksgov/sips/blob/main/sips/sip-029/sip-029-halving-alignment.md): Bootstrapping sBTC Liquidity and Nakamoto Signer Incentives
* [x] [SIP-031](https://github.com/stacksgov/sips/blob/main/sips/sip-031/sip-031.md): Five-Year Stacks Growth Emissions
* [x] [SIP-033](https://github.com/stacksgov/sips/blob/main/sips/sip-033/sip-033-clarity4.md): Clarity Smart Contract Language, version 4
* [x] [SIP-034](https://github.com/stacksgov/sips/blob/main/sips/sip-034/sip-034.md): Dimension-Specific Tenure Extend Variants
* [x] [SIP-035](https://github.com/stacksgov/sips/blob/main/sips/sip-035/sip-secp256r1-verify.md): Clarification of Clarity's `secp256r1-verify` Behavior

### How to Get Involved

There are several ways you can get involved with the SIP process:

* **Join the weekly SIP Meeting call**, [here](https://community.stacks.org/events).
* **SIP Editor**. SIP editors help SIP authors make sure their SIPs are well-formed and follow the right process. They help get SIPs ready for deep review by advancing it them from Draft to Accepted status. If you want to become a SIP editor, open an issue with your name and email to ask to be added to the list of SIP editors.
* **Join a CAB** (Consideration Advisory Board). SIPs fall under the purview of one or more considerations. A full list is in [this github](https://github.com/stacksgov/sips/tree/main/considerations) directory. Currently they are: Diversity, Economics, Ethics, Governance and Technical. Members of SIP consideration advisory boards use their domain expertise to give Accepted SIPs a deep read, and give the authors any/all feedback to help make the SIP workable. If you want to join a board, reach out to the board's chairperson via the listed contact information.
* **Steering Committee**. The Steering Committee organizes the consideration advisory boards and votes to advance Recommended SIPs to Activation-in-Progress status, and then to either Ratified or Rejected status. Once they are in the process of being activated, they use a SIP's Activation section to determine whether or not the Stacks ecosystem has ratified or rejected the SIP. Joining this committee requires the consent of the Stacks Foundation board.

***

### Additional Resources

* [\[Stacks Community YT\]](https://www.youtube.com/playlist?list=PLg717Ri_rTnx5kuaWqp3cUAtwQk_yzslT) Recorded SIP Meeting calls (legacy)


# Technical Specifications

### Consensus

* Proof of Transfer (PoX) as described in [SIP-007](https://github.com/stacksgov/sips/blob/main/sips/sip-007/sip-007-stacking-consensus.md)
* Network will transition to Proof of Burn (PoB) as described in [SIP-001](https://github.com/stacksgov/sips/blob/main/sips/sip-001/sip-001-burn-election.md) after 10 years. [Learn more about Proof-of-Burn in SIP-001](https://github.com/stacksgov/sips/blob/main/sips/sip-001/sip-001-burn-election.md).
* Threat model
  * 51% of malicious Bitcoin mining power can reorg the Stacks chain or perform a double-spend attack
  * Chain can halt if Stackers cannot meet 70% consensus on block validity
* Different actors and their roles
  * Stacks Miners package transactions into blocks and propose them to stackers
  * Stacks Holders may alter the calculation of block limits (subject to a miner veto) and may vote to disable Proof-of-Transfer rewards for a reward cycle.
  * Stackers validate and append blocks to the chain and validate sBTC deposit and withdrawal transactions

### Proof of Transfer Mining

* Coinbase reward schedule:
  * 1000 STX/block for first 4 years
  * 500 STX/block for following 4 years
  * 250 STX/block for subsequent 4 years
  * 125 STX/block in perpetuity after that
* Coinbase rewards accumulate for "missed sortitions": If a Bitcoin block has no sortition (at height N), then any Stacks block mined in a subsequent sortition that builds off of any Stacks chain tip that existed at the penultimate sortition (at height N-1) may claim its coinbase. This encourages miners to keep mining even if Bitcoin fees are high.
* Initial mining bonus: This is a special case of the above to incentivize early miners. Coinbase for all burnchain blocks between the first burn block height (to be chosen by independent miners as part of the Stacks 2.0 launch) and the first sortition winner accumulate and are distributed to miners over a fixed window (to be determined). For instance, say burn block height is 10,000 and first sortition is at block 10500 and distribution window is 100 blocks, then coinbase for the first 500 blocks (10,500 - 10,000) will be distributed evenly to miners who win sortition over the subsequent 100 blocks.
* Reward maturity window: 100 blocks, meaning leaders will earn the coinbase reward 100 blocks after the block they successfully mine.
* Block interval: Stacks blockchain produces fast blocks roughly every 10 seconds with a miner tenure change occurring every Bitcoin block
* BTC commitment: Miners must commit at least 11,000 satoshis (5,500 sats / [UTXO output](https://learnmeabitcoin.com/technical/utxo)); 2 outputs / block) to avoid "dust."
* For more details, see Block Production.

### Stacking

{% stepper %}
{% step %}
**Prepare phase**

An "anchor block" is chosen. The qualifying set of addresses ("reward set") is determined based on the snapshot of the chain at the anchor block. Length of prepare phase is 100 blocks. Stacking commitments need to be confirmed before this phase starts.
{% endstep %}

{% step %}
**Reward phase**

Miner BTC commitments are distributed amongst the reward set. Reward cycle length is 2000 BTC blocks (\~2 weeks).
{% endstep %}
{% endstepper %}

* Two reward addresses / block, for a total of 4000 addresses every reward cycle. The addresses are chosen using a VRF (verifiable random function), so each node can deterministically arrive at the same reward addresses for a given block.
* Stacking threshold: 0.025% of the participating amount of STX when participation is between 25% and 100% and when participation is below 25%, the threshold level is always 0.00625 of the liquid supply of STX.
* Delegation: An STX address can designate another address to participate in Stacking on its behalf. [Relevant section in SIP-007](https://github.com/stacksgov/sips/blob/main/sips/sip-007/sip-007-stacking-consensus.md#stacker-delegation).
* Pooling: STX holders that individually do not meet the Stacking threshold can pool together their holdings to participate in Stacking. To do this, STX holders must set the (optional) reward address to the "delegate address." For more details, see [this reference](https://docs.stacks.co/references/stacking-contract#delegate-stx).
* Legacy, SegWit, Native Segwit, and Taproot addresses are supported

### Accounts and Addresses

* Transactions in the Stacks blockchain originate from, are paid for by, and execute under the authority of accounts
* An account is fully specified by its address + nonce + assets
* Address contains 2 or 3 fields: 1 byte version, 20 byte public key hash (RIPEMD160(SHA256(input))), optional name (variable length, max 128 bytes)
* Two types of accounts: standard accounts are owned by one or more private keys; contract accounts are materialized when a smart-contract is instantiated (specified by the optional name field above)
* Nonce counts number of times an account has authorized a transaction. Starts at 0, valid authorization must include the *next* nonce value.
* Assets are a map of all asset types -- STX, any on-chain assets specified by a Clarity contract (for example NFTs) -- to quantities owned by that account.
* Accounts need not be explicit "created" or registered; all accounts implicitly exist and are instantiated on first-use.

### Transactions

* Transaction types: coinbase, token-transfer, contract-deploy, contract-call, tenure-change.
* Only standard accounts (not contracts) can pay transaction fees.
* Transaction execution is governed by:

{% stepper %}
{% step %}
**Originating account**

The account that creates, authorizes and sends the transaction.
{% endstep %}

{% step %}
**Paying account**

The account that is billed by the leader for the cost of validating and executing the transaction.
{% endstep %}

{% step %}
**Sending account**

The account that identifies who is currently executing the transaction: this can change as a transaction executes via the `as-contract` Clarity function.
{% endstep %}
{% endstepper %}

* Transactions can be batched or streamed into blocks. The behavior can be controlled by the anchor mode of a transaction. With streaming (microblocks), a faster confirmation time is possible.
* Two types of authorizations: standard authorization is where originating account is the same as paying account. *Sponsored* authorization is where originating account and paying account are distinct. For instance, developers or service providers could pay for users to call their smart-contracts.
* For sponsored authorization, first a user signs with the originating account and then a sponsor signs with the paying account.
* Mempool limit for concurrent pending transactions is 25 per account
* Pending mempool transactions will be garbage-collected [256 blocks after receipt](https://github.com/stacks-network/stacks-blockchain/blob/master/src/core/mempool.rs#L62). With 10 minutes target block time, this would equal \~42 hours
* [Learn more about transaction encoding in SIP-005](https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md#transaction-encoding)
* [Transaction signing and verification are described in SIP-005](https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md#transaction-signing-and-verifying)
* All transactions impacting account balance are atomic, a transfer operation can not increment one account’s balance without decrementing another’s. However, transactions that perform multiple account actions (for example, transferring from multiple accounts) may partially complete.
* Transactions can include a memo string (max 34 bytes)


# Audits

<div data-with-frame="true"><figure><img src="/files/SEoRQeSeLaflkLZT7LrN" alt=""><figcaption></figcaption></figure></div>

#### Audits are just part of the story

For any project, layers of security are crucial. Audits represent one layer, while core developers and contributors collaborate to provide many more. Notable security programs, designs, and partners beyond audits include:

* Embedded security researchers [via Asymmetric Research](https://stacks.org/asymmetric-joins-stacks-ecosystem)
* Attackathon programs in partnership with Immunefi
* sBTC’s decentralized [network of validators/signers](https://www.stacks.co/sbtc) (removing the need to entrust a single entity and mitigating counterparty risk)
* Stacks’ underlying design that offers 100% Bitcoin finality, securing sBTC at the consensus level of a $2.5 billion network.
* Support at the app layer via [Hypernative](https://hackernoon.com/hypernative-bolsters-bitcoin-l2-security-as-stacks-ecosystem-gets-real-time-protection)
* Bitcoin L2 Labs' [whitehat security program](https://bitcoinl2-labs.github.io/2024/06/04/orange-hats.html)
* Stacks Foundation's partnership with Staking Defense League
* Stacks Founation's ongoing [Immunefi bug bounty program](https://immunefi.com/bug-bounty/stacks/information/)
* Dedicated Stacks Foundation Residents focused exclusively on fuzz and penetration testing (created [Rendezvous](https://stx-labs.github.io/rendezvous/))

{% hint style="warning" %}
*All 'high' or 'critical' issues listed in audits have either been mitigated or otherwise made obsolete, even if the report states otherwise.*
{% endhint %}

#### Stacks Core

Audits on Stacks Core

{% file src="/files/YQRg1Trk797MIhghvlJz" %}

{% file src="/files/L23xyKjbSJcyVqHSv3L8" %}

{% file src="/files/tZHnVHdROEx3iUciyfTB" %}

{% file src="/files/taJG1MuhmvT1gyXUZQbD" %}

{% file src="/files/nKK3jGNjFPePkAAcwFOc" %}

{% file src="/files/YjwZAJxfNgwH4vWb90Jz" %}

#### Other audits

{% file src="/files/D1Ibhab8UowKTe6lBTNN" %}

{% file src="/files/Q5cFnRbjsG5YjW3OKhz4" %}

{% file src="/files/H1Z2rFwYfFsOaPMzmCAy" %}

Trail of Bits Report, Stacks Blockchain (No PDF, [Github Issues List provided](https://github.com/diwakergupta/stacks-blockchain-tob-audit/issues))


# Block Production

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FAtIlPCw7qrGfrokaExNi%2Fblock-production-cover.png?alt=media&#x26;token=a3179850-9434-42ed-baf4-c64037aa5b03" alt=""><figcaption></figcaption></figure></div>

Block production is a key concept to understand how Stacks operates under the hood. This section walks through the three main actions that need to happen for the Stacks network to operate.

{% stepper %}
{% step %}
**Mining**

Miners are responsible for building and proposing new blocks on the Stacks chain.
{% endstep %}

{% step %}
**Signing**

Signing is the process used to validate blocks before they join the chain. A signer is a signer-manager contract bound to one signer key, and a block joins the chain only once signers carrying enough weight have signed it.
{% endstep %}

{% step %}
**Staking**

Staking is where that weight comes from. You lock STX in your own account and name an existing signer-manager contract; the stake you add becomes part of that manager's weight, and you earn Bitcoin-denominated rewards for it. Staking takes one of two mutually exclusive paths per account: STX-only, or a protocol bond pairing native BTC or sBTC with an STX lock.
{% endstep %}
{% endstepper %}

Three roles cooperate in Stacks block production: miners build and propose new blocks, signers validate and sign them, and stakers back the signers by locking STX to a signer-manager.

{% hint style="info" %}
**Signers here are not sBTC signers.** The signers on this page validate Stacks blocks under PoX-5. The [sBTC signers](https://docs.stacks.co/learn/sbtc/clarity-contracts/sbtc-signers) are a separate set with their own keys in their own contract, and they do not have to be Stacks signers. Their threshold signing requires more than 50% of the signer keys. The one connection is that the sBTC bridge is how miner-committed BTC becomes the sBTC paid out as staking rewards.
{% endhint %}

***

### Core Roles: Miner vs Staker vs Signer

<table><thead><tr><th width="94.29296875">Role</th><th>Primary Function</th><th>What They Do</th><th>Rewards</th><th>Where They Operate</th></tr></thead><tbody><tr><td><strong>Miner</strong></td><td>Produce Stacks blocks</td><td>Sends BTC in PoX to compete for the right to write the next block and earn STX</td><td>Earns STX block rewards + fees</td><td>Bitcoin (for bids) + Stacks</td></tr><tr><td><strong>Staker</strong></td><td>Secure the network via PoX</td><td>Locks STX in their own account and names a signer-manager contract</td><td>Earns Bitcoin-denominated rewards funded by miner BTC, as sBTC by default or native BTC by election</td><td>Stacks (the STX never leaves their account)</td></tr><tr><td><strong>Signer</strong></td><td>Validate and finalize blocks</td><td>A signer-manager contract bound to one signer key signs blocks; its weight is proportional to the STX staked through it</td><td>Receives per-staker settled rewards from pox-5 for distribution, and may take a fee set in the contract</td><td>Stacks</td></tr></tbody></table>

#### The relationship between Stakers and Signers

As you read through the Staking section, you may find stakers and signers mentioned in the same breath. Under PoX-5 the relationship is precise:

* Stakers are not signers\
  → signing is done by the key granted to the signer-manager contract they stake to, and running that signer is the manager operator's job
* Every signer is backed by **staked STX**\
  → to be in the signer set, a signer-manager must have at least 50,000 STX staked to it in aggregate, and its weight grows with the stake it represents


# How Are Blocks Mined?

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FKP7TV3rUxRBugJITtEOy%2Fmining-section-cover.png?alt=media&#x26;token=a3891617-2b64-4742-9a0c-004c6a70f944" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
**Builder Resources**

* For running your own Stacks miner, [here](https://docs.stacks.co/operate/run-a-miner).
  {% endhint %}

#### The Big Picture

* PoX selects a randomized single-leader block miner once per BTC block
* PoX incentivizes miners to make STX blocks and earn STX rewards + tx fees
* Miners send *block commit* transactions on Bitcoin L1.
* Block commits include: (block hash, VRF seed) pair
* Deterministic but unpredictable winner at each Bitcoin block
* PoX disincentivizes BTC L1 miners from interfering via ATC-C

***

### Intro

In Stacks mining, miners spend Bitcoin to earn the right to produce new Stacks blocks. Rather than introducing an entirely separate consensus mechanism, Stacks adapts and extends Bitcoin's existing Proof of Work. Stacks relies on Bitcoin's security and economic weight to secure the layer built on top of it.

When miners commit BTC as part of the mining process, that Bitcoin is not burned or wasted. Under PoX-5, it is routed into the reward pool, bridged automatically to sBTC, and distributed through the yield waterfall to staking participants: Bitcoin-paired protocol bonds first, then STX-only stakers and the protocol reserve. This flow of Bitcoin from miners to stakers is the core innovation behind Proof of Transfer (PoX). The "transfer" of BTC is what anchors Stacks to Bitcoin's security while aligning incentives between miners and network participants.

### Mining Flow Breakdown

In the previous version of Stacks (before the Nakamoto Upgrade), Stacks miners would mine new Stacks blocks at a one-to-one cadence with Bitcoin blocks. After Nakamoto, this is no longer the case. Under Nakamoto rules, miners are instead selected for a tenure that corresponds to a Bitcoin block. During this tenure, miners build and propose multiple Stacks blocks (roughly every 10 seconds) and signers will approve and append them.

{% hint style="info" %}
[What was the Nakamoto Upgrade?](/learn/block-production/what-was-the-nakamoto-upgrade)
{% endhint %}

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2Fca0oJCagFYDaEU3vw1e4%2Fmining-flow.png?alt=media&#x26;token=1d65f252-c0b3-4614-8166-726a22de4f42" alt="The mining cycle from registration through commitment and election to block assembly"><figcaption><p>The mining cycle, end to end</p></figcaption></figure></div>

Miners run Stacks nodes with mining enabled to participate in the PoX mechanism. The node handles each phase:

1. **Registration**: miners register for a future election by sending consensus data to the network
2. **Commitment**: registered miners transfer Bitcoin to participate in the election. Committed BTC is routed into the PoX-5 reward pool, where it is bridged to sBTC and paid out to staking participants.
3. **Election**: a verifiable random function chooses one miner for a new tenure to write blocks on the Stacks blockchain
4. **Assembly**: the elected miner writes the new blocks by pulling transactions from the mempool and collects rewards in the form of new STX tokens

### Miner Selection Process

As opposed to a block race, as in PoW, Stacks utilizes a single-leader election process called a cryptographic sortition. That is facilitated through an embedded verifiable random function state in Bitcoin transactions. This in turn allows for deterministic but unpredictable winners at each Bitcoin block.

<details>

<summary>What is a cryptographic sortition?</summary>

A cryptographic sortition is a process of randomly selecting one or more entities from a set using cryptography. This is a decentralized and verifiable way to select participants for a variety of tasks, such as consensus protocols, lotteries, and auctions.

More specifically, miner sortition in the context of Stacks is the weighted cryptographic sortition process by which a miner candidate is selected as the next miner (leader).

</details>

Every Stacks miner must register a VRF public key in a Bitcoin transaction. Once they do that, they can then issue *block commit* transactions on Bitcoin. Block commit transactions on Bitcoin contain:

`(block hash, VRF seed) pair`

These block commit transactions not only contain a pointer to the block stream they intend to produce, but also include all the relevant info to re-seed the next VRF for the next sortition. Miners cannot tamper with the VRF seed. This is enforced by the property:

`VRF seed = hash(VRF proof)`

And that VRF proof can only be generated by the miner's VRF private key.

<details>

<summary>How do block commits relate to each other?</summary>

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2F9l4YJ1AOry3SSTL724wd%2Fmining-leader-election-flow.png?alt=media&#x26;token=6dcfaefd-1362-4d10-a530-b726584b91d8" alt="Successive block commits, each carrying a VRF seed that re-seeds the next sortition"><figcaption><p>How one block commit feeds the next</p></figcaption></figure></div>

</details>

{% hint style="info" %}
To be considered for a tenure, a miner must have a block commit included in a Bitcoin block. If a miner wishes to update their commitment after submission, they may use Bitcoin's Replace-By-Fee.
{% endhint %}

#### Probability to mine next block

The miner who is selected to mine the next block is chosen depending on the amount of BTC the miners transfer. The probability for a miner to mine the next block is determined using a variation of the Assumed Total Commitment with Carryforward (ATC-C) [MEV](https://github.com/stacksgov/sips/blob/main/sips/sip-021/MEV-Report.pdf) mitigation strategy to allocate block rewards to miners. The probability a miner will win the sortition and be granted the current tenure will be based on a function that accounts for the total block commit spend on the blocks leading up to the current sortition.

While there is no minimum BTC commitment enforced by the protocol, in practice there is a floor constrained by dust: if the fees for a transaction exceed the value of the spent output, it is considered dust. How dust is [calculated](https://github.com/bitcoin/bitcoin/blob/master/src/policy/policy.cpp#L14) depends on a number of factors. We have found 5,500 satoshis to be a good lower bound per output. Under PoX-5 a block commit carries a single PoX output, so a commitment of at least 5,500 satoshis / block is recommended.

To calculate the amount of BTC to send, miners should:

* Guess the price BTC/STX for the next day (100 blocks later)
* Guess the total amount of bitcoin committed by all miners

{% hint style="info" %}
Signers are in charge of both validating and appending new blocks and conducting miner tenure changes.
{% endhint %}

#### Block Commit Transactions (on Bitcoin)

Under PoX-5, miners commit Bitcoin to **one** address in every leader block commit transaction: the sBTC bridge address that feeds the reward pool. The same output form applies to every block of the cycle, including the prepare phase. Nothing is sent to a burn address. This replaces the pre-PoX-5 model, in which each commit paid two addresses drawn from the reward set of stacking participants.

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FmPgihwk4yyZWRwlcHQ9k%2Fminer-btc-flow.png?alt=media&#x26;token=a2046c69-1021-414b-a487-d8837a96c2f5" alt="The block commit paying one output from the miner address to the sBTC bridge address on Bitcoin, and the automated flow on Stacks from the pox-5 contract through signer-managers to stakers"><figcaption><p>Where a miner's committed BTC ends up</p></figcaption></figure></div>

<details>

<summary>What does a block commit transaction actually look like?</summary>

* Watch this [clip](https://youtube.com/shorts/HPRsn-aSYrg?si=Y7hA7_9BeHFxV0zz) describing what goes into a block commit transaction on Bitcoin.
* Check out a previous block commit transaction on Bitcoin [here](https://mempool.space/tx/42834cb7ec9ca3e2b51e2ff16bd809ae049c925ed8d3da099c9ce3d5292d2a91).

</details>

### Miner rewards

Miners receive Stacks blocks' coinbase rewards for tenures they win.

The reward is a flat **1,000 STX per tenure**. [SIP-045](https://github.com/stacksgov/sips/blob/main/sips/sip-045/sip-045-pox-5-bitcoin-staking.md) restored the coinbase to 1,000 STX at Epoch 4.0 activation and removed the reduction schedule established under SIP-029, so no further scheduled reductions exist.

#### Transaction fees

Miners also receive Stacks fees for transactions mined in any block they produce.

#### Reward maturity

Block rewards and transaction fees take 100 blocks on the Bitcoin blockchain to mature. After successfully mining a block your rewards appear in your Stacks account after \~24 hours.

### Stacks mining in practice

Stacks runs with a small number of miners. That is a consequence of how the incentives work rather than a gap in them.

Stacks miners function similarly to sequencers in L2 systems in that they are only responsible for constructing and proposing new blocks, not appending them to the chain. But unlike most Ethereum L2s that operate with just a single centralized sequencer, Stacks consistently has at least 4-5 miners with open membership allowing anyone to join.

Block production on Stacks separates the work: miners construct and propose blocks, while signers, backed by stakers' locked STX, validate and append them. This separation limits what a miner can do to the chain.

Miners cannot reorganize the chain. In the worst case they can omit some kinds of transactions, and running your own miner addresses that.

More miners on the network would mean fewer rewards for stakers, as miners would have to spend more of their funds on Bitcoin L1 fees rather than sending it into the reward pool.

<details>

<summary><strong>Wouldn't more miners mean more competition, meaning more rewards?</strong></summary>

The reason more miners means fewer rewards is because miners act economically rationally, and they don't have an unlimited amount of BTC to work with.

Miners are paying their PoX commitments plus their Bitcoin fees for a chance to win the coinbase (1,000 STX) plus fees for a tenure. If there are more miners, they will each pay less, because they will have a lower chance of winning. They can't pay ever-increasing amounts of BTC because at some point they will never be profitable, so there is a limit to how much BTC they can spend in order to try and win a tenure.

As they pay less, the Bitcoin fee becomes a more significant portion of their expenses, and that also decreases their odds of winning the tenure.

Here's a concrete example:

Let's say Stacks is trading at 1,000 Sats per STX.

The total spend from all miners, if everyone is acting logically and we ignore Stacks fees, would be less than 1,000,000 Sats (1,000 STX coinbase \* 1000 Sats/STX).

If that is from 5 miners, then it could be 10,000 Sats (2,000 Sats for each transaction) going to Bitcoin fees and 990,000 Sats going to PoX.

If there are 100 miners, then it would be 200,000 Sats going to Bitcoin fees, and 800,000 Sats going to PoX.

</details>

This creates a natural economic equilibrium where:

{% stepper %}
{% step %}
**Enough miners participate to ensure blocks are produced reliably**
{% endstep %}

{% step %}
**Stakers receive optimal rewards**
{% endstep %}

{% step %}
**The network maintains censorship resistance without unnecessary mining competition**
{% endstep %}
{% endstepper %}

This design is intentional. Stakers act as complementary security guarantors who receive Bitcoin-denominated rewards via PoX, so Stacks achieves security without requiring an excessive number of miners competing solely to win block production rights.

Unlike other chains where miners alone determine the canonical chain, Stacks' two-party system provides stronger guarantees:

* Miners cannot force invalid transactions or blocks (signers won't sign them, and even if they did, the nodes would not accept them)
* No miner can unilaterally reorg the chain (signers control chain finality)
* Accepting a block requires signatures carrying at least 70% of total signer weight, ensuring broad consensus before blocks are accepted

This separation of concerns between miners and signers is why a small number of miners is not a weakness.

<details>

<summary>What happened to microblocks?</summary>

Microblocks are a legacy feature of the previous version of Stacks that no longer exist. They were originally created as a way to improve transaction throughput, but without the functionality of Nakamoto, they never worked in practice.

Nakamoto instead uses a block production structure that creates Stacks blocks at a rapid cadence. See [What was the Nakamoto Upgrade?](/learn/block-production/what-was-the-nakamoto-upgrade).

</details>

### Bitcoin MEV Mitigation

Miner Extractable Value (MEV) has been a longstanding issue across many blockchains, including Stacks pre-Nakamoto.

MEV refers to the potential profit miners can extract from the manipulation of transaction inclusion and ordering within the blocks they produce, which can lead to unfair practices and diminished trust in the network.

In pre-Nakamoto releases of Stacks, Bitcoin miners with a significant percentage of Bitcoin's hashrate had the ability to censor commitment transactions of other Stacks miners, ensuring they were able to win the block rewards and fees of Stacks blocks where they were also the winner of the Bitcoin block as a Bitcoin miner.

The Nakamoto system uses a variation of the Assumed Total Commitment with Carryforward (ATC-C) [MEV](https://github.com/stacksgov/sips/blob/main/sips/sip-021/MEV-Report.pdf) mitigation strategy to allocate block rewards to miners. The probability a miner will win the block and be granted the current tenure will be based on a function that accounts for the total block commit spend on the blocks leading up to the current block.

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FKR4LNqlqDmrC4hBmUwOB%2FATCC-formula.png?alt=media&#x26;token=ade7ed3f-2d1e-4124-8768-467069afca60" alt="The Assumed Total Commitment with Carryforward formula"><figcaption><p>The ATC-C formula</p></figcaption></figure></div>

The ATC solution leaves the option for a block to have no valid winner. The TenureChange-Extend transaction mitigates the majority of adverse effects caused by a missed block.

***

#### Additional Resources

* \[[Stacks YT](https://youtu.be/F31B-my510A?si=E0SRw0bbhuevB4kj)] The Stacks & Bitcoin Miners Relationship
* \[[Stacks YT](https://youtu.be/bhVyM5CYoh4?si=3bQl8Q_iJ_3z5jX-)] Long Term Security Budget & Miner Incentives for Bitcoin


# Staking: How STX Holders Contribute

How staking works under PoX-5: locking STX to a signer-manager contract, earning Bitcoin-denominated rewards, and what the lock does and does not do.

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FAkgFBWqIWWeT5ZeNwVzp%2Fstaking-cover.png?alt=media&#x26;token=82fd722d-efae-4218-ae0e-42ac6215fe4a" alt="Staking"><figcaption></figcaption></figure></div>

{% hint style="info" %}
**Builder Resources**

* All staking operations happen in the PoX contract implementation, [pox-5 on the Explorer](https://explorer.hiro.so/txid/SP000000000000000000002Q6VF78.pox-5?chain=mainnet).
* To start staking STX, see the [Staking STX guides](https://docs.stacks.co/operate/staking-stx).
  {% endhint %}

#### The Big Picture

* Staking locks STX to help secure the network and earn Bitcoin-denominated rewards.
* It is part of Proof of Transfer (PoX): miners commit BTC, and that BTC pays stakers.
* You stake by naming a signer-manager contract. The STX locks in your own account and never moves.
* There is no per-staker minimum. A signer-manager needs 50,000 STX in aggregate to enter the signer set.
* You can unstake an STX-only position at any time, and the STX unlocks at the start of the next cycle. Bond-paired STX is committed for the bond term.
* Rewards arrive as sBTC by default. A native BTC payout can be elected through your signer-manager.

***

### Intro

Staking rewards Stacks (STX) token holders with Bitcoin-denominated payouts for locking their tokens and backing the signers that validate blocks. Signers are covered in the [Signing section](/learn/block-production/signing). This page is a conceptual overview of staking under PoX-5.

`pox-5.clar` is the staking contract. It activated with the Epoch 4.0 hard fork at Bitcoin block 960,230 and replaced `pox-4`. Every staking function lives at the deployed contract:

* Mainnet: [`SP000000000000000000002Q6VF78.pox-5`](https://explorer.hiro.so/txid/SP000000000000000000002Q6VF78.pox-5?chain=mainnet)
* Testnet: the primary Hiro testnet runs PoX-5, with Epoch 4.0 activating at burnchain height 2,702. To run a node against it, start from the [example testnet follower configuration](https://docs.stacks.co/reference/node-operations/readme-1#example-testnet-follower-configuration), which carries the PoX-5 parameters (`pox_5_sbtc_contract`, `pox_5_sbtc_registry_contract`, `pox_5_bond_admin`).
* Devnet: [Clarinet](https://github.com/hirosystems/clarinet) 3.23.0 and later runs devnet on Epoch 4.0 and Clarity 6 by default, with pox-5 available out of the box from a devnet snapshot that starts at block 163.

The pinned source is [`pox-5.clar` at release 4.0.1](https://github.com/stacks-network/stacks-core/blob/4.0.1/stackslib/src/chainstate/stacks/boot/pox-5.clar), and [SIP-045](https://github.com/stacksgov/sips/blob/main/sips/sip-045/sip-045-pox-5-bitcoin-staking.md) specifies the design.

<details>

<summary>How this differs from proof-of-stake staking</summary>

The mechanism shares the shape of staking: lock a token, back consensus, earn yield. What still differs from staking on a proof-of-stake network:

**Yield comes from an external token, not issuance**

In proof-of-stake, you lock one token and earn yield in the same token, funded by the currency's issuance schedule. [Ethereum's issuance rate](https://ethereum.org/en/roadmap/merge/issuance/#post-merge) is set algorithmically against how much ETH is burned in fees. In PoX, you lock STX and the yield is denominated in the burnchain token: BTC, committed by Stacks miners, paid out as sBTC or native BTC. Stacks does issue new STX, but that issuance is separate from staking and does not fund staking rewards.

**No slashing**

Stakers back a consensus-critical role, but PoX has no slashing. Locked STX is never destroyed or seized. A signer that fails to perform forfeits rewards, not principal.

</details>

#### Locking and Unlocking STX

When STX locks, no transfer occurs. Locking is non-custodial: the tokens stay in your account and become unspendable at the protocol level.

Unlocking is implicit. At the start of the cycle after your chosen duration ends, or after you unstake, the tokens become spendable again. No transaction unlocks them.

***

### The Signer-Manager Relationship

Staking means locking STX and naming a signer-manager contract to act for you. The signer-manager is the contract your stake routes through: it validates your stake when you enter, is bound to the signer key that signs blocks, and distributes your rewards.

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FtgQWu2VHlMNA9q0uE9YH%2Fsigner-manager-relationship.png?alt=media&#x26;token=11367cc6-5f5a-4d1c-aada-8cefd809551b" alt="The staker, the signer-manager contract, and pox-5, with the STX lock staying in the staker&#x27;s account and rewards flowing back through the manager"><figcaption><p>How a stake reaches the signer set</p></figcaption></figure></div>

Who does what:

* **You, the staker**, lock STX in your own account and choose how many cycles it covers, from 1 to 96.
* **The signer-manager contract** is bound to a signer key once, through a one-time [SIP-018](https://github.com/stacksgov/sips/blob/main/sips/sip-018/sip-018-signed-structured-data.md) grant, and receives your settled rewards for onward distribution. It may take a fee, which is contract-level logic rather than a protocol feature.
* **The pox-5 contract** registers your position for every cycle you chose in the single staking transaction, and settles rewards per staker to the manager.

A signer-manager enters the signer set once at least 50,000 STX (`SIGNER_SET_MIN_USTX`) is staked to it in aggregate. The threshold is fixed, and it applies to the manager rather than to you: your own stake can be any size.

Running your own signer-manager and staking to someone else's are the same mechanism. A "solo" staker is someone running their own manager, which is operationally identical to offering a pool, because anyone can stake to that contract.

{% hint style="info" %}
Choosing a manager means reading its fee, fee ceiling, admin set, and grant status, all of which are on-chain. [Stake to an Existing Signer-Manager](https://docs.stacks.co/operate/staking-stx/stack-with-a-pool) covers what to check.
{% endhint %}

***

### Staking Flow

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FNSXVJ0OeRMpl5Ll36AHh%2Fstaking-flow.png?alt=media&#x26;token=91152a0a-f449-46ae-a146-65df613ba9c9" alt="The staking flow between a staker and the pox-5 contract: choose a signer-manager, stake, earn across cycles, get paid, unstake"><figcaption><p>Staking, start to finish</p></figcaption></figure></div>

{% stepper %}
{% step %}
**Choose a signer-manager**

Pick a contract whose fee and admin set you accept; both are readable on-chain before you commit.
{% endstep %}

{% step %}
**Broadcast the staking transaction**

`stake` names the manager, the amount, and a duration of 1 to 96 cycles, and locks the STX in your account.
{% endstep %}

{% step %}
**Earn across cycles**

The one transaction registers you for every cycle you chose, and no further action keeps you in the reward set.
{% endstep %}

{% step %}
**Get paid**

pox-5 settles rewards per staker to your manager, which distributes them as sBTC, or as native BTC if you elected that.
{% endstep %}

{% step %}
**Unstake when you choose**

`unstake` ends the position and the STX unlocks at the start of the next cycle.
{% endstep %}
{% endstepper %}

{% hint style="warning" %}
Staking, staking updates, and unstaking are blocked during the prepare phase, the last 100 Bitcoin blocks of every reward cycle, while the upcoming cycle's signer set is frozen. This recurs every cycle.
{% endhint %}

`stake-update` changes a live position without a cooldown: switch managers, increase the amount, extend the duration, or rotate a payout address. Changes take effect from the start of the next cycle. Reducing your locked amount is the exception, and still costs a cycle.

### Staking Cycles

Staking happens in reward cycles of 2,100 Bitcoin blocks (roughly two weeks). The last 100 Bitcoin blocks of each cycle are the prepare phase, in which the upcoming cycle's signer set is fixed and staking transactions are rejected.

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2Ffz7B1xYNMnl5u5ICddZi%2Fstaking-cycles.png?alt=media&#x26;token=7aea0cf7-4dee-42af-a195-acf5c9aade65" alt="A reward cycle of 2,100 Bitcoin blocks ending in a 100-block prepare phase, with reward distributions every 1,050 blocks and unlocks at the cycle boundary"><figcaption><p>One reward cycle, block by block</p></figcaption></figure></div>

* The prepare phase fixes the signer set for the upcoming cycle: every signer-manager with at least 50,000 STX staked to it in aggregate.
* During the reward phase, miners commit BTC to mine Stacks blocks, and that BTC funds staker rewards.
* Rewards are credited once per distribution interval of 1,050 Bitcoin blocks (roughly one week), two intervals per reward cycle. The interval gates crediting only: your signer-manager can claim credited rewards at any time.
* Unlocks happen at a cycle boundary: at the start of the cycle after your chosen duration ends, or after you unstake.

{% hint style="info" %}
The two-week target comes from Bitcoin's 10-minute target block time, so a cycle stretches when Bitcoin blocks run slow.
{% endhint %}

***

### Two Ways to Participate

PoX-5 has two participation paths, and a Stacks principal can hold one position in one path at a time.

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FE8dFBwzzAgg3X2CtEBn4%2Fstaking-participation-paths.png?alt=media&#x26;token=469a09a9-c442-42cc-9907-2cb7f763294d" alt="STX-only staking beside a Bitcoin-paired protocol bond, mutually exclusive per Stacks principal"><figcaption><p>The two paths, side by side</p></figcaption></figure></div>

**STX-only staking** locks STX alone. You choose 1 to 96 cycles, you can unstake at any time outside the prepare phase with the unlock at the next cycle start, and there is no capacity limit. Rewards come from the miner BTC left after protocol bond obligations, split 85% to STX-only stakers pro rata and 15% to the protocol reserve.

**Bitcoin-paired protocol bonds** pair a BTC commitment with an STX lock for a bond term of 12 cycles (roughly six months). The BTC side is either a timelocked UTXO on Bitcoin L1 that stays under your own keys, or sBTC, which pox-5 holds for the term. Bonds target a fixed yield rate on the BTC side; the paired STX earns no yield. Capacity is allocated per bonding period, so registering requires an allowance for that period, and `register-for-bond` is the entry point.

In the bootstrap phase that allowance is allocated by the Stacks Endowment to whitelisted partners, with roughly a tenth of bond capacity kept open through selected pooling partners, so most participants reach a bond through a pool rather than by calling `register-for-bond` themselves. Liquid staking products work differently again: you deposit into the product, the product stakes, and you hold a token representing your share, so pox-5 never records you as a staker at all.

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FRIZYeYjWEOj7wqhN6rM2%2Fprotocol-bonds.png?alt=media&#x26;token=c62adaed-b393-483e-b600-8ec0389d72b0" alt="Six staggered bonding periods overlapping, and the anatomy of one bond period from enrollment to STX unlock"><figcaption><p>Six bonds running at once</p></figcaption></figure></div>

Bonding periods are staggered: a new one opens every two reward cycles (about a month), each runs twelve cycles, and six are active at any moment, so a bond that ends is immediately followed by one that starts. The BTC timelock expires 1,050 Bitcoin blocks (about a week) before the bond ends, and that window is when you can re-lock BTC for the next bond. On a roll-over the STX lock extends without unlocking; otherwise the STX unlocks when the bond ends. Exiting early (`unstake-sbtc`, or the L1 early-exit path) forfeits the remaining yield, never principal, and the paired STX stays locked to term.

Both paths route through a signer-manager, and both keep the STX in your account. Registering a bond while STX-only staking, or the reverse, is rejected by the contract.

The bond mechanics in depth are in [SIP-045](https://github.com/stacksgov/sips/blob/main/sips/sip-045/sip-045-pox-5-bitcoin-staking.md) and the [Bitcoin Staking whitepaper](https://github.com/stacksgov/sips/blob/main/sips/sip-045/sip-045-5.pdf).

***

### Staking and Signing

Staking and signing are distinct actions, and both are necessary. The staked STX decides how much weight a signer carries, and the signer key does the signing. A signer-manager connects the two: it is bound to one signer key through a one-time grant, and the signer software detects from chain state whether its manager is in the signer set for the upcoming cycle.

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FS1L4pYrXDd1Ju74JhJkr%2Fstaking-and-signing.png?alt=media&#x26;token=3395cd31-c1fa-4f1a-97e0-f762285052c7" alt="Manual staking transactions feeding the reward phase, and the signer software acting automatically once its manager is in the signer set"><figcaption><p>What you do, and what the signer does</p></figcaption></figure></div>

You do not run a signer to stake. The manager you stake to is bound to one, and your stake adds to its weight. Running your own signer means deploying a signer-manager, binding your signer key to it, and operating the signer software: see [Deploy a Signer Manager Contract](https://docs.stacks.co/operate/deploy-a-signer-manager-contract) and [Run a Signer](https://docs.stacks.co/operate/run-a-signer).

Signing itself is covered in [Signing: Verifying Block Validity](/learn/block-production/signing).

***

### How and Where to Stake

Anyone with STX in their own account can stake. [app.leather.io/staking](https://app.leather.io/staking) lists signer-managers to pick from, and several pool operators run their own staking apps. Whichever you use, the transaction goes to `pox-5`.

For step-by-step instructions, see the [Staking STX guides](https://docs.stacks.co/operate/staking-stx).

***

### If You Knew Stacking Under PoX-4

The network renamed stacking to staking with PoX-5, and the mechanics changed with the name. The corrections to the old model, in one place:

* Every PoX-4 position unlocked when Epoch 4.0 activated. Re-enroll under PoX-5 to keep earning.
* Solo and pooled stacking were separate mechanisms. Both are replaced by staking to a signer-manager, and the protocol has no delegator or pool operator role.
* `delegate-stx`, `revoke-delegate-stx`, and `stack-aggregation-commit` no longer exist. No operator commits per cycle on your behalf, so a missed commit can no longer cost a pool a cycle of rewards.
* The dynamic minimum is gone, and the `min_threshold_ustx` field with it.
* Per-transaction signer signatures are gone, replaced by the one-time signer-key grant.
* The cooldown cycle is gone for everything except reducing your locked amount, which still costs a cycle.
* [SIP-007](https://github.com/stacksgov/sips/blob/main/sips/sip-007/sip-007-stacking-consensus.md) describes PoX before Nakamoto, and [SIP-021](https://github.com/stacksgov/sips/blob/main/sips/sip-021/sip-021-nakamoto.md) describes Nakamoto. Read both as history rather than current behavior.

[What's Changed in PoX-5](https://docs.stacks.co/operate/staking-stx/whats-changed-in-pox-5) covers the migration in operator detail.

***

#### Additional Resources

* [SIP-045: PoX-5, Bitcoin Staking](https://github.com/stacksgov/sips/blob/main/sips/sip-045/sip-045-pox-5-bitcoin-staking.md)
* [Bitcoin Staking whitepaper](https://github.com/stacksgov/sips/blob/main/sips/sip-045/sip-045-5.pdf)
* [pox-5.clar at release 4.0.1](https://github.com/stacks-network/stacks-core/blob/4.0.1/stackslib/src/chainstate/stacks/boot/pox-5.clar)
* [Staking STX guides](https://docs.stacks.co/operate/staking-stx)


# Signing: Verifying Block Validity

How signers validate and sign Stacks blocks under PoX-5: how the signer set is chosen each cycle, what a valid block is, and how tenure changes work.

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FjFK8dOojyXCt47QStvhQ%2Fsigning-cover.png?alt=media&#x26;token=a5b8dfbc-f35b-4928-b2b8-b82ac4dd46dc" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
**Builder Resources**

* To operate as a signer, see [Run a Signer](https://docs.stacks.co/operate/run-a-signer).
* To view a full list of active signers, see the [Explorer's signers page](https://explorer.hiro.so/signers?chain=mainnet).
  {% endhint %}

#### The Big Picture

* Signers validate and sign proposed Stacks blocks before they can join the chain.
* The signer set is fixed each reward cycle: every signer-manager with at least 50,000 STX staked to it.
* A signer's voting weight is proportional to the STX staked through it.
* Accepting a block requires signatures carrying at least 70% of total signer weight.
* Signing prevents forks and anchors Stacks history to Bitcoin.

***

### Intro

Signers play a role in the Stacks network that had previously belonged to miners. Before the Nakamoto upgrade, miners both decided the contents of blocks and decided whether blocks joined the chain. Since Nakamoto, each actor holds one of those responsibilities:

* **Miners** decide the contents of blocks.
* **Signers** decide whether a block is included in the chain.

The bulk of the complexity in the Nakamoto changes went into separating these two concerns while keeping both mining and staking open-membership. Anyone can become a miner and anyone can become a staker. [SIP-021](https://github.com/stacksgov/sips/blob/main/sips/sip-021/sip-021-nakamoto.md) describes the design as it was introduced.

Signers are required to acknowledge and validate a miner's block before it can be appended to the chain. To do so, they must first agree on the canonical chain tip, then apply the block on that tip to determine its validity. Once enough signers agree that the block is both canonical and valid, their signatures accompany the block as it replicates to the rest of the Stacks peer network, and only at that point do nodes append it to their chain histories.

This behavior prevents forks. If a miner builds a block atop a stale tip, signers refuse to sign it. If signers cannot agree on the canonical Stacks tip, no block is appended in the first place. The failure mode this creates, a chain that halts while signers disagree, is mitigated by keeping the signer set large and diverse enough that quorum is met at all times, and by paying signers through PoX rewards to stay online.

***

### How Signers Are Selected

Under PoX-5, a signer is a signer-manager contract bound to one signer key. The binding happens once: the signer-key holder signs a [SIP-018](https://github.com/stacksgov/sips/blob/main/sips/sip-018/sip-018-signed-structured-data.md) grant naming the manager, and the manager submits it through `grant-signer-key` and registers with `register-signer`. The key holder can revoke the grant at any time with `revoke-signer-grant`, which stops the manager accepting new stake while existing positions wind down.

During each prepare phase, the last 100 Bitcoin blocks of a reward cycle, the signer set for the upcoming cycle is fixed: every registered signer-manager with at least 50,000 STX (`SIGNER_SET_MIN_USTX`) staked to it in aggregate. A signer's voting weight for that cycle is proportional to the total STX staked through it, counting the STX in STX-only stakes and the STX side of protocol bonds together. The BTC side of a bond carries no signing weight: signing weight, like governance weight, is a function of locked STX alone.

The signer software detects from chain state whether its manager is in the upcoming cycle's signer set. Staking transactions are sent manually; everything the signer does with that information is automatic.

#### The relationship between stakers and signers

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FS1L4pYrXDd1Ju74JhJkr%2Fstaking-and-signing.png?alt=media&#x26;token=3395cd31-c1fa-4f1a-97e0-f762285052c7" alt="Manual staking transactions feeding the reward phase, and the signer software acting automatically once its manager is in the signer set"><figcaption><p>Manual on the staker's side, automatic on the signer's</p></figcaption></figure></div>

* Stakers are not signers. Signing is done by the key granted to the signer-manager they stake to, and running that signer is the manager operator's job.
* Every signer is backed by staked STX. To be in the signer set, a manager must represent at least the 50,000 STX aggregate threshold, and its weight grows with the stake it represents.

***

### Signer Signing

When a miner proposes a block, each signer validates it independently and signs it with its granted signer key. The block carries the resulting set of signatures, and a node accepts it only when the signatures are valid, free of duplicates, ordered consistently with the signer set, and together carry at least 70% of the total signer weight for the cycle. The threshold is a consensus constant in the node ([`NAKAMOTO_SIGNER_BLOCK_APPROVAL_THRESHOLD`](https://github.com/stacks-network/stacks-core/blob/4.0.1/stackslib/src/core/mod.rs)).

Weight, in this protocol, is stake: a signer-manager representing 10% of all staked STX carries 10% of the vote on every block. Blocks are accepted by an economic majority of the locked capital, which is what ties block production back to the staking described on the [Staking page](/learn/block-production/staking).

***

### Validating and Appending New Blocks

When miners are selected for a new tenure, they begin building blocks from transactions in the mempool and send them to signers for approval. Signers must approve a block with at least 70% of signer weight for it to be appended to the chain.

Signers approve a block based on several properties:

* The block is well-formed
  * It has the correct version and mainnet/testnet flag
  * Its header contains the right number of Stacks blocks preceding this one.
  * Its header contains the correct total Bitcoin spent in the sortition that elected the current tenure.
  * Its header contains the same Bitcoin block hash as the Bitcoin block that contains its tenure's block-commit transaction\*
  * Its header contains the correct parent block ID of the immediate parent of this block.\*
  * The transaction Merkle tree root is consistent with the transactions
  * The state root hash matches the MARF tip root hash once all transactions are applied
  * The block header has a valid ECDSA signature from the miner.
  * The block header carries signer signatures meeting the 70% weight threshold.
* All Bitcoin transactions since the last valid sortition up to (but not including) this tenure's block-commit's Bitcoin block have been applied to the Stacks chain state\*
* In the case of a tenure start block:
  * The first transaction is the `TenureChange` transaction.
  * The first transaction after the `TenureChange` transaction is a `Coinbase`.

The properties marked with \* are collectively how Stacks ensures Bitcoin finality. By adhering to them, miners can only append blocks that build atop the correct chain tip, which also anchors the history to Bitcoin.

### Conducting Miner Tenure Changes

The other primary signing responsibility in block production is conducting tenure change transactions. As discussed in the mining section, miners submit a `block-commit` transaction on the Bitcoin chain to initiate mining. If a miner is selected, signers detect that and create a `tenure-change` transaction.

This tenure change transaction includes:

| Name                           | Description                                                                                                                                                                                                                                                                                                                                           | Representation      |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| tenure consensus hash          | Consensus hash of this tenure. Corresponds to the sortition in which the miner of this block was chosen. It may be the case that this miner's tenure gets extended across subsequent sortitions; if this happens, then this `consensus hash` value remains the same as the sortition in which the winning block-commit was mined.                     | 20 bytes            |
| previous tenure consensus hash | Consensus hash of the previous tenure. Corresponds to the sortition of the previous winning block-commit.                                                                                                                                                                                                                                             | 20 bytes            |
| burn view consensus hash       | Current consensus hash on the underlying burnchain. Corresponds to the last-seen sortition.                                                                                                                                                                                                                                                           | 20 bytes            |
| previous tenure end            | The index block hash of the last Stacks block from the previous tenure.                                                                                                                                                                                                                                                                               | 32 bytes            |
| previous tenure blocks         | The number of blocks produced since the last sortition-linked tenure.                                                                                                                                                                                                                                                                                 | 4 bytes, big-endian |
| cause                          | <p>A flag to indicate the cause of this tenure change<br>- <code>0x00</code> indicates that a sortition occurred, and a new miner should begin producing blocks.<br>- <code>0x01</code> indicates that the current miner should continue producing blocks. The current miner's tenure execution budget is reset upon processing this transaction.</p> | 1 byte              |
| pubkey hash                    | The ECDSA public key hash of the current tenure.                                                                                                                                                                                                                                                                                                      | 20 bytes            |

This tenure change transaction is then sent to the newly elected miner, who must include it as the first transaction in their first block, otherwise signers will not approve it.

This process repeats as new miners are elected for tenures.

[SIP-021](https://github.com/stacksgov/sips/blob/main/sips/sip-021/sip-021-nakamoto.md) has a detailed description of what happens under the hood during these processes.

***

### If You Knew Signing Under PoX-4

The corrections to the old model, in one place:

* Stackers registered a block-signing key with every stacking or delegate-stack transaction. That is gone: a signer-manager holds one signer key through a one-time grant, revocable by the key holder.
* Reward slots are gone, and with them the cap of 4,000 slots per cycle. The signer set is the set of qualifying signer-managers, and weight comes from staked STX rather than slots clinched.
* Delegation is gone, so the old distinction between stackers who sign and stackers who delegate their signing no longer describes anything. Signing belongs to the key granted to the signer-manager a staker stakes to.
* SIP-021 specifies signing with an aggregate Schnorr signature generated through the WSTS protocol, including a distributed key generation round each cycle. The node validates blocks against a set of individual signer signatures weighted by stake, as described above. Read the WSTS material in SIP-021 as design history.

***

#### Additional Resources

* [SIP-021: Nakamoto](https://github.com/stacksgov/sips/blob/main/sips/sip-021/sip-021-nakamoto.md)
* [SIP-045: PoX-5, Bitcoin Staking](https://github.com/stacksgov/sips/blob/main/sips/sip-045/sip-045-pox-5-bitcoin-staking.md)
* [pox-5.clar at release 4.0.1](https://github.com/stacks-network/stacks-core/blob/4.0.1/stackslib/src/chainstate/stacks/boot/pox-5.clar)
* [Run a Signer](https://docs.stacks.co/operate/run-a-signer)
* [Generate a Signer Signature](https://docs.stacks.co/operate/staking-stx/generate-signer-signature)


# Bitcoin Finality

<div data-with-frame="true"><figure><img src="/files/u5uaP1QhTvbx8i8R8MCW" alt=""><figcaption></figcaption></figure></div>

The concept of 100% Bitcoin finality is crucial to the design of Stacks. This is what turns Stacks into a true Bitcoin L2 and allows it to leverage all of the security inherent in Bitcoin.

Finality refers to the point at which transactions are irreversible. Once a blockchain reaches finality, it is nearly impossible to change the ledger's history without undertaking extraordinary measures that are often computationally and economically prohibitive.

When we talk about Stacks blocks having 100% Bitcoin finality, we mean that they are as hard to reverse as Bitcoin transactions themselves.

That's a bold claim, so how does Stacks accomplish that?

As discussed above, miners are responsible for producing Stacks blocks in their tenure, which corresponds to a single Bitcoin block. As part of their block commit transaction, which is the transaction that previously committed the hash of the next Stacks block to the Bitcoin chain, miners will instead be required to add an indexed block hash.

The indexed block hash is the hash of the first block produced by the last Stacks miner in their tenure. This is the SHA512/256 hash of both the consensus hash of all previously-accepted Bitcoin transactions that Stacks recognizes, as well as the hash of the block itself.

This will anchor the Stacks chain history to Bitcoin up to the start of the previous miner's tenure, as well as all causally-dependent Bitcoin state that Stacks has processed. This ensures Bitcoin finality, resolves miner connectivity issues by putting fork prevention on stackers, and allows nodes with up-to-date copies of the Stacks chain state to identify which Stacks blocks are affected by a Bitcoin reorg and recover the affected Stacks transactions.

This relationship between Stackers, miners, Bitcoin blocks, and Stacks blocks is what maintains Bitcoin finality while allowing miners to rapidly produce Stacks blocks. Bitcoin finality is achieved because at every Bitcoin block N + 1, the state of the Stacks chain as of the start of tenure N is written to Bitcoin. Even if at a future date all of the former Stackers’ signing keys were compromised, they would be unable to rewrite Stacks history for tenure N without rewriting Bitcoin history back to tenure N + 1.

Because of this, Stacks transactions can be considered to have Bitcoin finality after the tenure they are a part of concludes, or Bitcoin block N + 1. As an example, if I initiate a Stacks transaction that gets confirmed by a Stacks miner, at the conclusion of that miner's tenure (the end of the current Bitcoin block) that transaction will be written to Bitcoin as part of the Stacks chain state and all future miners are required to build off of that chain tip, making reversing the transaction as difficult as reversing the corresponding Bitcoin transaction.

{% hint style="info" %}
Key point: At every Bitcoin block N + 1 the state of the Stacks chain as of the start of tenure N is anchored to Bitcoin. This makes reversing Stacks history for tenure N as hard as rewriting Bitcoin history back to N + 1.
{% endhint %}

## Nakamoto Transactions and Bitcoin Reorgs

If Nakamoto transactions follow Bitcoin finality, what happens if Bitcoin forks?

In order to answer this question, we need to distinguish between two types of Stacks transactions: Bitcoin-reliant and internal.

{% hint style="info" %}

* **Bitcoin-reliant** transactions are transactions that read Bitcoin state. If Bitcoin forks, these transactions will change. For these, you cannot do better than following Bitcoin finality. For example, if you moved BTC from L1 to L2, you must wait for Bitcoin finality before your L2 BTC can be used (you don’t have any L2 BTC if the L1 transaction becomes unconfirmed due to a fork).
* **Internal** transactions don't rely on Bitcoin state, and thus won't change if Bitcoin forks. These can have faster confirmations because even if Bitcoin forks, signers can ensure they are re-processed in the same order.
  {% endhint %}

The key takeaway is this:

Under Nakamoto Stacks, transactions won’t impactfully reorganize due to a Bitcoin fork. Not only is reorging relatively infrequent, but transactions on Stacks that got reorganized due to a Bitcoin fork behave just as reorganized Bitcoin transactions do. With some future analysis, transactions purely on the L2 chain may one day be entirely unaffected.

<details>

<summary>Read more about Bitcoin reorg behavior</summary>

If you are interested in learning more about how this works, see the [Bitcoin Reorgs](/learn/block-production/bitcoin-reorgs) page of the docs.

</details>

***

{% embed url="<https://youtu.be/w2mA3ajOoNQ?si=IK8w4Kxd6v0acdDB>" %}


# Bitcoin Reorgs

<div data-with-frame="true"><figure><img src="/files/5Ok44NVfati4n3rdC4HE" alt=""><figcaption></figcaption></figure></div>

Stacks transactions don’t impactfully reorganize due to a Bitcoin fork. Not only is reorging relatively infrequent, but transactions on Stacks that got reorganized due to a Bitcoin fork behave just as reorganized Bitcoin transactions do. With some future analysis, transactions purely on the L2 chain may one day be entirely unaffected.

Understanding this concept fundamentally comes down to understanding finality on post-Nakamoto Stacks.

{% hint style="info" %}
Stacks won’t fork on its own. It is designed not to fork with only special exceptions, and it’s entirely infeasible for Stacks to fork on its own if even 31% of Stackers don’t want it to fork, and even then it would likely only happen within the span of a single tenure.

The only case in which Stacks forks is if Bitcoin forks cause it to fork.
{% endhint %}

Instead of winning the right to make a single block, miners win the right to make a ton of blocks, and during that time we say they’re under “tenure”. Every single Stacks block produced in a tenure requires at least 70% of Stackers to approve (sign) it for it to be included in the Stacks blockchain. The Stackers are watching the Bitcoin blockchain and will only sign blocks from the miner that won the latest sortition.

Now, let’s imagine that Bitcoin reorganizes itself and the Stackers were watching a Bitcoin fork that is now sub-optimal. The Stackers would essentially go back in time to the latest common sortition between the fork that they were watching and the new best Bitcoin fork and start signing the blocks within the tenures from there. Note that 70% of the Stackers will be doing the same thing all at once, and the moment 70% agree to start signing from the latest tenure on the new Bitcoin fork there’s a new singularly optimal Stacks blockchain.

So what happens to the transactions that were confirmed on the tenure that got reorganized? Nothing. Still in the mempool as if the reorganized tenure didn’t happen. For anything within the Stacks blockchain everything is fine.

This is 1:1 with a Bitcoin fork reorganizing a Bitcoin transaction. You shouldn’t consider a transaction on Bitcoin final if it’s near the chain tip, and you shouldn’t consider a Stacks transaction final if it’s near the tenure tip.

<details>

<summary>Replaying Transactions</summary>

Since 70% of the signers have to sign any Stacks block included in the chain at least 70% of signers know the state of the chain before and after a Bitcoin fork causes a Stacks reorg.

There’s a catch to this that makes enforcing it difficult: if a transaction were dependent on something on the Bitcoin blockchain that also got reorganized (a peg-in, for example), that transaction would now be invalid. Taint analysis is when you attempt to answer the questions “which transaction interacted with the now-orphaned Bitcoin blockchain in a way that makes them invalid (tainted) in the new chain” and then also “which transactions interacted with the now invalid (tainted) transaction such that they are now also invalid”. There’s a cascading effect, but enforcing any kind of replay requires that the Stackers and the Miners can identify which transactions can get replayed at all.

Taint analysis, and subsequently replay enforcement, can be added in the future.

For the first release, Nakamoto explicitly ties the Stacks blockchain to the Bitcoin blockchain such that there’s only one optimal Stacks fork tied to Bitcoin at any given point. This is completely 1:1 with the Bitcoin Blockchain behavior, but on the tenure scale.

</details>


# Financial Incentive And Security Budget

<div data-with-frame="true"><figure><img src="/files/3xMQd1uI5VSmCOCyYALE" alt=""><figcaption></figcaption></figure></div>

In order to reorg the Stacks chain, someone must take control of at least 70% of the STX that are currently Stacked and conduct a 51% attack on Bitcoin itself.

In addition to this, because of how Stacks achieves Bitcoin finality by not allowing forks, Stacks security budget reaches 51% of Bitcoin's mining power because in order to reverse the chain state you would need to reverse the Bitcoin chain state as well.

Stackers have the new-found power to sign blocks in order to append them to the Stacks chain. However, some of them could refuse to sign, and ensure that no block ever reaches the 70% signature threshold. While this can happen by accident, this is not economically rational behavior -- if they stall the chain for too long, their STX loses their value, and furthermore, they cannot re-stack or liquidate their STX or activate PoX to earn BTC. Also, miners will stop mining if no blocks are getting confirmed, which eliminates their ongoing PoX payouts.

The technical details of how this all works are discussed in the [Block Production](/learn/block-production) section.

***

### Additional Resources

* \[[Stacks YT](https://www.youtube.com/watch?v=HUyFnGnA4FU)] Long Term Security Budget & Miner Incentives for Bitcoin


# What was the Nakamoto Upgrade?

The Nakamoto Release was a hard fork, in Q4 of 2024, on the Stacks network designed to bring several benefits, chief among them are increased transaction throughput and 100% Bitcoin finality.

With Nakamoto, Stacks block production would no longer be tied to miner elections. Instead, miners produce blocks at a fixed cadence, and the set of PoX Stackers rely on the miner elections to determine when the current miner should stop producing blocks and a new miner should start. This blockchain will only fork if 70% of Stackers approve the fork, and chain reorganization will be as difficult as reorganizing Bitcoin.

The Nakamoto release brought many new capabilities and improvements to the Stacks blockchain by focusing on a set of core advancements: improving transaction speed, enhancing finality guarantees for transactions, mitigating Bitcoin miner MEV (miner extractable value) opportunities that affect PoX, and boosting robustness against chain reorganizations.

### Previous Stacks Block Production Design

The Stacks blockchain today produces blocks in accordance with the algorithms described in [SIP-001](https://github.com/stacksgov/sips/blob/main/sips/sip-001/sip-001-burn-election.md) and [SIP-007](https://github.com/stacksgov/sips/blob/main/sips/sip-007/sip-007-stacking-consensus.md), and [SIP-015](https://github.com/stacksgov/sips/blob/main/sips/sip-015/sip-015-network-upgrade.md). Miners compete to append a block to the blockchain through the miner selection process facilitated by a VRF backed sortition process. Miners submit a block-commit transaction to Bitcoin, which commits to the hash of the block the miner intends to append. The sortition process selects at most one block-commit in the subsequent Bitcoin block, which entitles the submitter to propagate their block and earn a block reward.

### The Problems

Over the last three years the Stacks community has identified several issues with the current system design:

1. **Slow Bitcoin blocks, Stacks forks, and missed sortitions are disruptive to on-chain applications.** The act of waiting to produce a new block until after a sortition elects a valid miner ties best-case Stacks block production rate to the block production rate of Bitcoin, leading to very high transaction confirmation latency.
2. **Microblocks are not effective in speeding up transaction confirmation time.** While microblocks have the potential to mitigate missed sortitions and improve transaction inclusion time, they do not work in practice because the protocol cannot ensure that microblocks will be confirmed until the next sortition happens. Additionally, new miners will often orphan recently-confirmed transactions from the old miner that were included in microblocks because there is no consensus-critical procedure that forces the next miner to build upon the latest microblock.
3. **Stacks forks are not tied to Bitcoin forks, allowing cheap reorgs** The cost to reorg the last N blocks in the Stacks blockchain is the cost to produce the next N + 1 Stacks blocks (i.e. by spending BTC), which is cheap compared to the cost of reorging the Bitcoin. This SIP describes an opportunity to tie the canonical Stacks fork to the Bitcoin blockchain such that the act of reorging Stacks chain history requires the Stacks miner to produce the fork with 70% of stacker sign-off.
4. **Stacks forks arise due to poorly-connected miners.** If a set of miners has a hard time learning the canonical Stacks chain tip when they submit block-commits, then they will collectively orphan other miners who are better-connected. This has happened in practice.
5. **Some Bitcoin miners run their own Stacks miners and deliberately exclude other Stacks miners' `block-commits` from their Bitcoin blocks.** Once the STX block reward became sufficiently large this allowed them to pay a trivial PoX payout while guaranteeing that they would win the cryptographic sortition in their Bitcoin block. This was anticipated in the original design but the regularity with which it happens today is greater than the original protocol accounted for, and thus must be addressed now.

### The Solutions

To address these shortcomings, Nakamoto applies three fundamental changes to the way Stacks works.

* **Fast blocks:** The time taken for a user-submitted transaction to be mined within a block (and thus confirmed) will now take on the order of seconds, instead of tens of minutes. This is achieved by separating block production from cryptographic sortitions -- a winning miner may produce many blocks between two subsequent sortitions.
* **Bitcoin finality:** Once a transaction is confirmed, reversing it is at least as hard as reversing a Bitcoin transaction. The Stacks blockchain no longer forks on its own.
* **Bitcoin Miner MEV Resistance:** This proposal alters the sortition algorithm to ensure that Bitcoin miners do not have an advantage as Stacks miners. They must spend competitive amounts of Bitcoin currency to have a chance of earning STX.

### Nakamoto Design

To achieve these goals Nakamoto introduced the following changes to the Stacks protocol:

1. **Decouple Stacks tenure changes from Bitcoin block arrivals.** In both today's system and Nakamoto, miners take turns appending blocks to the Stacks blockchain -- the next miner is selected by cryptographic sortition, and the miner has the duration of the Bitcoin block (its tenure) to announce a new block state. Nakamoto allows a miner to produce many Stacks blocks per Bitcoin block instead of one, and requiring the next miner to confirm all of them. There are no more microblocks or Bitcoin-anchored blocks; instead, there are only Nakamoto Stacks blocks. This will achieve fast block times.
2. **Require stackers to collaborate before the next block can be produced.** Stackers will need to collectively validate, store, sign, and propagate each Nakamoto Stacks block the miner produces before the next block can be produced. Stackers must do this in order to earn their PoX payouts and unlock their STX (i.e. PoX is now treated as compensation from the miner for playing this essential role). In Nakamoto, a sortition only selects a new miner; it does not give the miner the power to unilaterally orphan confirmed transactions as it does today. This will ensure that miners do not produce forks and are able to confirm all prior Stacks blocks prior to selection.
3. **Use stackers to police miner behavior.** A sortition causes the Stackers to carry out a tenure change by (a) agreeing on a "last-signed" block from the current miner, and (b) agreeing to only sign blocks from the new miner which descend from this last-signed block. Thus, Stackers police miner behavior -- Stackers prevent miners from mining forks during their tenure, and ensure that they begin their tenures by building atop the canonical chain tip. The new miner cannot orphan recently-confirmed transactions from the old miner because the signers who approved the tenure change are necessarily aware of all Stacks blocks that came before it. This **further prevents miners from forking the Stacks blockchain.**
4. **Require Stacks miners to commit the indexed block hash of the first block produced by the last Stacks miner in their block-commit transactions on the Bitcoin blockchain.** This is the SHA512/256 hash of both the consensus hash of all previously-accepted Bitcoin transactions that Stacks recognizes, as well as the hash of the block itself (a block-commit today only contains the hash of the Stacks block). This will anchor the Stacks chain history to the Bitcoin up to the start of the previous miner's tenure, as well as all causally-dependent Bitcoin state that Stacks has processed. This **ensures Bitcoin finality and resolves miner connectivity issues** by putting fork prevention on Stackers.
5. **Adopt a Bitcoin MEV solution which punishes block-commit censorship.** The probability a stacks miner wins a sortition should be altered such that omitting block commits of honest Stacks miners is not profitable to Bitcoin miners. The mechanics of this are outlined below.

***

{% embed url="<https://youtu.be/zIXY_49xbIY?si=jyBrtZpZd9tC_kUE>" %}

***

### Additional Resources

* \[[Hiro Blog](https://www.hiro.so/blog/understanding-nakamotos-fast-blocks-on-stacks)] Understanding Nakamoto’s Fast Blocks on Stacks
* \[[Stacks YT](https://youtu.be/Idjctsghb4s?si=Qxbzt1Md_7cPzFMV)] What’s Next for Stacks After Nakamoto Upgrade


# Transactions

Transactions are a key component of the Stacks network and are the primary way users will interact with it. In this section, we'll cover how transactions work and give an introduction to post conditions, an additional security feature of Stacks that allows client-side developers to enforce certain conditions to protect users from interacting with malicious contracts.


# How Transactions Work

<div data-with-frame="true"><figure><img src="/files/y3ebVcdJmCIf7nwGSryL" alt=""><figcaption></figcaption></figure></div>

### Introduction

Transactions are the fundamental unit of execution in Stacks. Each transaction is originated from a Stacks account, and is retained in the Stacks network history for eternity. This guide helps you understand Stacks transactions.

### Lifecycle

Transactions go through phases before being finally confirmed.

<div data-with-frame="true"><figure><img src="/files/OnGtKNwGFGZb1W3wFI9U" alt=""><figcaption></figcaption></figure></div>

{% stepper %}
{% step %}
**Generate**

Transactions are assembled according to the encoding specification.
{% endstep %}

{% step %}
**Validate and sign**

Transactions are validated to confirm they are well-formed. Required signatures are filled in.
{% endstep %}

{% step %}
**Broadcast**

Transactions are sent to a node.
{% endstep %}

{% step %}
**Register**

A miner receives transactions, verifies, and adds them to the mempool, a holding area for all the pending transactions.
{% endstep %}

{% step %}
**Process**

Miners review the mempool and select transactions for the next block to be mined. Depending on the transaction type, different actions can happen during this step. For example, post-conditions could be verified for a token transfer, smart-contract defined tokens could be minted, or an attempt to call an existing smart contract method could be made.
{% endstep %}

{% step %}
**Confirm**

Miners successfully propose blocks with a set of transactions. The transactions inside are successfully propagated to the network when the stackers approve them.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
A transaction can have one of three states once it is registered: `pending`, `success`, or `failed`.
{% endhint %}

### Types

Stacks supports a set of different transaction types:

| **Type**                  | **Value**                 | **Description**                                                                                                                                                                                                                                                             |
| ------------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Tenure change             | `TenureChange`            | A tenure change is an event in the existing Stacks blockchain when one miner assumes responsibility for creating new stacks blocks from another miner. A change in tenure occurs when a Stacks block is discovered from a cryptographic sortition. Carried out by stackers. |
| Tenure change block found | `TenureChange-BlockFound` | A `TenureChange-BlockFound` transaction is induced by a winning sortition. This causes the new miner to start producing blocks, and stops the current miner from producing more blocks.                                                                                     |
| Tenure change extend      | `TenureChange-Extend`     | A `TenureChange-Extend`, which is induced by Stackers, resets the current tenure's ongoing execution budget, thereby allowing the miner to continue producing blocks.                                                                                                       |
| Token transfer            | `token_transfer`          | Asset transfer from a sender to a recipient                                                                                                                                                                                                                                 |
| Contract deploy           | `smart_contract`          | Contract instantiation                                                                                                                                                                                                                                                      |
| Contract call             | `contract_call`           | Contract call for a public, non read-only function                                                                                                                                                                                                                          |

## Fees

Fees are used to incentivize miners to confirm transactions on the Stacks blockchain. The fee is calculated based on the estimate fee rate and the size of the raw transaction in bytes. The fee rate is a market determined variable. For the testnet, it is set to 1 micro-STX.

## Nonces

Every account carries a [nonce property](https://en.wikipedia.org/wiki/Cryptographic_nonce) that indicates the number of transactions processed for the given account. Nonces are one-time codes, starting at `0` for new accounts, and incremented by 1 on every transaction.

Nonces are added to all transactions and help identify them in order to ensure transactions are processed in order and to avoid duplicated processing.

{% hint style="info" %}
The consensus mechanism also ensures that transactions aren't "replayed" in two ways. First, nodes query its unspent transaction outputs (UTXOs) in order to satisfy their spending conditions in a new transaction. Second, messages sent between nodes review sequence numbers.
{% endhint %}

When a new token transfer transaction is constructed, the most recent nonce of the account needs to be fetched and set.

### How nonce gaps are detected and resolved

Stacks transactions must be executed **strictly in nonce order**. When a transaction is submitted with a nonce higher than expected, the network does **not** reject it outright—instead, it tracks the gap and waits for the missing nonces to arrive.

Below is a conceptual walkthrough, with visual responses from the API, of how the system behaves when nonces are submitted out of order.

{% stepper %}
{% step %}
**Initial state (no pending transactions)**

```json
{
  last_mempool_tx_nonce: null,
  last_executed_tx_nonce: 241,
  possible_next_nonce: 242,
  detected_missing_nonces: [],
  detected_mempool_nonces: []
}
```

**Interpretation**

* All transactions up to nonce `241` have executed
* The network expects nonce `242` next
* No transactions are currently waiting in the mempool
* No nonce gaps exist
  {% endstep %}

{% step %}
**Submitting a future nonce (`245`)**

```json
{
  last_mempool_tx_nonce: 245,
  last_executed_tx_nonce: 241,
  possible_next_nonce: 246,
  detected_missing_nonces: [244, 243, 242],
  detected_mempool_nonces: []
}
```

**Interpretation**

* A transaction with nonce `245` is now in the mempool
* Nonces `242`, `243`, and `244` are missing
* Execution cannot proceed until those nonces are submitted
* `possible_next_nonce` reflects the highest observed nonce + 1
  {% endstep %}

{% step %}
**Submitting a partial gap (`243`)**

```json
{
  last_mempool_tx_nonce: 245,
  last_executed_tx_nonce: 241,
  possible_next_nonce: 246,
  detected_missing_nonces: [244, 242],
  detected_mempool_nonces: [243]
}
```

**Interpretation**

* Nonce `243` is now present in the mempool
* Nonces `242` and `244` are still missing
* Execution is still blocked
* The API distinguishes between:
  * `detected_mempool_nonces` → present but unexecuted
  * `detected_missing_nonces` → required but not yet seen
    {% endstep %}

{% step %}
**Filling more gaps (`244`)**

```json
{
  last_mempool_tx_nonce: 245,
  last_executed_tx_nonce: 241,
  possible_next_nonce: 246,
  detected_missing_nonces: [242],
  detected_mempool_nonces: [243, 244]
}
```

**Interpretation**

* Nonces `243` and `244` are both waiting in the mempool
* Nonce `242` is still missing
* Execution remains paused at `241`
  {% endstep %}

{% step %}
**All required nonces present (`242`)**

```json
{
  last_mempool_tx_nonce: 245,
  last_executed_tx_nonce: 241,
  possible_next_nonce: 246,
  detected_missing_nonces: [],
  detected_mempool_nonces: [242, 243, 244]
}
```

**Interpretation**

* All required nonces (`242–245`) are now available
* No gaps remain
* The network can execute transactions sequentially
  {% endstep %}

{% step %}
**After execution completes**

```json
{
  last_mempool_tx_nonce: null,
  last_executed_tx_nonce: 245,
  possible_next_nonce: 246,
  detected_missing_nonces: [],
  detected_mempool_nonces: []
}
```

**Interpretation**

* All pending transactions have executed
* The account nonce has advanced to `245`
* The next valid nonce is now `246`
* The mempool state is clean again
  {% endstep %}
  {% endstepper %}


# Post Conditions

<div data-with-frame="true"><figure><img src="https://2842511454-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2Fgit-blob-3716767855649150a8a31e6cedc4c9d4139a7500%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
**Builder Resources**

* For a deeper dive on post-conditions usage, [here](https://docs.stacks.co/post-conditions/overview).
* For post-conditions' technical specification outlined in SIP-005, [here](https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md#transaction-post-conditions).
* For Originator mode and the MAY SEND NFT condition outlined in SIP-040, [here](https://github.com/stacksgov/sips/blob/main/sips/sip-040/sip-040-post-conds.md).
* For the staking and PoX post-conditions outlined in SIP-045, [here](https://github.com/stacksgov/sips/blob/main/sips/sip-045/sip-045-pox-5-bitcoin-staking.md).
  {% endhint %}

#### **The Big Picture**

* Post-conditions are constraints *you attach to a transaction* that define exactly what assets (STX, SIP-010 tokens, NFTs) are allowed to move and how much. Starting with SIP-045, they also define what staking and PoX actions are allowed to occur.
* If the underlying smart contract execution would violate your declared limits, the entire transaction aborts.
* Even if a smart contract contains unexpected logic, it cannot move assets beyond what your post-conditions permit.
* Post-conditions are constructed on the client-side usually by the client-side developer. They are part of the signed transaction. Contracts cannot modify them.
* Wallets will parse the signed transaction and display the declared post-conditions to the user before broadcasting.

***

### What are post-conditions? <a href="#what-are-post-conditions" id="what-are-post-conditions"></a>

Post-conditions are assertions about an on-chain transaction that must be met; otherwise, the transaction will abort during execution. Post-conditions act as a safety net, allowing you to specify what state changes can occur in a transaction.

**At times, the client-side developer is not the same person who wrote the underlying smart contract and may not be deeply familiar with its internal logic, nested external contract calls, or edge cases.** This logic helps limit the amount of damage that can be done to a user and their assets, whether due to a bug or malicious behavior.

Post conditions are a set of conditions that must be met before a user's transaction will execute. The primary goal behind post conditions is to limit the amount of damage that can be done to a user's assets due to a bug, intentional or otherwise.

Post conditions are an additional safety feature built into the Stacks protocol itself that help to protect end users. Rather than being a feature of Clarity smart contracts, they are implemented on the client side and meant to be an additional failsafe against malicious contracts.

They are sent as part of the transaction when the user initiates it, meaning we need to implement post-conditions on the frontend. Whenever you are transferring an asset (fungible or non-fungible) from one address to another, you should take advantage of post conditions.

Post-conditions originally covered only asset transfers: STX, fungible tokens, and NFTs. Starting with Stacks epoch 4.0, [SIP-045](https://github.com/stacksgov/sips/blob/main/sips/sip-045/sip-045-pox-5-bitcoin-staking.md) extends them to staking. A staking post-condition constrains how much STX a principal locks (or modifies) when staking, and a PoX post-condition constrains whether a principal performs other PoX actions such as unstaking. This means a user can also be protected from a contract unexpectedly changing their staking position, not just from unexpected transfers.

***

> #### *Post-conditions act as a safety net, allowing you to specify what state changes can and should occur during the execution of a transaction.*


# Clarity

A smart contract language built to be readable and predictable.

<div data-with-frame="true"><figure><img src="/files/KuiwkH3keym751bfdWwf" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
Head to the [Clarity Crash Course](/get-started/clarity-crash-course) to build your first Clarity smart contract.
{% endhint %}

Clarity is a **decidable** smart contract language that optimizes for predictability and security, designed for the Stacks blockchain. It has been built from the ground up to make it easier for developers to write safe, secure smart contracts. Clarity has several unique features that make it an ideal choice for writing smart contracts.

The design decisions behind Clarity were based heavily on taking lessons learned in common Solidity exploits and creating a language that has been purpose-built for safety and security in mind.

### What makes Clarity different

The following section is an excerpt from the [Clarity book](https://book.clarity-lang.org/ch00-00-introduction.html):

The number of smart contract languages grows by the year. Choosing a first language can be challenging, especially for a beginner. The choice is largely dictated by the ecosystem you are interested in, although some languages are applicable to more than just one platform. Each language has its own upsides and downsides and it is out of the scope of this book to look at all of them. Instead, we will focus on what sets Clarity apart and why it is a prime choice if you require the utmost security and transparency.

One of the core precepts of Clarity is that it is secure by design. The design process was guided by examining common pitfalls, mistakes, and vulnerabilities in the field of smart contract engineering as a whole. There are countless real world examples of where developer failure led to the loss or theft of vast amounts of tokens. To name two big ones: an issue that has become known as the Parity bug led to the irreparable loss of millions of dollars worth of Ethereum. Second, the hacking of The DAO (a "Decentralized Autonomous Organization") caused financial damage so great that the Ethereum Foundation decided to issue a contentious hard fork that undid the theft. These and many other mistakes could have been prevented in the design of the language itself.

#### Clarity is interpreted, not compiled

Clarity code is interpreted and committed to the chain exactly as written. Solidity and other languages are compiled to byte-code before it is submitted to the chain. The danger of compiled smart contract languages is two-fold: first, a compiler adds a layer of complexity. A bug in the compiler may lead to different byte-code than was intended and thus carries the risk of introducing a vulnerability. Second, byte-code is not human-readable, which makes it very hard to verify what the smart contract is actually doing. Ask yourself, would you sign a contract you cannot read? If your answer is no, then why should it be any different for smart contracts? With Clarity, what you see is what you get.

#### Clarity is decidable

A decidable language has the property that from the code itself, you can know with certainty what the program will do. This avoids issues like the halting problem. With Clarity you know for sure that given any input, the program will halt in a finite number of steps. In simple terms: it is guaranteed that program execution will end. Decidability also allows for complete static analysis of the call graph so you get an accurate picture of the exact cost before execution. There is no way for a Clarity call to "run out of gas" in the middle of the call. We explore this idea more, along with a discussion on Turing completeness, in the security deep dive on decidability.

#### Clarity does not permit reentrancy

Reentrancy is a situation where one smart contract calls into another, which then calls back into the first contract—the call "re-enters" the same logic. It may allow an attacker to trigger multiple token withdrawals before the contract has had a chance to update its internal balance sheet. Clarity's design considers reentrancy an anti-feature and disallows it on the language level.

#### Clarity guards against overflow and underflows

Overflows and underflows happen when a calculation results in a number that is either too large or too small to be stored, respectively. These events throw smart contracts into disarray and may intentionally be triggered in poorly written contracts by attackers. Usually this leads to a situation where the contract is either frozen or drained of tokens. Overflows and underflows of any kind automatically cause a transaction to be aborted in Clarity.

#### Support for custom tokens is built-in

Issuance of custom fungible and non-fungible tokens is a popular use-case for smart contracts. Custom token features are built into the Clarity language. Developers do not need to worry about creating an internal balance sheet, managing supply, and emitting token events. Creating custom tokens is covered in depth in later chapters.

#### On Stacks, transactions are secured by post conditions

In order to further safeguard user tokens, post conditions can be attached to transactions to assert the chain state has changed in a certain way once the transaction has completed. For example, a user calling into a smart contract may attach a post condition that states that after the call completes, exactly 500 STX should have been transferred from one address to another. If the post condition check fails, then the entire transaction is reverted. Since custom token support is built right into Clarity, post conditions can also be used to guard any other token in the same way.

#### Returned responses cannot be left unchecked

Public contract calls must return a so-called response that indicates success or failure. Any contract that calls another contract is required to properly handle the response. Clarity contracts that fail to do so are invalid and cannot be deployed on the network. Other languages like Solidity permit the use of low level calls without requiring the return value to be checked. For example, a token transfer can fail silently if the developer forgets to check the result. In Clarity it is not possible to ignore errors, although that obviously does prevent buggy error handling on behalf of the developer. Responses and error handling are covered extensively in the chapters on functions and control flow.

#### Composition over inheritance

Clarity adopts a composition over inheritance. It means that Clarity smart contracts do not inherit from one another like you see in languages like Solidity. Developers instead define traits which are then implemented by different smart contracts. It allows contracts to conform to different interfaces with greater flexibility. There is no need to worry about complex class trees and contracts with implicit inherited behavior.

#### Access to the base chain: Bitcoin

Clarity smart contracts can read the state of the Bitcoin base chain. It means you can use Bitcoin transactions as a trigger in your smart contracts! Clarity also features a number of built-in functions to verify secp256k1 signatures and recover keys.


# Understanding Clarity's Decidability

### What does it mean for a language to be Non-Turing Complete or Decidable?

Non-Turing complete and decidable are two terms you will often hear about the security advantages of Clarity, but what do they mean?

While related, they are not quite interchangeable, since there are a few differences.

#### Non-Turing Complete

A system or language is non-Turing complete if it cannot simulate a Turing machine, which is an abstract model of computation. Non-Turing complete systems have limited computational power compared to Turing complete systems. A Turing-complete system or language can simulate any Turing machine. Examples of non-Turing complete systems include finite state machines and some domain-specific languages (like Clarity).

Non-Turing complete languages typically cannot express all possible algorithms. Specifically, some problems whose solutions require unbounded loops or recursion cannot be expressed using non-Turing complete languages. This last property is especially important in the context of Clarity, as it makes it so that features like unbounded loops and reentrancy are disallowed at a language level.

#### Decidable

A problem is decidable if there exists an algorithm that can always determine whether a given input has a particular property or not in a finite amount of time. In other words, a decidable problem can be solved by a Turing machine that is guaranteed to halt for all input instances. Decidability is a property of problems, whereas Turing completeness is a property of languages or computational systems.

The fact that Clarity is decidable means that developers (and tooling) can more easily reason about and predict with certainty the behavior of Clarity contracts, regardless of the input.

### Mindset of a Smart Contract Developer

Before we dive into specifics, let's first set the context and viewpoint we should hold as smart contract developers who want to write secure code.

As you explore further into the security properties of Solidity and Clarity, you'll see that there are always mitigation steps that *can* be taken by developers to help address some of these security issues.

The main issue, with this line of thinking, is it increases the odds of human error in smart contract security. If we can preserve functionality while mitigating the chance of human error as much as possible, we should do so.

### Should smart contracts be Turing complete?

We will discover new applications for smart contracts. These applications will go beyond current smart contracts, traditional contracts, and may even open new economic opportunities. Given these possibilities, how should we build our smart contracts? What characteristics should our smart contract languages have?

It is good practice to separate data from programs. Should smart contracts be data, or programs, or something in between? If smart contracts are data, then should the programs that execute them be Turing complete or perhaps less powerful? If smart contracts are programs, then what language should smart contracts be written in? What characteristics should this programming language have?

The Church–Turing thesis is the hypothesis that all formal notions of computation are captured by Turing machines or modern computers. A programming language is Turing complete if it captures all formal notions of computation. Many programming languages are Turing complete. For example, Python, C++, Rust, Java, Lisp, and Solidity are all Turing complete.

Consider a program and its input. In the worst case, determining this program’s output is impossible. Validating a program, on a particular input, is done by generating a proof-of-correctness.

Proofs-of-correctness are logical proofs that can be mechanically validated. Finding proofs-of-correctness for programs and their input is undecidable. Kurt Gödel showed there are undecidable logical statements.

This indicates all programs in Turing complete languages cannot be validated in the worst case. Thus, Turing complete smart contract languages must allow contracts that cannot be validated.

Alonzo Church and Alan Turing showed there are problems that are uncomputable. Uncomputable problems cannot be solved by any Turing machine. Hence, assuming the Church–Turing thesis, these uncomputable problems cannot be solved by any computer.

We'll explore this idea further later in this section.

Turing complete languages are very expressive. In fact, assuming the Church–Turing thesis, Turing complete languages are as expressive as possible in some sense.

Is there a trade-off? What types of problems can occur with uncomputable problems and programs whose validity may be undecidable?

As smart contracts subsume parts of contract law, consider the large body of laws and regulations for tax law.

For instance, US tax law and regulations take up several million words. International tax law and regulations pushes these numbers much higher.

Are these laws and regulations programs or are they data? If tax law were to be written in a Turing complete language, then the law may codify uncomputable problems. It is an accountant’s nightmare for their advice to be undecidable.

Clarity is non-Turing complete, yet very expressive. This makes it so that Clarity is decidable and cannot encode uncomputable problems. There are discussions and papers on smart contract languages such as Solidity that propose subsets of Solidity that are non-Turing complete. These subsets are decidable and cannot encode uncomputable problems. However, there is no consensus on which subsets to work with and they are not widely used.

### Advantages of Decidability in Smart Contracts

Why is decidability important in the context of smart contracts?

First, it is not possible for a Clarity call to run out of gas in the middle of a call. Because of its decidability, it is possible to get a complete static analysis of the call graph to get an accurate picture of the cost before execution.

Solidity allows for unbounded loops, recursion, and dynamic function calls, which makes it difficult to accurately predict the execution cost or gas usage beforehand. As a result, Solidity contracts may run out of gas during execution if the gas limit is not set appropriately or if the contract encounters a scenario with unexpectedly high computational requirements.

One practical example is the issue of a specific kind of DoS attack in Solidity, where the contract is rendered inoperable because of unbounded execution constraints. An example of this is the GovernMental attack, where a mapping that needed to be deleted for a payout became so large that working with it exceeded the block gas limit.

There are a few different properties of Clarity's language design that prevents such DoS attacks.

The reason that the analysis system can accurately estimate the execution cost is because certain functionality is intentionally limited in Clarity.

For example, there is no recursion in Clarity, so we can't infinitely call into a function over and over.

Data types in Clarity are also restricted. Any data types that don't require a hard length limit are not iterable.

Maps and tuples, for example, do not require you to enter a maximum length when defining them, but you also can't iterate over them.

Lists, on the other hand, which are iterable, do require the developer to define an upper limit when defining them. This is a large part of what allows an accurate static analysis of Clarity contracts.

So how would we implement a mapping of an undefined size in Clarity? We wouldn't, because it's an anti-pattern in smart contract design.

Instead, Clarity forces us to think of a better solution to our problem. For example, implementing a way for users to handle mapping/list element operations themselves, instead of mass operations handled at the contract level.

If you [analyze the GovernMental attack](https://hackernoon.com/smart-contract-attacks-part-2-ponzi-games-gone-wrong-d5a8b1a98dd8#h-attack-2-call-stack-attack), you'll see that it took advantage of multiple security issues, all of which are mitigated in Clarity. You'll also see that a fix was added to make it economically infeasible to carry out this type of attack again.

This brings up another crucial point when setting appropriate mental models for smart contracts and blockchain systems: complexity means more potential bugs, which means adding more complexity to address those bugs.

When this happens over and over again, we are trapping ourselves into creating an evermore complex system. Addressing these issues at the language level prevents this ever-growing complexity.

For a deep dive into how Clarity was designed, check out [SIP-002](https://github.com/stacksgov/sips/blob/main/sips/sip-002/sip-002-smart-contract-language.md).

{% hint style="info" %}
You can view some more common smart contract vulnerabilities and how they are mitigated in [this article](https://stacks.org/bringing-clarity-to-8-dangerous-smart-contract-vulnerabilities/).
{% endhint %}

This has second-order effects as well when we look at security testing and auditing. One of the common tools for testing smart contracts is formal verification, where we mathematically prove that certain properties of smart contracts will or will not remain true in all cases.

This can lead to the path explosion problem, where there are so many paths available that formal verification becomes incredibly difficult. This problem is mitigated in Clarity, since there is not chance of a program encountering an unbounded loop.

This leads us to a more general mental model for thinking about decidability as smart contracts continue to become a larger part of our economy. Remember that the goal with blockchain systems is to create an open, transparent, fair financial system.

This means that smart contracts will be responsible for managing large amounts of wealth for ever-growing amounts of people. As smart contracts encompass more financial structures, their complexity and usage will grow.

Complexity is the enemy of security. The more complex a system is, the more danger there is in creating uncomputable problems when there are no hard restrictions on the execution steps that can be taken.

This is deadly in financial infrastructure that is not only open and transparent, but immutable. Let's explore this idea of uncomputability a bit more.

### Intuition on Uncomputability

Intuitively, uncomputability is an algorithmic view of undecidability. Uncomputability has the same foundations as undecidability. Undecidable questions are framed as logic statements or statements about integers. Of course, programs are logic statements and may even be viewed as integers, though we view programs differently. We often view programs with additional details of memory models, implementation details, and execution semantics.

The [Halting problem](https://en.wikipedia.org/wiki/Halting_problem): As an example, given any program `P` and any finite input `I` for `P`, then the Halting Problem is the challenge of determining if `P` halts on input `I`.

Alonzo Church and Alan Turing showed the Halting Problem is unsolvable.

Christopher Strachey gave an intuitive proof-by-contradiction showing the Halting problem is uncomputable. This is set up by supposing there is a program `H` that can solve the Halting problem for any program `P`. `H(P)` returns true if `P` halts and false otherwise. Then build a program `P` that does not halt when `H(P)` is true, giving a contradiction. Similarly, this program `P` halts when `H(P)` is false, also a contradiction.

Uncomputable problems are problems that cannot be solved by an algorithm or a computer, no matter how much time or resources are provided. These problems exist in various forms, and one such example is the Post correspondence problem, which was proposed by Emil Post.

The Post correspondence problem can be described using pairs of strings and an integer. Imagine you have n pairs of strings, called P. These strings are made up of characters from a character set, such as UTF-8 or any other alphabet with at least two symbols. The pairs of strings look like this:

```
P = { (x1, y1), (x2, y2), … , (xn, yn) }
```

Now, you also have an integer m that is greater than 0. The Post correspondence problem asks whether there is a way to create a list of indices (i1, i2, …, im) using the given pairs of strings. You can repeat these indices if needed, with one condition: when you combine the x strings from the pairs using the indices, the resulting string must be equal to the combined y strings from the same pairs using the same indices. In other words:

```
x(i1) x(i2) … x(im) = y(i1) y(i2) … y(im)
```

When developers try to solve the Post correspondence problem, they often attempt to use indeterminate loops (loops without a fixed number of iterations) rather than recursion. This is because the problem seems to require searching through different combinations of indices until a solution is found or it's proven that no solution exists.

In simple terms, the Post correspondence problem involves trying to find a sequence of indices that, when applied to the given pairs of strings, produces equal concatenated strings from both the x and y components. This problem is considered uncomputable because there is no general algorithm that can solve it for all possible input pairs of strings and integers.

It turns out, many questions about how programs behave are uncomputable. This has a number of consequences for smart contracts that are built in Turing complete languages, many of which we are not aware of yet but will surely become aware of as we encounter them in the future.

### Raymond Smullyan’s Intuition on Undecidability

This is a part of Raymond Smullyan’s approach to understanding undecidability in propositional logic. It uses meta-information to show something must be true, though it cannot be proved in propositional logic. This is based on a paradox.

In propositional logic, a logical statement is undecidable if we cannot prove it true or false. Given a propositional logic statement S, a proof is a sequence of formal logical deductions, starting from basic facts and ending by indicating if S is true or false.

Smullyan starts with an island of Knights and Knaves. Knights always tell the truth. Knaves always lie. We cannot distinguish islanders otherwise.

There is a great logician named Ray. Whatever Ray proves is true. This is just like a good theorem prover.

An islander Jack proclaims: “You cannot prove I am a Knight” to the logician Ray.

The next reasoning is based on meta-knowledge of this situation. This meta-knowledge shows that some problems are undecidable in propositional logic.

If Ray can prove Jack is a Knight, then Jack must be a Knave, since Jack must have lied. That is because Ray proved Jack is a Knight. Since Jack is a Knave, Ray’s proof contradicts the assumption that Ray only proves true things. So, this case cannot hold.

If Ray cannot prove Jack is a Knight, then Jack must be a Knight, since Jack stated the truth. But Ray cannot prove the fact that Jack is a Knight.

In the context of smart contracts and programming languages, Turing complete languages like Solidity come with the possibility of undecidable problems.

These undecidable problems are similar to the paradox presented in the Knights and Knaves story, where it's impossible to determine whether Jack is a Knight or a Knave based on the given information.

In the Knights and Knaves story, Ray is analogous to a theorem prover or a smart contract in a Turing complete language. Ray is faced with a statement that is undecidable within the constraints of the system (Knights and Knaves), which leads to a paradox.

Similarly, a Turing complete smart contract language might face undecidable problems that can't be resolved, leading to unexpected behavior, vulnerabilities, or resource consumption issues (like running out of gas in Ethereum).

On the other hand, non-Turing complete languages like Clarity are designed to avoid undecidable problems by limiting their expressiveness.

In the context of the Knights and Knaves story, a non-Turing complete language would simply not allow Jack to make a statement that could lead to a paradox. By disallowing certain features like unbounded loops and recursion, non-Turing complete languages can provide stronger guarantees about the behavior and resource usage of smart contracts.

This predictability is desirable in many cases, especially when dealing with high-value transactions or critical systems.

### Reference

The Mathematics of Various Entertaining Subjects: Research in Recreational Math Illustrated Edition, Jennifer Beineke (Editor), Jason Rosenhouse (Editor), Raymond M. Smullyan (Foreword), Princeton University Press, 2016.


# sBTC

Design of a Trustless Two-way Peg for Bitcoin

<div data-with-frame="true"><figure><img src="/files/4ZuYxVfbZUuMBiC1S3mF" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
For builders and developers, head to the [sBTC guides](/more-guides/sbtc) under the Build section to start integrating sBTC into your Clarity smart contracts and front-end application.
{% endhint %}

## Introduction

sBTC is a SIP-010 token on the Stacks blockchain that represents Bitcoin (BTC) in a 1:1 ratio. It enables Bitcoin holders to participate in DeFi applications and other smart contract functionalities while maintaining a peg to the underlying Bitcoin.

## Purpose

The primary purpose of sBTC is to bridge Bitcoin to DeFi via the Stacks blockchain, providing Bitcoin holders with access to the rich functionality of smart contracts without sacrificing the security and value of their BTC holdings.

> *Unlocking Bitcoin to be a fully programmable, productive asset would allow Bitcoin to be the*\
> \&#xNAN;*backbone of DeFi and a more secure web3. The ability to move Bitcoin assets in and out of*\
> \&#xNAN;*smart contracts freely and for these contracts to trustlessly write to the Bitcoin blockchain can*\
> \&#xNAN;*unlock hundreds of billions of dollars of passive BTC for web3.*\
> \
> \- sBTC: Design of a Trustless Two-way Peg for Bitcoin

## Key Benefits

1. **Bitcoin Compatibility**: Allows Bitcoin holders to participate in the Stacks ecosystem without selling their BTC.
2. **Quick Conversions**: Facilitates rapid movement between BTC and sBTC (within 3 Bitcoin blocks for deposit, 6 for withdrawal).
3. **Decentralized Management**: Initially utilizes a set of 15 community-chosen signers for maintaining the peg wallet.
4. **Community Governance**: Involves the community in key decisions, such as selecting the initial signing set.

## Key Concepts

Understanding sBTC requires familiarity with several key concepts:

<details>

<summary><strong>sBTC</strong></summary>

sBTC is a [SIP-010](https://github.com/stacksgov/sips/blob/main/sips/sip-010/sip-010-fungible-token-standard.md) token on the Stacks Blockchain that can be converted back to BTC on the Bitcoin Blockchain. The key property of sBTC is its 1:1 peg to Bitcoin, meaning 1 sBTC is always equivalent to 1 BTC.

</details>

<details>

<summary><strong>sBTC UTXO</strong></summary>

The sBTC UTXO is the single unspent transaction output (UTXO) on the Bitcoin blockchain that holds the entire BTC balance pegged into sBTC. This UTXO is managed and maintained by the set of sBTC Signers.

This UTXO resides in a secure multi-signature taproot address controlled by the sBTC Signers:\
[bc1pgg0us9y5skfpatq0nhxt7khhk8qxv0zgle36r6yxnql6dvyaafqsahn043](https://mempool.space/address/bc1pgg0us9y5skfpatq0nhxt7khhk8qxv0zgle36r6yxnql6dvyaafqsahn043)

</details>

<details>

<summary><strong>sBTC Signer</strong></summary>

In sBTC, the sBTC Signer is a signer entity separate from the Stacks Nakamoto signer. sBTC signer responsibilities include:

* Signing sBTC operations
* Communicating with the sBTC contracts on the Stacks chain
* Managing the sBTC UTXO

</details>

<details>

<summary><strong>sBTC Signer Set</strong></summary>

The sBTC Signer Set is the group of all sBTC signers. This set has full democratic access to the sBTC UTXO and is responsible for maintaining the security of the peg wallet. The signers also have the ability to rotate their private keys for enhanced security.

For more info on who the sBTC Signers are, check out this section on the Bitcoin L2 Labs website [here](https://bitcoinl2labs.com/sbtc-rollout#sbtc-signers).

</details>

<details>

<summary><strong>Emily API</strong></summary>

Emily is an API that helps facilitate and supervise the sBTC Bridge in addition to serving as a programmatic liaison between sBTC users and signers.

</details>

<details>

<summary><strong>SIP-010 Token</strong></summary>

sBTC adheres to the [SIP-010](https://github.com/stacksgov/sips/blob/main/sips/sip-010/sip-010-fungible-token-standard.md) standard for fungible tokens on the Stacks blockchain. This ensures compatibility with wallets and applications that support the SIP-010 standard.

</details>

Understanding these concepts is crucial for grasping the overall architecture and functionality of sBTC. In the following sections, we'll explore how these concepts come together to create sBTC.

***

{% embed url="<https://www.youtube.com/watch?v=phbb8k9077I>" %}

***

#### Additional Resources

* \[[sBTC Whitepaper](https://stacks-network.github.io/stacks/sbtc.pdf)] The official sBTC whitepaper
* \[[Stacks Foundation](https://stacks.org/sbtc-on-mainnet)] Official sBTC launch announcement (December 2024)
* \[[Bitcoin Writes](https://www.bitcoinwrites.com/)] Weekly sBTC Updates (last update: August 2024)
* \[[Hiro Blog](https://www.hiro.so/blog/who-are-the-sbtc-signers-breaking-down-sip-028)] Who Are the sBTC Signers: Breaking Down SIP-028


# Core Features of sBTC

sBTC offers several core features that make it a powerful trust-minimized Bitcoin bridge between Stacks and Bitcoin:

{% stepper %}
{% step %}
**1:1 Bitcoin Backing**

Each sBTC token is backed by an equivalent amount of Bitcoin in the peg wallet. This ensures that sBTC maintains a stable value relative to BTC.
{% endstep %}

{% step %}
**Decentralized Management**

The sBTC peg wallet is maintained and managed by a set of sBTC signers. This decentralized approach enhances security and reduces single points of failure.
{% endstep %}

{% step %}
**Quick Conversions**

sBTC facilitates rapid movement between BTC and sBTC:

* BTC to sBTC conversion can be completed within 3 Bitcoin blocks
* sBTC to BTC conversion can be completed within 6 Bitcoin blocks
  {% endstep %}

{% step %}
**SIP-010 Compatibility**

sBTC adheres to the SIP-010 fungible token standard on the Stacks blockchain. This ensures wide compatibility with Stacks wallets and applications.
{% endstep %}

{% step %}
**Community Governance**

The initial sBTC signing set is determined by a community vote, weighted by STX holdings. This approach ensures that the community has a say in the management of the sBTC system.
{% endstep %}

{% step %}
**Signer Key Rotation**

sBTC signers have the ability to rotate their private keys, enhancing long-term security of the system.
{% endstep %}

{% step %}
**Transaction Fee Sponsorship**

sBTC transactions on Stacks can be sponsored, allowing users to pay transaction fees in sBTC instead of STX.
{% endstep %}
{% endstepper %}


# How sBTC Moves

This section covers the main operations in the sBTC system. These operations form the core functionality of sBTC, allowing users to permissionlessly move value between the Bitcoin and Stacks ecosystems.

{% stepper %}
{% step %}
**Deposit**

Converting BTC to sBTC.

* **Increased Utility**: Users can leverage their Bitcoin on the Stacks network by converting BTC to sBTC, providing access to smart contracts and decentralized applications (dApps) that are not natively possible on the Bitcoin network.
* **DeFi Opportunities**: By utilizing sBTC, users can participate in decentralized finance (DeFi) activities such as lending, borrowing, and earning yield on their assets.
* **Cost Efficiency**: Operating on the Stacks network might offer lower transaction fees compared to the Bitcoin network, making it cost-effective for conducting transactions and executing smart contracts.
* **Interoperability**: sBTC allows users to enjoy the benefits of blockchain interoperability, moving their value seamlessly between the Bitcoin and Stacks ecosystems.
* **Network Security**: Stacks enhance security by building on Bitcoin's robustness, providing an added layer of trust and reliability when using sBTC.
  {% endstep %}

{% step %}
**Withdrawal**

Converting sBTC back to BTC.

* **Liquidity Needs**: Users might want to convert sBTC back to BTC to access the deep liquidity available on the Bitcoin network, facilitating easier and potentially faster transactions.
* **Off-Ramping**: Converting sBTC to BTC can allow users to withdraw their funds from the cryptocurrency ecosystem into fiat currency through exchanges that primarily support Bitcoin.
* **Security Preferences**: Some users might prefer holding their assets directly on the Bitcoin network due to its reputation for security and decentralization.
* **Network Preference**: Individuals may choose to operate exclusively within the Bitcoin network for its simplicity and widespread acceptance as a method of payment.
  {% endstep %}
  {% endstepper %}


# Pegging in sBTC

Converting BTC to sBTC.

The deposit operation enables users to mint sBTC, anchored to the BTC they have placed in the threshold wallet on the Bitcoin chain. This process can be completed within a single Bitcoin block, streamlining the user experience.

## Process Overview

<div data-with-frame="true"><img src="/files/uomdEwF71vFusniO2ft5" alt="deposit diagram"></div>

The deposit process begins when a user initiates a specific Bitcoin transaction that has two outputs. The depositor (usually through the application they are using to deposit) then initiates an API call referencing that Bitcoin transaction. This call triggers the Emily API, which relays deposit information to the sBTC Signers. These signers verify and process the deposit. Once verified, an equivalent amount of sBTC is minted on the Stacks blockchain.

{% stepper %}
{% step %}
**Script output**

A script that lets the signers spend the funds.
{% endstep %}

{% step %}
**Time-locked output**

A time lock that allows the depositor to reclaim the funds if necessary.
{% endstep %}
{% endstepper %}

For more information on deposit and withdrawal confirmation times and why deposits can be so fast, check out the [Deposit and Withdrawal Times](/learn/sbtc/sbtc-operations/deposit-vs-withdrawal-times) doc.

## Bitcoin Deposit Requirements

For a deposit to be considered valid, it must adhere to specific requirements:

* The deposit must be made to a taproot address.
* The output must be spendable by a consensus threshold of signers.
* The deposit must follow a format that prevents short-term clawbacks, ensuring the security and integrity of the system.

## User Experience

From a user's perspective, the deposit process is straightforward:

1. Initiate a BTC transaction to the specified address.
2. Wait for the transaction to be confirmed on the Bitcoin blockchain.
3. Receive the equivalent amount of sBTC in the Stacks wallet once the deposit is verified and processed.

To enhance the user experience, an sBTC bridge web application is currently in development which will provide an intuitive interface for users to track the status of their deposit operations, allowing users to stay informed throughout the process from initiation to completion.


# Pegging out sBTC

Converting sBTC back to BTC.

The sBTC withdrawal operation enables users to convert their sBTC back to BTC. This process involves burning sBTC on the Stacks blockchain and releasing an equivalent amount of BTC on the Bitcoin blockchain.

## Process Overview

<div data-with-frame="true"><figure><img src="/files/ezOoDzgsKvKwHRLBfjqp" alt=""><figcaption></figcaption></figure></div>

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeNx03RFtUIZTzKCbSnakHtStQl69RWZ7TWRYsW4KvIS2HS-93ghvu3s2U-g5PXbdeCvV_PZUZv1JL3CdPo3Zkm2ZHHmW8BDJIvMoZMFBf256K0fVH07TEazw7EPu7Wixex-inhIAwIzy4WCHwzoUbzpPph_?key=LMMtMf3zwOdkwel07ZrRiw" alt=""><figcaption></figcaption></figure>

{% stepper %}
{% step %}
**Initiate withdrawal**

A user initiates a Clarity contract call (via a Stacks wallet or dApp) specifying:

* the amount of sBTC to withdraw
* the destination Bitcoin address
  {% endstep %}

{% step %}
**Stacks transaction finality**

The Stacks transaction must reach finality. The protocol requires six Bitcoin block confirmations before proceeding to the next step.
{% endstep %}

{% step %}
**Signer verification and BTC release**

After confirmations, sBTC Signers verify the withdrawal request and create the withdrawal transaction on the Bitcoin network, releasing the equivalent BTC to the specified Bitcoin address.
{% endstep %}
{% endstepper %}

The withdrawal process requires six Bitcoin block confirmations to complete. After these confirmations, sBTC Signers create the withdrawal transaction on the Bitcoin network.

## Withdrawal Confirmation

The six-block confirmation requirement serves multiple purposes:

* Ensures finality of the Stacks transaction and prevents potential reversals or conflicts.
* Mitigates issues from potential Bitcoin forks by allowing time for network stability.
* Gives sBTC Signers sufficient time to verify and process the withdrawal request accurately.

For more information on deposit and withdrawal confirmation times and why deposits can be faster than withdrawals, see the [Deposit and Withdrawal Times](/learn/sbtc/sbtc-operations/deposit-vs-withdrawal-times) doc.

## Failure Cases

Some withdrawal failures can be identified and resolved before the six confirmations are complete. Other failures may only become apparent after the sBTC Bootstrap Signer attempts to create the withdrawal transaction on the Bitcoin network. These delays stem from the complexity of cross-chain operations and the need for thorough verification at each step.

<details>

<summary>More about failure detection timing</summary>

Because cross-chain operations involve verification on both Stacks and Bitcoin, certain issues (for example: insufficient signer consensus, malformed Bitcoin transaction construction, or Bitcoin network conditions) may only be detectable when the signer attempts to broadcast the Bitcoin transaction. This can cause failure detection to occur after confirmations on Stacks are already complete.

</details>

## Security Considerations

{% hint style="info" %}
The multi-block confirmation process is a critical security measure to help prevent double-spending attempts. Requiring multiple block confirmations ensures the withdrawal request is valid and final before processing on the Bitcoin network. Additionally, sBTC Signers perform verification of each withdrawal request prior to creating the Bitcoin transaction, providing an extra security layer.
{% endhint %}

## User Experience

From a user's perspective:

* Initiate a withdrawal through a Stacks wallet or dApp.
* Specify the sBTC amount and destination Bitcoin address.
* Wait for the required six Bitcoin blocks to confirm.
* Once confirmations complete and signers process the request, BTC is sent to the specified Bitcoin address.

The sBTC bridge web application offers a user-friendly interface that lets users track the status of their withdrawal operations in real time, providing updates at each stage so users can understand progress and estimate when they will receive BTC.


# Peg-in vs Peg-out Duration

Understanding why the time is takes to deposit BTC to sBTC is different than withdrawing sBTC back into BTC.

### Why are Deposits So Fast and Withdrawals So Slow?

sBTC allows users to use their BTC on the Stacks L2 by using a wrapped token called sBTC. Moving sBTC onto the Stacks L2 can take as little time as 1 Bitcoin block, but moving sBTC off the Stacks L2 into the native Bitcoin blockchain takes 6 Bitcoin blocks. Why is that?

> To understand why moving onto the Stacks layer can be so fast and yet moving off must be so slow, we need to first understand the consensus mechanism of the Stacks blockchain.

The Stacks blockchain uses a consensus mechanism called Proof of Transfer, or PoX, in order to mint new blocks. On each Bitcoin block, miners, on the Stacks blockchain, each sacrifice some amount of Bitcoin in a bid to win the right to make the next few Stacks blocks, where they retain the right to keep making Stacks blocks until the next Bitcoin block occurs and the latest bidding round elects a new Stacks miner.

#### Determining which Stacks blocks should be tied to which Bitcoin block

Signers (validators equivalents for the Stacks Blockchain) look at the Bitcoin blocks and approve new Stacks blocks based on which miner currently has the right to make Stacks blocks, and they only approve new blocks from the miner that won the most recent bid on the Bitcoin block within the fork that they collectively consider to be the “best”. The Stacks blockchain can only have new blocks added if the Signers agree that the miner who proposed it is the winner of the bid on the Bitcoin blockchain, and all the Signers are voting on which block should be added, effectively collectively deciding which Bitcoin fork is the best one.

**Here’s an important part**: if the Signers believe that there’s a new and better Bitcoin fork that differs from the one that the last several Stacks blocks had been mined on, they’ll then only approve new Stacks blocks that build off of existing Stacks blocks that are tied to that new Bitcoin fork. As in, every Stacks block that was built on Bitcoin blocks in the other Bitcoin fork that aren’t in this new canonical fork are considered invalid; thus the Stacks blockchain forks too.

> “The Stacks blockchain forks with the Bitcoin blockchain.”

Now that we understand this forking mechanism, let's take a look at why moving off the Stacks layer must be so slow.

#### **Why moving from sBTC to BTC takes more time**

sBTC exists on the Stacks layer as a token that smart contracts can interact with. To move sBTC over from the Stacks layer to the Bitcoin layer, the owner of the sBTC calls a smart contract to initiate what we call the “withdrawal” sequence. This lets the “sBTC Signers” (these are different from the earlier Signers mentioned) know that they need to create a transaction on the Bitcoin blockchain to distribute the BTC back to the user.

If the sBTC Signers create a Bitcoin transaction to enact the withdrawal, they can’t take it back, and it will be valid on every fork of the Bitcoin blockchain. So what happens if, say, the Bitcoin blockchain forks and the withdrawal on the Stacks layer got reorganized out? Then there’s an irretrievable withdrawal transaction on the Bitcoin blockchain giving precious BTC to a user who never withdrew their sBTC on the Stacks layer.

<details>

<summary>Can the Signers that maintain the original chain force miners to replay all previously confirmed transactions?</summary>

The Stacks blockchain is a true Layer 2 on top of Bitcoin, and you can write a smart contract to have different behavior based on observations of the Bitcoin blockchain underneath. You can, for example, write a Stacks contract that says “Pay to Jeff if the latest Bitcoin block hash ends in an even hex digit, and pay to Abigail if it’s an odd hex digit.” Now when there’s a reorg of the Bitcoin blockchain you can replay this transaction which originally paid to Jeff, but it now pays to Abigail, and what happens if this contract was giving out sBTC, and further what happens if Jeff then immediately executed a withdrawal?

</details>

So in the end, to process a withdrawal safely you need to be sufficiently sure it won’t get reorganized out. That means it can only be processed 6 Bitcoin blocks (the finality criteria the sBTC Signers are comfortable with) after the sBTC withdrawal transaction was made on the Stacks blockchain.

#### But then, why can deposits be done in one Bitcoin block at its fastest?

Remember how Stacks forks with Bitcoin? Let's say someone makes a deposit on the Bitcoin blockchain in an attempt to mint sBTC, and then lets say the sBTC Signers immediately mint sBTC. What happens if the Bitcoin chain forks causing the Stacks blockchain to fork? The mint gets reorganized out! Sure, the deposit is no longer on the Bitcoin blockchain, but it’s not on the Stacks blockchain either. If that deposit doesn’t ever arrive on the Bitcoin blockchain the sBTC signers will never mint sBTC, so there’s nothing to take back!

#### The Bitcoin chain gets the final say

So all in all, for movements of sBTC from the Stacks layer into the Bitcoin layer the protocol needs to wait for Bitcoin to be sufficiently final, but movements from the Bitcoin layer to the Stacks layer don’t need to wait for finality to mint because the Stacks layer will just reorganize itself if the Bitcoin layer reorganizes too.

But then conceptually remember, the mint call on the Stacks blockchain is just as final as the Bitcoin block that contains the deposit of BTC onto the Stacks layer. If you’re minting sBTC on the Stacks layer and you want to wait for it to be final you’ll need to wait a suitable number of Bitcoin blocks to consider it finally minted, but that’s up to you and not the sBTC Signers.


# Emily API

[Emily](https://github.com/stacks-network/sbtc/tree/main/emily) is an API that helps facilitate and supervise the sBTC Bridge, serving as a programmatic liaison between sBTC users and signers.

## Overview

The Emily API is designed to track deposits and withdrawals, providing information about the status of in-flight sBTC operations. It serves two primary user groups: sBTC users and sBTC app developers.

### Why Call it Emily?

The Emily API is given an indirect name because it handles more than just Deposits and Withdrawals; it can detect the health of the system and will likely be extended to handle more as user requirements mature. It was once called the “Revealer API”, which stopped making sense after a few design changes, and then “Deposit API” which also stopped making sense after a few changes. The most obvious choice “sBTC API” gives the wrong impression of what the API is responsible for as well, since the API itself isn’t managing the entirety of the protocol.

Large companies name their APIs after something loosely related but ambiguous enough that extensions of the API don’t make the original name of the API misleading. Following this, we chose “Emily” after Emily Warren Roebling who was the liaison between the builders and chief engineer, her husband, of the Brooklyn bridge. She was, in effect, the supervisor of the bridge’s construction; similarly, the Emily API supervises the sBTC bridge and liaises between the users of the protocol and the sBTC signers.

### Key Features

* Track Deposits: Monitor the process of converting BTC to sBTC.
* Track Withdrawals: Monitor the process of converting sBTC back to BTC.
* Provide Operation Status: Offer real-time status updates for ongoing sBTC operations.
* Retrieve Historical Data: Allow querying of past sBTC operations.

## Core Concepts

#### sBTC Operations

sBTC operations are the fundamental processes tracked by Emily:

* Deposits: Converting BTC to sBTC
* Withdrawals: Converting sBTC back to BTC

#### Operation States

Each sBTC operation goes through several states:

* PENDING: The operation has been initiated.
* ACCEPTED: The operation has been approved by the signers.
* CONFIRMED: The operation has been completed and confirmed on the blockchain.
* FAILED: The operation could not be completed.

### Where Emily is involved in the sBTC flows

In each of the deposit and withdrawal flows for sBTC, Emily plays a vital role. Here's where Emily sits in both the Deposit and Withdrawal flows.

#### **During the Deposit Flow**

1. User creates a deposit transaction on Bitcoin
2. User submits proof of deposit to the Deposit API
3. **Emily records the deposit as PENDING**
4. Signers validate and vote on the deposit
5. **If accepted, Emily updates status to ACCEPTED**
6. Signers process the Bitcoin transaction
7. Signers mint sBTC on Stacks
8. **Emily updates the deposit status to CONFIRMED**

#### **During the Withdrawal Flow**

1. User initiates withdrawal through the sBTC Clarity contract
2. **Emily records the withdrawal as PENDING**
3. Signers decide to accept or reject the withdrawal
4. **If accepted, Emily updates status to ACCEPTED**
5. Signers process the Bitcoin transaction
6. Signers burn sBTC on Stacks
7. **Emily updates the withdrawal status to CONFIRMED**


# The sBTC Signers

The Peg Wallet UTXO is a fundamental element of the sBTC system, serving as the Bitcoin backing for all sBTC tokens in circulation. The system uses a Single UTXO Model: the sBTC peg wallet is consistently represented as a single Unspent Transaction Output (UTXO) on the Bitcoin blockchain. This design offers simplicity and improved efficiency in managing the peg wallet.

{% hint style="info" %}
This UTXO resides in a secure multi-signature taproot address controlled by the sBTC Signers:\
[bc1pgg0us9y5skfpatq0nhxt7khhk8qxv0zgle36r6yxnql6dvyaafqsahn043](https://mempool.space/address/bc1pgg0us9y5skfpatq0nhxt7khhk8qxv0zgle36r6yxnql6dvyaafqsahn043)
{% endhint %}

## Overview

* Single UTXO Model: the peg wallet is always a single UTXO.
* Responsibility: UTXO management is performed by the Signer set.
* Purpose: simplify tracking and management, reduce Bitcoin transactions required for sBTC operations, and centralize funds in a single, well-secured output.

## How the Single UTXO is maintained

{% stepper %}
{% step %}
**Constructing the new UTXO**

A Signer coordinator constructs the UTXO by creating a new Bitcoin output that will represent the peg wallet going forward.
{% endstep %}

{% step %}
**Consolidating requests into a batch**

The Signer set collectively consolidates all deposit and withdrawal requests and creates optimized batches that can be processed within a single UTXO.
{% endstep %}

{% step %}
**Creating the new UTXO from the previous UTXO**

The new UTXO is created by:

* spending the amount from the previous UTXO,
* adding confirmed deposits,
* subtracting confirmed withdrawals.
  {% endstep %}

{% step %}
**Optimizing batching with approval sets**

When multiple sBTC operation requests are present, the Signer coordinator groups them by approval sets. If differing approval sets exist across active operations, the coordinator batches deposit UTXOs into groups with the maximum size per approval set to preserve the single UTXO invariant while maximizing batch efficiency.
{% endstep %}
{% endstepper %}

## Benefits

* Simplified tracking and management of peg funds.
* Fewer Bitcoin transactions for sBTC operations.
* Centralized funds in a single, well-secured output improves operational efficiency.

{% hint style="info" %}
The Single UTXO Model is designed to balance simplicity and operational efficiency for the sBTC peg wallet.
{% endhint %}

## Security considerations

* The single UTXO is managed by the sBTC Bootstrap Signer Set, which requires a threshold of signers to approve any spending (multi-signature).
* Regular audits and continuous monitoring are essential to ensure the UTXO accurately represents the total sBTC in circulation at all times.
* The UTXO, held by the Signers' bitcoin address, is only spendable via a [key path spend](https://github.com/stacks-sbtc/sbtc/blob/7d8b2cb508f7068373ced808f6e9d28c92387b28/signer/src/keys.rs#L439-L441). This means there are no hidden taproot script path spends.

{% hint style="warning" %}
Security is paramount: multi-signature approval, audits, and monitoring are core controls to protect the peg wallet.
{% endhint %}

***

### What's the difference between Stacks Signers vs sBTC Signers

| Role                       | Stacks Signer                      | sBTC Signer                                        |
| -------------------------- | ---------------------------------- | -------------------------------------------------- |
| **Primary Responsibility** | Signs and validates Stacks blocks  | Secures peg for sBTC (Bitcoin ↔ Stacks)            |
| **What They Sign**         | Stacks block data                  | Bitcoin transactions (peg-in / peg-out)            |
| **Layer**                  | Stacks consensus layer             | Bitcoin layer (via threshold signatures)           |
| **Purpose**                | Ensure canonical chain progression | Ensure safe custody + movement of BTC backing sBTC |
| **Trust Model**            | Part of Stacks consensus           | Threshold signer set managing BTC                  |
| **Failure Impact**         | Chain instability / fork risk      | Risk to BTC peg integrity                          |
| **Assets Involved**        | STX                                | BTC                                                |


# The Clarity Contracts Powering sBTC

The Clarity contracts responsible for sBTC's logic and interactions on Stacks.

<div data-with-frame="true"><figure><img src="/files/8zMcT9dUDzedZkv7TYUW" alt=""><figcaption></figcaption></figure></div>

### Deployed Mainnet Contracts

* [sbtc-token](https://explorer.hiro.so/txid/SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token?chain=mainnet)
* [sbtc-registry](https://explorer.hiro.so/txid/SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-registry?chain=mainnet)
* [sbtc-deposit](https://explorer.hiro.so/txid/SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-deposit?chain=mainnet)
* [sbtc-withdrawal](https://explorer.hiro.so/txid/SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-withdrawal?chain=mainnet)
* [sbtc-bootstrap-signers](https://explorer.hiro.so/txid/SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-bootstrap-signers?chain=mainnet)

### sBTC Clarity Contracts

At a high level, the sBTC Clarity contracts are responsible for the following:

#### sbtc-bootstrap signers

Core contract for meta signer functionality such as registration & the rotation process.

#### sbtc-deposit

Processing contract called by the signers to record a consumed Bitcoin transaction & mint some amount of sBTC to a principal contained in the payload.

#### sbtc-registry

State storage for maintaining upgradability across protocol.

#### sbtc-withdrawal

Interaction points for users and signers to update withdrawal request state.

<figure><img src="/files/uhD6c9NuSpX33Vd5dUVK" alt=""><figcaption></figcaption></figure>

### User Types

In addition to the contracts themselves, there are two main user types that will interact with these contracts.

#### Signer

A signer that is part of the current sBTC signer set. More information on signers and their role in sBTC can be found in the [Signer Process Walkthrough](/learn/sbtc/walkthroughs/signer-process-walkthrough).

#### Wallet

A participant in the Stacks/Bitcoin ecosystem that wants to deposit/withdraw/use sbtc.


# sBTC Signers

### Overview

The [sBTC Signers contract](https://github.com/stacks-network/sbtc/blob/main/contracts/contracts/sbtc-bootstrap-signers.clar) (`sbtc-bootstrap-signers.clar`) manages the signer set for the sBTC system. It handles rotation of signer keys and provides utilities for generating multisig addresses.

**Constants**

* `key-size`: The required length of public keys (33 bytes).

**Error Constants**

* `ERR_KEY_SIZE_PREFIX`: Prefix for key size errors in batch processing.
* `ERR_KEY_SIZE` (u200): Indicates that a provided key is not the correct length.
* `ERR_INVALID_CALLER` (u201): Signifies that the function caller is not the current signer principal.
* `ERR_SIGNATURE_THRESHOLD` (u202): Indicates an invalid signature threshold (must be >50% and ≤100% of total signer keys).

#### Public Functions

**`rotate-keys-wrapper`**

Rotates the keys of the signers. Called when the signer set is updated.

* Parameters:
  * `new-keys`: `(list 128 (buff 33))` - List of new signer public keys
  * `new-aggregate-pubkey`: `(buff 33)` - New aggregate public key
  * `new-signature-threshold`: `uint` - New signature threshold
* Returns: `(response (buff 33) uint)`

Function flow:

{% stepper %}
{% step %}
**Validate signature threshold**

Ensure the new signature threshold is valid (must be >50% and ≤100% of total signer keys).
{% endstep %}

{% step %}
**Verify caller**

Verify that the caller is the current signer principal.
{% endstep %}

{% step %}
**Validate keys**

Check the length of each new key and the aggregate public key (must be 33 bytes).
{% endstep %}

{% step %}
**Update registry**

Call the sBTC Registry contract to update the keys and address.
{% endstep %}
{% endstepper %}

#### Read-only Functions

**`pubkeys-to-spend-script`**

Generates the p2sh redeem script for a multisig.

* Parameters:
  * `pubkeys`: `(list 128 (buff 33))` - List of public keys
  * `m`: `uint` - Number of required signatures
* Returns: `(buff 1024)` - The p2sh redeem script

**`pubkeys-to-hash`**

Computes the hash160 of the p2sh redeem script.

* Parameters:
  * `pubkeys`: `(list 128 (buff 33))` - List of public keys
  * `m`: `uint` - Number of required signatures
* Returns: `(buff 20)` - The hash160 of the redeem script

**`pubkeys-to-principal`**

Generates a principal (Stacks address) from a set of pubkeys and an m-of-n threshold.

* Parameters:
  * `pubkeys`: `(list 128 (buff 33))` - List of public keys
  * `m`: `uint` - Number of required signatures
* Returns: `principal` - The generated Stacks address

**`pubkeys-to-bytes`**

Concatenates a list of pubkeys into a buffer with length prefixes.

* Parameters:
  * `pubkeys`: `(list 128 (buff 33))` - List of public keys
* Returns: `(buff 510)` - Concatenated pubkeys with length prefixes

**`concat-pubkeys-fold`**

Concatenates a pubkey buffer with a length prefix.

* Parameters:
  * `pubkey`: `(buff 33)` - A single public key
  * `iterator`: `(buff 510)` - Accumulator for concatenation
* Returns: `(buff 510)` - Updated concatenated buffer

**`bytes-len`**

Returns the length of a byte buffer as a single byte.

* Parameters:
  * `bytes`: `(buff 33)` - Input byte buffer
* Returns: `(buff 1)` - Length as a single byte

**`uint-to-byte`**

Converts a uint to a single byte.

* Parameters:
  * `n`: `uint` - Input number
* Returns: `(buff 1)` - Number as a single byte

#### Private Functions

**`signer-key-length-check`**

Checks that the length of each key is exactly 33 bytes.

* Parameters:
  * `current-key`: `(buff 33)` - Public key to check
  * `helper-response`: `(response uint uint)` - Accumulator for error handling
* Returns: `(response uint uint)` - Updated accumulator or error

#### Constants

**`BUFF_TO_BYTE`**

A constant list mapping uint values (0-255) to their corresponding byte representations.

Interactions with Other Contracts

* `.sbtc-registry`: Calls `get-current-signer-data` and `rotate-keys` to manage signer data.

Security Considerations

{% hint style="warning" %}

* Access Control: Only the current signer principal can call the key rotation function.
* Key Validation: Ensures all provided keys are the correct length.
* Signature Threshold: Enforces a minimum threshold of over 50% of signers and a maximum of 100%.
* Multisig Generation: Provides utilities for secure generation of multisig addresses.
  {% endhint %}


# sBTC Token

## Overview

The [sBTC Token contract](https://github.com/stacks-network/sbtc/blob/main/contracts/contracts/sbtc-token.clar) (`sbtc-token.clar`) implements the fungible token functionality for sBTC. It manages both unlocked and locked sBTC tokens and provides functions for minting, burning, transferring, and querying token information. sBTC is a SIP-010 standard fungible token.

## Constants

* `ERR_NOT_OWNER` (u4): Error when the sender tries to move a token they don't own.
* `ERR_NOT_AUTH` (u5): Error when the caller is not an authorized protocol caller.
* `token-decimals` (u8): The number of decimal places for the token.

## Fungible Tokens

* `sbtc-token`: The main sBTC fungible token.
* `sbtc-token-locked`: Represents locked sBTC tokens.

## Data Variables

* `token-name`: The name of the token (default: "sBTC").
* `token-symbol`: The symbol of the token (default: "sBTC").
* `token-uri`: An optional URI for token metadata.

## Protocol Functions

These functions can only be called by authorized protocol contracts:

### protocol-transfer

* Parameters: `amount: uint`, `sender: principal`, `recipient: principal`
* Returns: `(response bool uint)`

### protocol-lock

* Parameters: `amount: uint`, `owner: principal`
* Returns: `(response bool uint)`

### protocol-unlock

* Parameters: `amount: uint`, `owner: principal`
* Returns: `(response bool uint)`

### protocol-mint

* Parameters: `amount: uint`, `recipient: principal`
* Returns: `(response bool uint)`

### protocol-burn

* Parameters: `amount: uint`, `owner: principal`
* Returns: `(response bool uint)`

### protocol-burn-locked

* Parameters: `amount: uint`, `owner: principal`
* Returns: `(response bool uint)`

### protocol-set-name

* Parameters: `new-name: (string-ascii 32)`
* Returns: `(response bool uint)`

### protocol-set-symbol

* Parameters: `new-symbol: (string-ascii 10)`
* Returns: `(response bool uint)`

### protocol-set-token-uri

* Parameters: `new-uri: (optional (string-utf8 256))`
* Returns: `(response bool uint)`

### protocol-mint-many

* Parameters: `recipients: (list 200 {amount: uint, recipient: principal})`
* Returns: `(response (list 200 (response bool uint)) uint)`

## Public Functions (SIP-010 Trait)

### transfer

* Parameters: `amount: uint`, `sender: principal`, `recipient: principal`, `memo: (optional (buff 34))`
* Returns: `(response bool uint)`

### get-name

* Returns: `(response (string-ascii 32) uint)`

### get-symbol

* Returns: `(response (string-ascii 10) uint)`

### get-decimals

* Returns: `(response uint uint)`

### get-balance

Returns the total balance (locked + unlocked) for a principal.

* Parameters: `who: principal`
* Returns: `(response uint uint)`

### get-balance-available

Returns the available (unlocked) balance for a principal.

* Parameters: `who: principal`
* Returns: `(response uint uint)`

### get-balance-locked

Returns the locked balance for a principal.

* Parameters: `who: principal`
* Returns: `(response uint uint)`

### get-total-supply

* Returns: `(response uint uint)`

### get-token-uri

* Returns: `(response (optional (string-utf8 256)) uint)`

## Private Functions

### protocol-mint-many-iter

* Helper function for minting tokens to multiple recipients.
* Parameters: `item: {amount: uint, recipient: principal}`
* Returns: `(response bool uint)`

## Security Considerations

{% stepper %}
{% step %}
**Access Control**

Protocol functions can only be called by authorized contracts, enforced through the `sbtc-registry` contract.
{% endstep %}

{% step %}
**Ownership Verification**

The `transfer` function checks that the sender owns the tokens being transferred.
{% endstep %}

{% step %}
**Separate Token Tracking**

The contract maintains separate tracking for locked and unlocked tokens, ensuring proper accounting.
{% endstep %}
{% endstepper %}

## Interactions with Other Contracts

* `.sbtc-registry`: Used to validate protocol callers for privileged operations.


# sBTC Registry

## Overview

The [sBTC Registry contract](https://github.com/stacks-network/sbtc/blob/main/contracts/contracts/sbtc-registry.clar) (`sbtc-registry.clar`) serves as the central registry for the sBTC system. It manages withdrawal requests, completed deposits, and the current signer set. This contract is crucial for maintaining the state and coordinating operations within the sBTC ecosystem.

## Error Constants

* `ERR_UNAUTHORIZED` (u400): Indicates unauthorized access.
* `ERR_INVALID_REQUEST_ID` (u401): Signifies an invalid withdrawal request ID.
* `ERR_AGG_PUBKEY_REPLAY` (u402): Indicates an attempt to replay an aggregate public key.
* `ERR_MULTI_SIG_REPLAY` (u403): Signifies an attempt to replay a multi-signature address.

## State Variables

* `last-withdrawal-request-id`: Tracks the latest withdrawal request ID.
* `current-signature-threshold`: Stores the current threshold for required signatures.
* `current-signer-set`: Maintains a list of current signer public keys.
* `current-aggregate-pubkey`: Holds the current aggregate public key.
* `current-signer-principal`: Stores the current signer's principal address.

## Data Maps

### withdrawal-requests

Stores withdrawal request details indexed by request ID.

* Fields:
  * `amount`: Amount of sBTC being withdrawn (in sats)
  * `max-fee`: Maximum fee for the withdrawal
  * `sender`: Principal of the sender
  * `recipient`: BTC recipient address (version and hashbytes)
  * `block-height`: Burn block height where the request was created

### withdrawal-status

Tracks the status of withdrawal requests indexed by request ID.

* Value: `bool` (true if accepted, false if rejected, none if pending)

### completed-deposits

Records completed deposit transactions to prevent replay attacks.

* Key: `{txid: (buff 32), vout-index: uint}`
* Value: `{amount: uint, recipient: principal}`

### aggregate-pubkeys

Tracks used aggregate public keys to prevent replay attacks.

* Key: `(buff 33)` (aggregate public key)
* Value: `bool`

### multi-sig-address

Tracks used multi-signature addresses to prevent replay attacks.

* Key: `principal` (multi-sig address)
* Value: `bool`

### protocol-contracts

Stores authorized protocol contract addresses.

* Key: `principal` (contract address)
* Value: `bool`

## Read-only Functions

### get-withdrawal-request

Retrieves a withdrawal request by its ID.

* Parameters:
  * `id`: `uint`
* Returns: `(optional {amount: uint, max-fee: uint, sender: principal, recipient: {version: (buff 1), hashbytes: (buff 32)}, block-height: uint, status: (optional bool)})`

### get-completed-deposit

Fetches a completed deposit by transaction ID and output index.

* Parameters:
  * `txid`: `(buff 32)`
  * `vout-index`: `uint`
* Returns: `(optional {amount: uint, recipient: principal})`

### get-current-signer-data

Returns current signer set information.

* Returns: `{current-signer-set: (list 128 (buff 33)), current-aggregate-pubkey: (buff 33), current-signer-principal: principal, current-signature-threshold: uint}`

### get-current-aggregate-pubkey

Returns the current aggregate public key.

* Returns: `(buff 33)`

### get-current-signer-principal

Returns the current signer's principal.

* Returns: `principal`

### get-current-signer-set

Returns the current set of signer public keys.

* Returns: `(list 128 (buff 33))`

## Public Functions

### create-withdrawal-request

Creates a new withdrawal request. Only callable by protocol contracts.

* Parameters:
  * `amount`: `uint`
  * `max-fee`: `uint`
  * `sender`: `principal`
  * `recipient`: `{version: (buff 1), hashbytes: (buff 32)}`
  * `height`: `uint`
* Returns: `(response uint uint)`

### complete-withdrawal-accept

Marks a withdrawal request as accepted.

* Parameters:
  * `request-id`: `uint`
  * `bitcoin-txid`: `(buff 32)`
  * `output-index`: `uint`
  * `signer-bitmap`: `uint`
  * `fee`: `uint`
* Returns: `(response bool uint)`

### complete-withdrawal-reject

Marks a withdrawal request as rejected.

* Parameters:
  * `request-id`: `uint`
  * `signer-bitmap`: `uint`
* Returns: `(response bool uint)`

### complete-deposit

Records a completed deposit transaction.

* Parameters:
  * `txid`: `(buff 32)`
  * `vout-index`: `uint`
  * `amount`: `uint`
  * `recipient`: `principal`
* Returns: `(response bool uint)`

### rotate-keys

Updates the signer set, multi-sig principal, and aggregate public key.

* Parameters:
  * `new-keys`: `(list 128 (buff 33))`
  * `new-address`: `principal`
  * `new-aggregate-pubkey`: `(buff 33)`
  * `new-signature-threshold`: `uint`
* Returns: `(response (buff 33) uint)`

## Private Functions

### increment-last-withdrawal-request-id

Increments and returns the next withdrawal request ID.

* Returns: `uint`

### is-protocol-caller

Checks if the caller is an authorized protocol contract.

* Returns: `(response bool uint)`

### validate-protocol-caller

Validates if a given principal is an authorized protocol contract.

* Parameters:
  * `caller`: `principal`
* Returns: `(response bool uint)`

## Events

The contract emits events (via `print`) for important actions:

* Withdrawal request creation: "withdrawal-create"
* Withdrawal acceptance: "withdrawal-accept"
* Withdrawal rejection: "withdrawal-reject"
* Deposit completion: "completed-deposit"

{% hint style="info" %}
Events are emitted via `print` statements in the contract for the actions listed above.
{% endhint %}

## Security Considerations

{% stepper %}
{% step %}
**Access Control**

Only authorized protocol contracts can call certain functions.
{% endstep %}

{% step %}
**Replay Prevention**

The contract prevents replay attacks on deposits, aggregate public keys, and multi-signature addresses.
{% endstep %}

{% step %}
**State Management**

The contract carefully manages the state of withdrawals and the current signer set.
{% endstep %}
{% endstepper %}


# sBTC Withdrawal

## Overview

The [sBTC Withdrawal contract](https://github.com/stacks-network/sbtc/blob/main/contracts/contracts/sbtc-withdrawal.clar) (`sbtc-withdrawal.clar`) manages the withdrawal process for the sBTC system. It handles the initiation, acceptance, and rejection of withdrawal requests, ensuring proper validation and interaction with other sBTC contracts.

## Constants

### Error Codes

* `ERR_INVALID_ADDR_VERSION` (u500): Invalid address version.
* `ERR_INVALID_ADDR_HASHBYTES` (u501): Invalid address hashbytes.
* `ERR_DUST_LIMIT` (u502): Withdrawal amount below dust limit.
* `ERR_INVALID_REQUEST` (u503): Invalid withdrawal request ID.
* `ERR_INVALID_CALLER` (u504): Caller is not the current signer principal.
* `ERR_ALREADY_PROCESSED` (u505): Withdrawal request already processed.
* `ERR_FEE_TOO_HIGH` (u505): Paid fee higher than requested.
* `ERR_WITHDRAWAL_INDEX_PREFIX`: Prefix for withdrawal index errors.
* `ERR_WITHDRAWAL_INDEX` (u506): General withdrawal index error.

### Other Constants

* `MAX_ADDRESS_VERSION` (u6): Maximum value of an address version.
* `MAX_ADDRESS_VERSION_BUFF_20` (u4): Maximum version for 20-byte hashbytes.
* `MAX_ADDRESS_VERSION_BUFF_32` (u6): Maximum version for 32-byte hashbytes.
* `DUST_LIMIT` (u546): Minimum amount of sBTC for withdrawal.

## Public Functions

### initiate-withdrawal-request

Initiates a new withdrawal request.

* Parameters:
  * `amount`: `uint` - Amount of sBTC to withdraw
  * `recipient`: `{ version: (buff 1), hashbytes: (buff 32) }` - Bitcoin address details
  * `max-fee`: `uint` - Maximum fee for the withdrawal
* Returns: `(response uint uint)`

### accept-withdrawal-request

Accepts a withdrawal request.

* Parameters:
  * `request-id`: `uint` - Withdrawal request ID
  * `bitcoin-txid`: `(buff 32)` - Bitcoin transaction ID
  * `signer-bitmap`: `uint` - Bitmap of signers
  * `output-index`: `uint` - Output index in the Bitcoin transaction
  * `fee`: `uint` - Actual fee paid
* Returns: `(response bool uint)`

### reject-withdrawal-request

Rejects a withdrawal request.

* Parameters:
  * `request-id`: `uint` - Withdrawal request ID
  * `signer-bitmap`: `uint` - Bitmap of signers
* Returns: `(response bool uint)`

### complete-withdrawals

Processes multiple withdrawal requests (accept or reject).

* Parameters:
  * `withdrawals`: `(list 600 {...})` - List of withdrawal details
* Returns: `(response uint uint)`

## Read-only Functions

### validate-recipient

Validates the recipient's Bitcoin address format.

* Parameters:
  * `recipient`: `{ version: (buff 1), hashbytes: (buff 32) }` - Bitcoin address details
* Returns: `(response bool uint)`

## Private Functions

### complete-individual-withdrawal-helper

Helper function to process individual withdrawals in the batch operation.

* Parameters:
  * `withdrawal`: `{...}` - Individual withdrawal details
  * `helper-response`: `(response uint uint)` - Accumulator for processing
* Returns: `(response uint uint)`

## Interactions with Other Contracts

* `.sbtc-token`: Calls `protocol-lock`, `protocol-burn-locked`, `protocol-mint`, and `protocol-unlock` for token operations.
* `.sbtc-registry`: Calls `create-withdrawal-request`, `get-withdrawal-request`, `get-current-signer-data`, `complete-withdrawal-accept`, and `complete-withdrawal-reject` for managing withdrawal requests and signer data.

## Security Considerations

{% stepper %}
{% step %}
**Access Control**

Only the current signer principal can accept or reject withdrawal requests.
{% endstep %}

{% step %}
**Dust Limit**

Enforces a minimum withdrawal amount to prevent spam and ensure economic viability.
{% endstep %}

{% step %}
**Fee Management**

Ensures that the actual fee doesn't exceed the maximum fee set by the user.
{% endstep %}

{% step %}
**Address Validation**

Implements thorough validation of Bitcoin address formats.
{% endstep %}

{% step %}
**State Management**

Prevents double-processing of withdrawal requests.
{% endstep %}
{% endstepper %}

## Bitcoin Address Types

The contract supports various Bitcoin address types, including:

* P2PKH (Pay-to-Public-Key-Hash)
* P2SH (Pay-to-Script-Hash)
* P2SH-P2WPKH (P2SH nested P2WPKH)
* P2SH-P2WSH (P2SH nested P2WSH)
* P2WPKH (Pay-to-Witness-Public-Key-Hash)
* P2WSH (Pay-to-Witness-Script-Hash)
* P2TR (Pay-to-Taproot)

Each address type is represented by a specific version byte and hashbytes format in the recipient structure.


# sBTC Deposit

## Overview

The [sBTC Deposit contract](https://github.com/stacks-network/sbtc/blob/main/contracts/contracts/sbtc-deposit.clar) (`sbtc-deposit.clar`) manages the deposit process for the sBTC system. It handles the validation and minting of sBTC tokens when users deposit Bitcoin, and interacts with the sBTC Registry contract to update the protocol state.

## Constants

* `txid-length`: The required length of a transaction ID (32 bytes).
* `dust-limit`: The minimum amount for a valid deposit (546 satoshis).

## Error Constants

* `ERR_TXID_LEN` (u300): Indicates that the provided transaction ID is not the correct length.
* `ERR_DEPOSIT_REPLAY` (u301): Signifies an attempt to replay a deposit that has already been completed.
* `ERR_LOWER_THAN_DUST` (u302): Indicates that the deposit amount is below the dust limit.
* `ERR_DEPOSIT_INDEX_PREFIX`: Used as a prefix for deposit-related errors in batch processing.
* `ERR_DEPOSIT` (u303): General deposit error.
* `ERR_INVALID_CALLER` (u304): Indicates that the caller is not authorized to perform the operation.

***

## Public Functions

### complete-deposit-wrapper

Processes a single deposit request.

* Parameters:
  * `txid`: `(buff 32)` - The Bitcoin transaction ID
  * `vout-index`: `uint` - The output index of the deposit transaction
  * `amount`: `uint` - The amount of sBTC to mint (in satoshis)
  * `recipient`: `principal` - The Stacks address to receive the minted sBTC
* Returns: `(response bool uint)`

{% stepper %}
{% step %}
**Validation and authorization**

1. Verifies that the caller is the current signer principal.
2. Checks that the deposit amount is above the dust limit.
3. Validates the transaction ID length.
   {% endstep %}

{% step %}
**Replay protection**

4. Ensures the deposit hasn't been processed before (prevents replay).
   {% endstep %}

{% step %}
**Execution**

5. Mints sBTC tokens to the recipient via `.sbtc-token`'s `protocol-mint`.
6. Updates the deposit state in the sBTC Registry contract via `.sbtc-registry`'s `complete-deposit`.
   {% endstep %}
   {% endstepper %}

***

### complete-deposits-wrapper

Processes multiple deposit requests in a single transaction.

* Parameters:
  * `deposits`: `(list 650 {txid: (buff 32), vout-index: uint, amount: uint, recipient: principal})` - List of deposit data
* Returns: `(response uint uint)`

{% stepper %}
{% step %}
**Authorization**

1. Verifies that the caller is the current signer principal.
   {% endstep %}

{% step %}
**Batch processing**

2. Iterates through the list of deposits, processing each one using the `complete-individual-deposits-helper` function.
   {% endstep %}
   {% endstepper %}

***

## Private Functions

### complete-individual-deposits-helper

Helper function to process individual deposits within the batch operation.

* Parameters:
  * `deposit`: `{txid: (buff 32), vout-index: uint, amount: uint, recipient: principal}` - Single deposit data
  * `helper-response`: `(response uint uint)` - Accumulator for tracking processed deposits
* Returns: `(response uint uint)`

{% stepper %}
{% step %}
**Call deposit wrapper**

1. Calls `complete-deposit-wrapper` for the individual deposit.
   {% endstep %}

{% step %}
**Success handling**

2. If successful, increments the processed deposit count.
   {% endstep %}

{% step %}
**Error handling**

3. If an error occurs, it's propagated with additional index information (using `ERR_DEPOSIT_INDEX_PREFIX` or related error constants).
   {% endstep %}
   {% endstepper %}

***

## Interactions with Other Contracts

* `.sbtc-registry`: Calls `get-current-signer-data`, `get-completed-deposit`, and `complete-deposit` to manage deposit state.
* `.sbtc-token`: Calls `protocol-mint` to create new sBTC tokens.

***

## Security Considerations

1. Access Control: Only the current signer principal can call the deposit completion functions.
2. Replay Prevention: The contract checks for previously processed deposits to prevent replay attacks.
3. Dust Limit: Enforces a minimum deposit amount to prevent spam and ensure economic viability.
4. Transaction ID Validation: Ensures the provided transaction ID is the correct length.


# Supporting Features

This section covers additional features that enhance the functionality and security of the sBTC system. These auxiliary features contribute to the overall robustness and user-friendliness of the sBTC ecosystem.

{% stepper %}
{% step %}
**Transaction Fee Sponsorship**

Allowing sBTC transactions to be sponsored.
{% endstep %}

{% step %}
**Signer Wallet Rotation**

Enabling secure key rotation for sBTC Signers.
{% endstep %}
{% endstepper %}


# Transaction Fee Sponsorship

Transaction Fee Sponsorship is a feature in sBTC that allows users to pay for Stacks transaction fees using sBTC instead of STX.

## Overview

* sBTC transactions on Stacks can be sponsored in return for some sBTC.
* This feature improves user experience by allowing sBTC holders to use their tokens for gas fees.

## Implementation

The fee sponsorship system is implemented using the approach suggested in [stacks-network/stacks-core#4235](https://github.com/stacks-network/stacks-core/issues/4235).

{% stepper %}
{% step %}
**Sponsor support for fees**

sBTC users can get support from existing STX holders for transaction fees.
{% endstep %}

{% step %}
**Sponsor receives sBTC**

The sponsor pays the STX fee and receives sBTC in return.
{% endstep %}
{% endstepper %}

## User Experience

From a user's perspective:

{% stepper %}
{% step %}
**Opt into fee sponsorship**

When initiating an sBTC transaction, they can opt for fee sponsorship.
{% endstep %}

{% step %}
**Agree to sponsorship terms**

The user agrees to pay a small amount of sBTC for the sponsorship.
{% endstep %}

{% step %}
**Transaction processed**

The transaction is then processed with the fees paid in STX by the sponsor.
{% endstep %}
{% endstepper %}

## Benefits

* Improved UX: Users don't need to hold STX to use sBTC.
* Lower Barrier to Entry: New users can start using sBTC without first acquiring STX.
* Flexibility: Provides an additional option for handling transaction fees.


# Signer Wallet Rotation

Signer wallet rotation allows sBTC signers to update their private keys and modify the signer set composition. This mechanism is how the network maintains security over time and adapts to changing participants.

## How it works

The sBTC system uses a multi-signature wallet on Bitcoin to custody BTC deposits. When the system needs to change who controls this wallet—either by rotating keys or changing the signer set—it uses the rotation mechanism.

As of v1.1.0, the system supports:

* Adding new signers to the set
* Removing existing signers
* Replacing specific signers
* Rotating keys for current signers

When signers agree on a new configuration, the system automatically runs a Distributed Key Generation (DKG) protocol to create new signing shares for the updated group. Once complete, control of the sBTC wallet transfers to the new configuration.

## The rotation process

{% stepper %}
{% step %}
**Signers coordinate off-chain**

Signers agree on the new signer set.
{% endstep %}

{% step %}
**Update configuration**

Each signer operator updates their configuration with the newly decided set.
{% endstep %}

{% step %}
**DKG runs automatically**

Once all signers have configured the exact same set of signers, DKG occurs automatically to generate new signing shares.
{% endstep %}

{% step %}
**New signer set takes control**

The new signer set takes control of the sBTC wallet.
{% endstep %}
{% endstepper %}

The Bitcoin UTXOs remain under continuous control throughout this process—there's no moment where funds are unsecured.

## When rotation occurs

Key rotation typically happens when:

* **Signer changes**: When someone leaves the signer set or new participants join, the configuration must be updated to reflect the new membership.
* **Security events**: If a key might be compromised, an emergency rotation can be initiated to secure the system.


# Walkthroughs


# Signer Process Walkthrough

<div data-with-frame="true"><figure><img src="/files/40019PENaxoqykJqfgqh" alt=""><figcaption></figcaption></figure></div>

## Introduction

This document provides a detailed overview of the sBTC system, focusing on the operations of an sBTC signer node. We'll explore the automated processes and software interactions that occur in the sBTC ecosystem.

A step-by-step guide for setting up and running a sBTC signer node is in the works. This is a conceptual guide to help signers understand what their role looks like in the sBTC system.

## Signer Node Setup

As an sBTC signer, your primary responsibility is to run and maintain a signer node. Here's what that entails:

{% stepper %}
{% step %}
**Hardware setup**

Ensure your node has sufficient computational power and storage.
{% endstep %}

{% step %}
**Software installation**

Install the sBTC signer node software and its dependencies.
{% endstep %}

{% step %}
**Key management**

The node software securely generates and stores the Bitcoin private key and corresponding public key.
{% endstep %}

{% step %}
**Node registration**

Upon first run, the node automatically registers its public key with the sBTC Registry contract on the Stacks blockchain.
{% endstep %}
{% endstepper %}

## Day-to-Day Operations

Once set up, your signer node operates autonomously, performing the following tasks:

{% stepper %}
{% step %}
**Monitoring Deposit Requests**

Your node continuously monitors for sBTC minting requests:

* The node connects to the Bitcoin network and the Stacks blockchain.
* It watches for Bitcoin transactions sent to the sBTC UTXO address.
* When a deposit is detected, the node verifies the transaction details.
  {% endstep %}

{% step %}
**Processing Mint Requests**

Upon confirming a deposit:

* The node automatically prepares a signature for the mint operation using its private key.
* It submits this signature to the sBTC Deposit contract on the Stacks blockchain.
* The contract verifies the signature and combines it with signatures from other signer nodes.
* Once enough valid signatures are collected, the contract mints the corresponding amount of sBTC.
  {% endstep %}

{% step %}
**Handling Withdrawal Requests**

For sBTC withdrawal requests:

* The node monitors the sBTC Withdrawal contract for new requests.
* Upon detecting a request, it verifies the user's sBTC balance and the request's validity.
* The node automatically signs the withdrawal operation and submits its signature.
* Once enough signatures are collected and the sBTC is burned, the node participates in creating and signing a Bitcoin transaction to fulfill the withdrawal.
* The signed Bitcoin transaction is broadcast to the Bitcoin network.
  {% endstep %}
  {% endstepper %}


# sBTC Transaction Walkthrough

Let's follow the journey of 1 BTC as it moves through the sBTC system, from initial deposit to final withdrawal.

## Part 1: Deposit (BTC → sBTC)

{% stepper %}
{% step %}
**Initiation**

* Alice decides to convert 1 BTC to sBTC to participate in Stacks DeFi.
* Alice creates a deposit transaction on the Bitcoin network (typically via a UI such as the sBTC bridge or a DeFi application).
* The transaction enters the Bitcoin mempool.
  {% endstep %}

{% step %}
**Proof Submission**

* Alice submits proof of her deposit to the Deposit API (usually via the application's UI).
* The Deposit API sets the deposit status to PENDING.
  {% endstep %}

{% step %}
**Signer Validation**

The sBTC Signer Set:

* Detects the deposit.
* Validates the UTXO format.
* Votes on the deposit.

If the deposit is rejected:

* Signers notify the API of the rejection.
* The Deposit API updates the status to FAILED.

If the deposit is accepted:

* The Deposit API updates the status to ACCEPTED.
  {% endstep %}

{% step %}
**Bitcoin Transaction**

If accepted, the sBTC Signer Set:

* Creates a new Bitcoin transaction consuming Alice's deposited BTC.
* Broadcasts this transaction to the Bitcoin network.

If this transaction fails:

* Signers notify the API of the failure.
* The Deposit API updates the status to FAILED.
  {% endstep %}

{% step %}
**sBTC Minting**

Upon successful Bitcoin transaction:

* The sBTC Signer Set interacts with the Stacks blockchain.
* They fulfill the deposit by minting 1 sBTC to Alice's Stacks address.
  {% endstep %}

{% step %}
**Confirmation**

* The Deposit API updates the deposit status to CONFIRMED.
* Alice now has 1 sBTC in her Stacks wallet.
  {% endstep %}
  {% endstepper %}

***

## Part 2: sBTC Usage

Alice can now use her 1 sBTC in the Stacks ecosystem:

* Transfer it to other users via the `sbtc-token` contract (typically via an application UI).
* Participate in DeFi applications.
* Use it in any application that supports SIP-010 tokens.

***

## Part 3: Withdrawal (sBTC → BTC)

{% stepper %}
{% step %}
**Initiation**

* Alice initiates a withdrawal by interacting with the Clarity contract on the Stacks blockchain.
* She specifies her Bitcoin address for the withdrawal.
* If successful, the contract locks her sBTC and the withdrawal status is set to PENDING.
* If the transaction fails, no withdrawal occurs.
  {% endstep %}

{% step %}
**Signer Validation**

The sBTC Signer Set:

* Detects the withdrawal request.
* Decides whether to accept or reject the withdrawal.

If the withdrawal is rejected:

* Signers unlock the sBTC.
* The withdrawal status is updated to FAILED.

If the withdrawal is accepted:

* The withdrawal status is updated to ACCEPTED.
* Signers wait for 6 Bitcoin block confirmations (for security purposes).
  {% endstep %}

{% step %}
**Bitcoin Transaction**

After the waiting period, if accepted:

* The sBTC Signer Set creates a new Bitcoin transaction fulfilling Alice's withdrawal.
* They broadcast this transaction to the Bitcoin network.

If this transaction fails:

* Signers unlock the sBTC.
* The withdrawal status is updated to FAILED.
  {% endstep %}

{% step %}
**sBTC Burning and Confirmation**

Upon successful Bitcoin transaction:

* The sBTC Signer Set burns the locked 1 sBTC on the Stacks blockchain.
* The withdrawal status is updated to CONFIRMED.
  {% endstep %}

{% step %}
**Completion**

* Alice now has her 1 BTC back in her specified Bitcoin address.
* The withdrawn sBTC has been permanently removed from circulation.
  {% endstep %}
  {% endstepper %}


# Using the sBTC Bridge App

Start bridging over your BTC into sBTC on Stacks with the official sBTC Bridge app.

<div data-with-frame="true"><figure><img src="/files/Z1zcuFPBT9uN16KHiYvP" alt=""><figcaption><p><a href="https://sbtc.stacks.co/">https://sbtc.stacks.co/</a></p></figcaption></figure></div>

The purpose of the user-facing sBTC Bridge app is to facilitate seamless and secure conversion between BTC and sBTC. You can deposit (peg-in) your BTC into sBTC. Or you can withdraw (peg-out) your sBTC back into BTC. The app also provides an intuitive interface for safely managing the history of your transactions.

{% hint style="info" %}
The official sBTC Bridge app is found at <https://sbtc.stacks.co/>
{% endhint %}

Refer to the following guides below to learn how you can securely convert your BTC into sBTC.

* [How to Use the sBTC Bridge with Xverse/Leather](/learn/sbtc/using-the-sbtc-bridge-app/how-to-use-the-sbtc-bridge)
* [How to Use the sBTC Bridge with Fordefi](/learn/sbtc/using-the-sbtc-bridge-app/how-to-use-the-sbtc-bridge-with-fordefi)
* [How to Use the sBTC Bridge with Asigna](/learn/sbtc/using-the-sbtc-bridge-app/how-to-use-the-sbtc-bridge-with-asigna)


# How to Use the sBTC Bridge with Xverse/Leather

The sBTC bridge is a web application allowing you to convert your BTC into sBTC on the Stacks chain.

{% hint style="danger" %}
Ensure that you are using the bridge located at [sbtc.stacks.co](https://sbtc.stacks.co/). This is the only official sBTC bridge.
{% endhint %}

If you aren't familiar with sBTC, be sure to check out the [sBTC Conceptual Guide](/learn/sbtc) to understand how it works.

The bridge has been designed to be as simple as possible to use. In order to utilize sBTC, all you need to do is send a Bitcoin transaction using a supported wallet (like [Leather](https://leather.io/) or [Xverse](https://www.xverse.app/)). This guide will show screenshots of Xverse but the flow is the same if using Leather as well.

Below you'll find both a video and written walkthrough of using the bridge.

### Video Walkthrough

{% embed url="<https://youtu.be/XZruuDgTo4k>" %}

### Written Walkthrough

There are 5 simple steps to convert your BTC to sBTC.

{% stepper %}
{% step %}
**Connect your wallet**

First, you'll need to connect your wallet to the bridge UI. Currently Leather and Xverse are supported, with more on the way.

<div data-with-frame="true"><figure><img src="/files/WI7vUoqURScMTtH7W0Ee" alt=""><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Choose the amount to deposit**

After your wallet is connected, choose how much BTC you would like to convert to sBTC.

<div data-with-frame="true"><figure><img src="/files/1T5qzvl0ViLe2c8DTkbU" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
There are two transaction fees required to mint your sBTC. The first is set by the user manually when they initiate the deposit transaction within their wallet. The second is a fee used to consolidate the deposit UTXOs into the single signer UTXO. This separate transaction fee happens automatically and is set to a max of 80k sats. This is automatically deducted from your minted sBTC. This is not a signer fee but a regular Bitcoin transaction fee.
{% endhint %}
{% endstep %}

{% step %}
**Choose the Stacks address to mint to**

Next, enter the Stacks address you would like your sBTC minted to.

<div data-with-frame="true"><figure><img src="/files/wlLy5okCvoBmDa2gHTeB" alt=""><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Initiate the transaction**

After you choose your Stacks address, you'll use your connected wallet to transfer the BTC.

<div data-with-frame="true"><figure><img src="/files/CUACH8vQoj9QyzZWuYuW" alt=""><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Receive your sBTC**

In the UI, you can monitor the status of your transaction to see when it has been completed, at which point you can see the sBTC in your wallet. It will go through three stages:

* Pending - Your Bitcoin transaction is processing
* Minting - Your Bitcoin transaction has processed and the sBTC signers are minting your sBTC
* Completed - Your sBTC has been minted to your wallet

Note that you may need to enable the display of the sBTC token within your wallet by clicking on 'Manage Tokens' and enabling sBTC.

<div data-with-frame="true"><figure><img src="/files/qRvNx6qY64u0OfNfYVWF" alt=""><figcaption></figcaption></figure></div>
{% endstep %}
{% endstepper %}

### Reclaiming BTC

If your sBTC mint fails, you can reclaim your sBTC. You can do this via the bridge by visiting the reclaim page at <https://sbtc.stacks.co/\\>\<TX\_ID>/reclaim and replacing the bracketed text with your transaction ID, eg. <https://sbtc.stacks.co/8f37f750b6646f0a217121201967170bd3cfef5f2ebd4f30f359b5e9308470c4/reclaim>

There is an intermediate step in between depositing BTC and the sBTC signers consolidating it into the single signer UTXO. If the transaction is not picked up by signers, you can reclaim it using this UI. Note there is a 'Lock Time' field on the Reclaim page. That indicates the amount of blocks that must have passed in order to reclaim your BTC.

<div data-with-frame="true"><figure><img src="/files/QwHSP0BEyxR756tvdQlb" alt=""><figcaption></figcaption></figure></div>

This initiates a Bitcoin transaction that will transfer your BTC back to you.


# How to Use the sBTC Bridge with Fordefi

{% hint style="warning" %}
This guide is specifically for entities or teams that use [Fordefi](https://fordefi.com/) as it will demonstrate the flow for a multi-approval transaction policy setup. This assumes you have the Fordefi wallet setup with its browser extension and with its mobile app.
{% endhint %}

The sBTC Bridge is a web application allowing you to convert your BTC into sBTC on the Stacks chain. If you aren't familiar with sBTC, be sure to check out the [sBTC Conceptual Guide](/learn/sbtc) to understand how it works.

{% hint style="danger" %}
Ensure that you are using the bridge located at [sbtc.stacks.co](https://sbtc.stacks.co/). This is the only official sBTC bridge.
{% endhint %}

The sBTC Bridge has been designed to be as simple as possible to use. But specifically for this guide, a **2-of-2 approval transaction policy**, targeting Bitcoin transactions, has already been setup in the Fordefi UI. It is assumed you have a similar setup as this guide will walkthrough the different steps needed to take in such a scenario where multiple parties need to approve a transaction.

If you need assistance in setting up such a transaction policy in Fordefi, check out their dedicated [docs](https://docs.fordefi.com/user-guide/policies).

### Walkthrough for minting sBTC

Here are the necessary steps to convert your BTC to sBTC using Fordefi:

{% stepper %}
{% step %}
**Confirm your BTC and STX vaults**

First, you'll need to make sure you have a vault for Bitcoin, and a separate vault for Stacks. Both of these vaults will be used later when connecting with the sBTC Bridge app.

<div data-with-frame="true"><figure><img src="/files/ucFlOSACDAMY4vyrvyOp" alt=""><figcaption><p>A vault for native Bitcoin assets</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/bo2R5YsZRwRlLxTVkDBg" alt=""><figcaption><p>A vault for native Stacks assets</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Connect your Fordefi wallet extension**

First, you'll need to connect your Fordefi wallet to the sBTC Bridge app.

<div data-with-frame="true"><figure><img src="/files/IONsZ0OxHTcLAbepdJVc" alt=""><figcaption><p>Choose the option for Fordefi in the wallet selector modal</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Choose which Bitcoin and Stacks vault you want to use**

Next, the Fordefi extension will want you to select which Bitcoin vault, and then which Stacks vault you'd want to use. The reasoning for this is because you'll be needing to send a bitcoin transaction first from your Bitcoin vault, then you'll be receiving sBTC to your Stacks vault.

<div data-with-frame="true"><figure><img src="/files/ZsnAPKPG44NP0kNhPIrM" alt=""><figcaption><p>The selected Bitcoin vault needs to have at least the minimum required amount (0.001 BTC) of bitcoin to peg-in</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/GDj0Km0WbBZEianM6wIx" alt=""><figcaption><p>When both vaults are selected, you'll be able to see both at the top of the Fordefi extension when connected</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Choose the amount of BTC to deposit**

After your wallet is connected, choose how much BTC you would like to convert to sBTC.

{% hint style="info" %}
There are two transaction fees required to mint your sBTC. The first is when they initiate the bitcoin deposit transaction within their wallet. The second is a fee used to consolidate the deposit UTXOs into the single Signer's UTXO. This separate transaction fee happens automatically and is set to a max of 80k sats. This is automatically deducted from your minted sBTC. This is not a Signer fee but a regular bitcoin transaction fee.
{% endhint %}

<div data-with-frame="true"><figure><img src="/files/oEUuuf8d8lvEQGhL0fqc" alt=""><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Choose the Stacks address to mint the sBTC to**

Next, enter the Stacks address you would like your sBTC minted to. This will just be the Stacks address associated with the Stacks vault that you selected earlier when connecting your Fordefi wallet extension.

<div data-with-frame="true"><figure><img src="/files/qFYILR3Nf5V5htYd2xjv" alt=""><figcaption><p>Review the inputted STX address and then confirm</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Create initial BTC transfer**

Your Fordefi wallet extension will pop up prompting you to create the BTC transaction. This transaction is the initial peg-in transfer for your BTC to the sBTC Signers. Hit 'Create' after you confirm the transaction details and necessary approval details.

{% hint style="info" %}
If you have a transaction policy setup with certain approvals required, hitting 'Create' will not initiate the bitcoin transaction, it will simply store this unsigned transaction in your Fordefi wallet until all necessary approvals are met and then finally signed.
{% endhint %}

<div data-with-frame="true"><figure><img src="/files/m65rA0UG0IpL6CRiWq3I" alt=""><figcaption><p>You'll notice near the bottom of the Create Transaction view of the Fordefi extension is the required approval details. Be certain the other approvers are available to approve the transaction in a timely manner.</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/PznZzyTUdboJV8anVpfX" alt=""><figcaption><p>If you ever navigate back to your Fordefi web UI or extension UI, you'll notice this transaction will be marked as 'Pending approval'.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Approve transaction by approvers**

Upon notice of transaction to approvers, each approver will need to approve transaction in their Fordefi mobile wallets before the completion of the final step, which is signing the transaction by the initiator.

Each approver will need to pull up the pending transaction in their Fordefi mobile wallet and hit 'Approve'.

<div data-with-frame="true"><figure><img src="/files/v3s4kxQfiVtfe5akq85r" alt=""><figcaption><p>POV of approving transaction by approver</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Sign approved transaction**

Once all transaction policies are satisfied and approved, the initiator will need to officially sign the transaction in their Fordefi mobile wallet.

This mobile signature action will then notify the sBTC Bridge app.

<div data-with-frame="true"><figure><img src="/files/szZKeX7QtU797pwgQf37" alt=""><figcaption><p>The initiator will need to hit 'Sign' once approvals and transaction details are confirmed</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Receive your sBTC**

Back in the sBTC Bridge app UI, you can monitor the status of your transaction to see when it has been completed, at which point you can see the sBTC in your Fordefi wallet. It will go through three stages:

* Pending - Your [Bitcoin transaction](https://mempool.space/tx/6b5e63fbe4e4a4835dcf096ca2d2a8c112898692e28a4c5b38cb39e3e9837604) is processing
* Minting - Your Bitcoin transaction has processed and the [sBTC signers are minting](https://explorer.hiro.so/txid/a9e232289d2c6e50150b034894182d341343e7064b27c8dccbd25ebca79b2947?chain=mainnet) your sBTC
* Completed - Your sBTC has been minted to your wallet

<div data-with-frame="true"><figure><img src="/files/v13D1AvoV2j1WoM089yY" alt=""><figcaption><p>The bitcoin and sBTC transactions will take some time to be completely processed by the Signers</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/nz1zddNMjAsvJ72Em0vY" alt=""><figcaption><p>Once both the bitcoin and sBTC mint transactions are confirmed, the sBTC Bridge app will show a 'Complete' status</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/EMkh8RTK9FG4Pqf8ip8R" alt=""><figcaption><p>You'll be able to see the results of these transactions in your Fordefi wallet</p></figcaption></figure></div>
{% endstep %}
{% endstepper %}

### Reclaiming BTC

If your sBTC mint fails, you can reclaim your sBTC. You can do this via the bridge by visiting the reclaim page at <https://sbtc.stacks.co/\\>\<TX\_ID>/reclaim and replacing the bracketed text with your transaction ID as shown below:\
<https://sbtc.stacks.co/8f37f750b6646f0a217121201967170bd3cfef5f2ebd4f30f359b5e9308470c4/reclaim>

There is an intermediate step in between depositing BTC and the sBTC signers consolidating it into the single signer UTXO. If the transaction is not picked up by signers, you can reclaim it using this UI. Note there is a 'Lock Time' field on the Reclaim page. That indicates the amount of blocks that must have passed in order to reclaim your BTC.

<div data-with-frame="true"><figure><img src="/files/QwHSP0BEyxR756tvdQlb" alt=""><figcaption></figcaption></figure></div>

This initiates a Bitcoin transaction that will transfer your BTC back to you.


# How to Use the sBTC Bridge with Asigna

{% hint style="warning" %}
This guide is specifically for entities or teams that use [Asigna](https://www.asigna.io/) as it will demonstrate the flow for a multi-signature setup. This assumes you have the Asigna web wallet setup with its browser extension.
{% endhint %}

The sBTC Bridge is a web application allowing you to convert your BTC into sBTC on the Stacks chain. If you aren't familiar with sBTC, be sure to check out the [sBTC Conceptual Guide](/learn/sbtc) to understand how it works.

{% hint style="danger" %}
Asigna has the sBTC Bridge as an embedded app within its web wallet. This guide will be using that embedded app.
{% endhint %}

The sBTC Bridge has been designed to be as simple as possible to use. But specifically for this guide, a **2-of-2 multi-signature setup of a Bitcoin vault AND a separate Stacks vault**. It is assumed you have a similar setup as this guide will walkthrough the different steps needed to take in such a scenario where 2 parties of this 2-of-2 multi-signature setup need to sign transactions.

### Walkthrough for minting sBTC

Here are the necessary steps to convert your BTC to sBTC using Asigna:

{% stepper %}
{% step %}
**Confirm your BTC and STX vaults**

First, you'll need to make sure you have a vault for Bitcoin, and a separate vault for Stacks. In this scenario, the same 2-of-2 signature setup are applied for both vaults. Throughout the guide, we'll refer to each party of this setup as Member\_1 and Member\_2.

<div data-with-frame="true"><figure><img src="/files/XAL5qEKyVLlUHfWedgLC" alt=""><figcaption><p>Member_2's POV of both its Bitcoin vault and Stacks vault setup.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Navigate and open the embedded sBTC Bridge app in Bitcoin vault**

Click into the Bitcoin vault and scroll down to the 'Trending Apps' section where you'll locate the sBTC Bridge embedded app. Open this embedded app and choose the 'Asigna Multisig' wallet to connect with.

<div data-with-frame="true"><figure><img src="/files/tlWKnkct0R94KBk8JQpz" alt=""><figcaption><p>Locate the sBTC Bridge embedded app and open it.</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/iuq7F8J2EfgOqGs9hgYB" alt=""><figcaption><p>Connect with the Asigna Multisig wallet option. This app will auto connect with the Bitcoin vault that is being using in this context of the embedded app. You won't need to connect to a Stacks vault but you will need a Stacks vault address to use as the receiving address of the minted sBTC.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Choose the amount of BTC to deposit**

After your Bitcoin vault is connected, choose how much BTC you would like to convert to sBTC.

{% hint style="info" %}
There are two transaction fees required to mint your sBTC. The first is when they initiate the bitcoin deposit transaction within their wallet. The second is a fee used to consolidate the deposit UTXOs into the single Signer's UTXO. This separate transaction fee happens automatically and is set to a max of 80k sats. This is automatically deducted from your minted sBTC. This is not a Signer fee but a regular bitcoin transaction fee.
{% endhint %}

<div data-with-frame="true"><figure><img src="/files/zAzHlGs9Wb1ktZdCG0pq" alt=""><figcaption><p>Currently the minimum to peg-in is 0.001 BTC.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Choose the Stacks address from the Stacks vault**

Next, enter the Stacks address you would like your sBTC minted to. For this guide, we'll be using the Stacks address of the Stacks vault that is assumed to be setup by both Member\_1 and Member\_2.

<div data-with-frame="true"><figure><img src="/files/BiInTNoHF2EbDqb1YwsI" alt=""><figcaption><p>Copy the multi-signature Stacks address from the Stacks vault setup.</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/nzHPiQgiRFnwm9ypllH5" alt=""><figcaption><p>Review the inputted STX address, hit 'NEXT', and then 'CONFIRM'.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Select Fee Rate**

Depending on congestion of the Bitcoin network, choose the appropriate fee rate based on your vault's preferences for timely confirmation.

<div data-with-frame="true"><figure><img src="/files/a0LuE9QTTdUMxtAtMMUD" alt=""><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Confirm the transaction creation**

Whomever member, of the 2-of-2 multi-signature setup, is currently acting as the context of the sBTC Bridge embedded app, a popup modal of that member's wallet will appear for confirmation. In this guide, is it Member\_1 that is acting as the context and is currently connected with the Bitcoin vault using Xverse. Therefore, the Xverse wallet popup will appear for confirmation.

Remember, this transaction is the initial peg-in transfer for your BTC to the sBTC Signers.

{% hint style="info" %}
If you have a multi-signature setup with certain signatures required, hitting 'Confirm' will not broadcast the bitcoin transaction, it will simply store this partially signed transaction in your Bitcoin vault until all required signatures are met.
{% endhint %}

<div data-with-frame="true"><figure><img src="/files/Gi6Vm5Q8h6DvSNsX2boQ" alt=""><figcaption><p>Review the transaction and hit confirm to create the partially signed bitcoin transaction where it will be waiting for the other members to sign in their respective Asigna Bitcoin vaults.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Sign and approve transaction by other members**

Upon notice of transaction to the other members of the multi-signature setup, each necessary member will need to approve the pending transaction in their own respective Asigna Bitcoin vaults.

In our case, Member\_2 will navigate to their own Bitcoin vault and find the pending partially signed bitcoin transaction waiting for signature.

<div data-with-frame="true"><figure><img src="/files/oFw4fh2WRvDhlg0vNybB" alt=""><figcaption><p>Member_2 will locate the pending transaction and complete signature as their approval.</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/0f3e0sH4WULXnywEUheh" alt=""><figcaption><p>Member_2 will see their connected wallet, in this case Leather, popup for them to confirm transaction.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Broadcasting of transaction**

Once all transaction policies are satisfied and approved, the sBTC Bridge embedded app will appear with a prompt confirming that all signatures have been gathered successfully which will then automatically prompt the broadcasting of the transaction.

<div data-with-frame="true"><figure><img src="/files/TIZCy0RrFVeWYDr40XCH" alt=""><figcaption><p>Great! All signatures have been gathered for the transaction to be broadcasted.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Receive your sBTC**

Back in the sBTC Bridge app UI, you can monitor the status of your transaction to see when it has been completed, at which point you can see the sBTC in your Fordefi wallet. It will go through three stages:

* Pending - Your [Bitcoin transaction](https://mempool.space/tx/838ebd2c78091ca805ff00c2a2182d2e9c652bd9b43ef286c3af33d1a414f587) is processing
* Minting - Your Bitcoin transaction has processed and the [sBTC signers are minting](https://explorer.hiro.so/txid/fef3dd3f6d4e6c89f3482fdec3816822261f29739ee81d1af6deb01d11e43961?chain=mainnet) your sBTC
* Completed - Your sBTC has been minted to your Asigna Stacks vault wallet

<div data-with-frame="true"><figure><img src="/files/uO98ptlUWtICGLRPP6Sp" alt=""><figcaption><p>The bitcoin and subsequent sBTC mint transaction will take some time to be completely processed by the Signers</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/fEXgX6sdQfp375v2u92n" alt=""><figcaption><p>Once both the bitcoin and sBTC mint transactions are confirmed, the sBTC Bridge app will show a 'Completed' status</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/XnNAwzRWOIU3Z36LU8Ys" alt=""><figcaption><p>You'll then be able to see the sBTC balance in your Asigna Stacks vault.</p></figcaption></figure></div>
{% endstep %}
{% endstepper %}

### Reclaiming BTC

If your sBTC mint fails, you can reclaim your sBTC. You can do this via the bridge by visiting the reclaim page at <https://sbtc.stacks.co/\\>\<TX\_ID>/reclaim and replacing the bracketed text with your transaction ID as shown below:\
<https://sbtc.stacks.co/8f37f750b6646f0a217121201967170bd3cfef5f2ebd4f30f359b5e9308470c4/reclaim>

There is an intermediate step in between depositing BTC and the sBTC signers consolidating it into the single signer UTXO. If the transaction is not picked up by signers, you can reclaim it using this UI. Note there is a 'Lock Time' field on the Reclaim page. That indicates the amount of blocks that must have passed in order to reclaim your BTC.

<div data-with-frame="true"><figure><img src="/files/QwHSP0BEyxR756tvdQlb" alt=""><figcaption></figcaption></figure></div>

This initiates a Bitcoin transaction that will transfer your BTC back to you.


# Security Model of sBTC

Explaining the security model of sBTC

### sBTC Security: A Multi-layered Approach

Security is the foundation of this rollout. Partnerships with top-tier security experts have been established to ensure the protocol is fortified at every level:

1. **Asymmetric Research**: Known for their rigorous research and top embedded security researchers, Asymmetric brings security expertise to sBTC to identify and mitigate potential vulnerabilities.
2. **ImmuneFi**: A robust bug bounty program incentivizes ethical hackers to uncover and address potential issues, adding an additional layer of defense. ImmuneFi is the [leading crowdsource bounty platform for DeFi](https://stacks.org/best-and-brightest-sbtc#immunefi).
3. **3rd Party Audits**: Independent audit reports have been made for additional security reviews, ensuring the protocol is thoroughly vetted by external experts.

### The components that make up the security model of sBTC

#### **sBTC Signer Network**

The sBTC Signer network is a decentralized group of entities responsible for managing the locking and unlocking of BTC during the minting and redemption of sBTC. This network operates in a distributed manner to enhance security and reduce the risks associated with centralized custodians.

Signers are responsible for approving all sBTC deposit and withdrawal operations, ensuring the integrity of the system. With a requirement of 70% consensus for transaction approval, Signers maintain the protocol's liveness and security.\
\
As approved by the Stacks community via [SIP-028](https://github.com/stacksgov/sips/blob/69d40a5f4f0ad98eb448ba44e7c31ca054820aa3/sips/sip-028/sip-028-sbtc_peg.md), the criteria for selecting signers include technical expertise, reliability, performance, and decentralization. An initial set of 15 institutional Signers will be used in Phase 1 to maintain simplicity and minimize operational risks. This group will grow as the protocol evolves.\
\
As sBTC evolves, the Signer set will transition to a fully decentralized model, further strengthening the protocol's resilience.

<div data-with-frame="true"><figure><img src="/files/ejMjtDSxzcGVl65DzplG" alt=""><figcaption><p>source: <a href="https://bitcoinl2labs.com/sbtc-rollout#sbtc-signers">Bitcoin L2 Labs</a></p></figcaption></figure></div>

For more info on who the sBTC Signers are, check out this section on the Bitcoin L2 Labs website [here](https://bitcoinl2labs.com/sbtc-rollout#sbtc-signers).

#### **Trust-Minimized Bridge Model**

The trust-minimized bridge model for sBTC ensures that the exchange between BTC and sBTC happens without relying on a single entity. Instead, it leverages cryptographic proofs and smart contracts on the Stacks blockchain, allowing for secure and transparent conversion processes.

The permissionless nature of the sBTC model empowers Bitcoin holders to freely peg their BTC into sBTC and vice versa. This process utilizes a decentralized network of Signers along with smart contracts, eliminating the need for centralized custody or intermediaries. Bitcoin holders initiate a peg by sending BTC to a predetermined address, automatically triggering the issuance of an equivalent amount of sBTC on the Stacks blockchain. Similarly, holders can burn their sBTC, prompting the smart contracts to release BTC back to their control. This model enhances user autonomy and aligns with the decentralized ethos of Bitcoin.

#### **Bitcoin Finality and Stacks**

Stacks' Bitcoin Finality mechanism aligns sBTC's security closely with Bitcoin itself. By anchoring blocks and transactions to the Bitcoin blockchain, this ensures that the finality and security of asset holdings on Stacks are as robust as those on the Bitcoin network. This integration helps maintain trust and stability for sBTC within the broader Bitcoin ecosystem.

### How sBTC's security contrasts with other wrapped Bitcoin alternatives

While the sBTC model leverages decentralization to minimize trust, other wrapped Bitcoin solutions often face centralization risks. Typically, these alternatives rely on a centralized custodian to hold the underlying BTC, introducing a significant point of failure. Such custodians act as the trust anchor in the conversion process, which can potentially lead to issues such as censorship, mismanagement, or even security breaches. As a result, these models may not fully align with the decentralized principles of Bitcoin, posing challenges to the security and autonomy intended for Bitcoin holders.

<div data-with-frame="true"><figure><img src="/files/SeFi8g0nBi6TpwQGUrCS" alt=""><figcaption><p>source: <a href="https://www.stacks.co/sbtc">stacks.co</a></p></figcaption></figure></div>

***

#### Resources

* \[[Stacks Roadmap](https://stacksroadmap.com/#sbtc)] Upcoming technical advancements and security designs for sBTC
* \[[Hiro Blog](https://www.hiro.so/blog/sbtc-vs-wbtc-a-comparison-of-tokenized-bitcoin)] sBTC vs WBTC: A Comparison of Tokenized Bitcoin


# sBTC Audits

Several third-party security audits have been conducted on the sBTC protocol and can be referenced here.

### Ottersec Audit Reports

{% file src="/files/xVJhxxMyao6iOlHYmodN" %}

{% file src="/files/XpfdWdpx0chDSqHXhImM" %}

### Immunefi Audit Reports

* <https://reports.immunefi.com/stacks-i-attackathon>
* <https://reports.immunefi.com/stacks-ii-attackathon>

### CoinFabrik Audit Reports

{% file src="/files/iyuVGtaCmqMTu5lfKSsl" %}

### Clarity Alliance Audit Reports

{% file src="/files/8TWe67mLwRVtVmxWzDoT" %}


# FAQs

### sBTC Basics

<details>

<summary>What is sBTC?</summary>

sBTC is a decentralizedl 1:1 Bitcoin-backed asset on the Stacks Bitcoin Layer. Read more about Stacks [here](https://www.stacks.co/) and sBTC [here](https://www.stacks.co/sbtc).

</details>

<details>

<summary>How does sBTC work?</summary>

sBTC as a SIP-010 tokensBTC is a SIP-010 token on the Stacks blockchain that represents Bitcoin (BTC) in a 1:1 ratio. sBTC is always backed 1:1 against BTC.Peg wallet and signersThe sBTC peg wallet is maintained and managed by a set of sBTC signers. This decentralized approach enhances security and reduces single points of failure. Read more about Stacker Signing here.

</details>

<details>

<summary>What is Bitcoin Finality, and why is it important?</summary>

Stacks and sBTC state automatically fork with Bitcoin. As such, all transactions settle to Bitcoin with 100% Bitcoin Finality. This protects users against attacks to sBTC via a hard fork. This is a critical security measure that aligns sBTC security with Bitcoin. Read more in [the Stacks Documentation](https://docs.stacks.co/concepts/block-production/bitcoin-finality).

</details>

<details>

<summary>How does the Stacks Signer network improve security?</summary>

Signers are responsible for approving all sBTC deposit and withdrawal operations, ensuring the integrity of the system. With a requirement of 70% consensus for transaction approval, Signers maintain the protocol's liveness and security.

To launch sBTC, the Stacks community approved [SIP-028](https://github.com/stacksgov/sips/blob/69d40a5f4f0ad98eb448ba44e7c31ca054820aa3/sips/sip-028-sbtc_peg.md), defining the criteria for selecting signers based on factors such as technical expertise, reliability, performance, and decentralization. An initial group of 15 institutional Signers has been chosen for Phase 1 to maintain simplicity and reduce operational risks. This group will expand over time as the protocol matures.

The list of sBTC signers is public and listed [here](https://bitcoinl2labs.com/sbtc-rollout#sbtc-signers).

</details>

<details>

<summary>What security measures have been put in place to ensure sBTC is safe?</summary>

sBTC is always backed 1:1 against BTC, and it's verifiably secure through threshold cryptography. sBTC removes the need for 3rd party custodian or trusted setup. Instead, BTC is secured by a decentralized signer set.

Partnerships with top-tier security experts have been established to ensure the protocol is fortified at every level:

Asymmetric Research is a core security contributor. Known for their rigorous research and protocol audits, Asymmetric brings security expertise to sBTC to identify and mitigate potential vulnerabilities. ImmuneFiA robust bug bounty program incentivizes ethical hackers to uncover and address potential issues, adding an additional layer of defense. 3rd Party AuditsSeveral third-party security audits have been conducted on the sBTC system and can be referenced on the sBTC Audits page.

</details>

<details>

<summary>What sets sBTC apart?</summary>

Here are the main differentiating characteristics of sBTC:

* sBTC is a true Bitcoin native product
* sBTC is backed by respected leaders in the Bitcoin community (signer network)
* sBTC's security is provided by a decentralized network of validators/signers rather than a single custodian, removing the need to trust a single entity or exchange
* sBTC leverages 100% Bitcoin finality
* sBTC's technology offers optimal UX and DevEx for an L2
* sBTC is a fully transparent project/product working in the open with public code

</details>

<details>

<summary>Where can I learn more about the sBTC signers?</summary>

Read the "[Selection of sBTC Signer Set](https://github.com/stacks-network/sbtc/discussions/624)" post for more information about each signer and their qualifications.

</details>

### Using sBTC

<details>

<summary>When will sBTC be available?</summary>

sBTC deposits first went live on December 16, 2024, quickly hitting the 1,000 BTC cap. The second cap will go live on February 25th, 2025, quickly hitting the 3,000 BTC cap. Withdrawals went live on April 30, 2025.

Full decentralization of the Signer set will follow in [a subsequent phase](https://bitcoinl2labs.com/sbtc-rollout), gradually expanding beyond the initial 15 community-elected signers.

</details>

<details>

<summary>What wallets are supported for sBTC?</summary>

[Xverse](https://www.xverse.app/) and [Leather](https://leather.io/) wallets are supported — two leading wallets with seamless integrations designed for Bitcoin and Stacks users.

In addition, [Ledger](https://www.ledger.com/) and [Asigna](https://www.asigna.io/) support sBTC.

We are actively working with institutional custodians, staking providers, and other 3rd party wallets to support sBTC. More will be announced.

</details>

<details>

<summary>Why is there a .001 BTC minimum for BTC to sBTC deposits?</summary>

A .001 BTC minimum is imposed for BTC to sBTC deposits to ensure the system does not get spammed by many smaller transactions. We are exploring reducing the deposit minimum for future phases.

</details>

<details>

<summary>What are the steps to use the sBTC Bridge and earn rewards?</summary>

In the Stacks Documentation, find a [video](https://www.youtube.com/watch?v=XZruuDgTo4k\&t=1s) and a more detailed [walkthrough](/learn/sbtc/using-the-sbtc-bridge-app).

</details>

<details>

<summary>How long will it take for my BTC deposit to confirm?</summary>

sBTC facilitates rapid movement between BTC and sBTC.

BTC to sBTCBTC to sBTC conversion can be completed within 3 Bitcoin blocks (under an hour).sBTC to BTCsBTC to BTC conversion can be completed within 6 Bitcoin blocks (Approximately two hours)

Read more in the [Stacks Documentation](https://docs.stacks.co/concepts/sbtc/operations/deposit-withdrawal-times).

</details>

<details>

<summary>Why is there a cap on the total BTC pegged in?</summary>

A BTC cap will be implemented to ensure a smooth rollout process with a focus on security.

In addition, the BTC cap will give developers the time to focus on the sBTC user experience and integration with DeFi applications across the Stacks ecosystem prior to opening sBTC for all users.

</details>

<details>

<summary>Are there any associated fees with minting sBTC?</summary>

There are two transaction fees required to mint your sBTC. The first is set by the user manually when they initiate the deposit transaction within their wallet.

The second is a fee used to consolidate the deposit UTXOs into the single signer UTXO. This separate transaction fee happens automatically and is set to a max of 80k sats. This is automatically deducted from your minted sBTC. This is not a signer fee but a regular Bitcoin transaction fee.

</details>

<details>

<summary>Are there multi-signature solutions for sBTC?</summary>

Yes. [Asigna](https://www.asigna.io/) provides a multi-signature solution for sBTC users.

</details>

<details>

<summary>Are custodians available to support sBTC?</summary>

At the moment, there is no custodian support for sBTC. However, we are actively working with institutional custodians to support sBTC.

Copper and BitGo already support Stacks and Stacking; however, we are working to prioritize SIP-10 and sBTC integration.

</details>

### sBTC Troubleshooting

<details>

<summary>My Bitcoin transaction confirmed, but I'm not seeing the sBTC token in my wallet.</summary>

You may need to enable the display of the sBTC token within your wallet by clicking on 'Manage Tokens' and enabling sBTC.

</details>

<details>

<summary>I received an "Errors.Invalid_Transaction" error when using an Xverse Wallet</summary>

If you received a "Errors.Invalid\_Transaction" error when using an Xverse Wallet, you may be using a "Nested SegWit" wallet. To resolve the issue, change your Xverse wallet to use the "Native SegWit".

</details>

<details>

<summary>sBTC still isn't showing up in wallet after 3 Bitcoin blocks. How much longer do I have to wait?</summary>

BTC to sBTC conversions are typically completed within 3 Bitcoin blocks. Due to the speed of Bitcoin blocks, deposits can take up to two hours to see sBTC in your wallet.

However, there may be a lag with your Leather or Xverse wallet where the sBTC will take another 20 minutes to show up in the wallet.

</details>


# Dual Stacking

An overview of the BTC-denominated rewards mechanism on Stacks

<div data-with-frame="true"><figure><img src="/files/7ZJitvAtUGSKFJkVlxuO" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
Check out the official blog announcement of Dual Stacking [here](https://www.stacks.co/blog/dual-stacking-launches-on-stacks).
{% endhint %}

Dual Stacking enables Bitcoin holders to earn Bitcoin-denominated rewards through Stacks' [Proof of Transfer](/learn/stacks-101/proof-of-transfer) consensus. Rewards are paid in [sBTC](/learn/sbtc).

Dual Stacking is the only way to earn Bitcoin rewards while stacking Bitcoin. Other blockchains pay rewards in their native token (ETH, SOL, etc.). They have no mechanism to generate real Bitcoin. **Stacks' Proof of Transfer (PoX)** is the architectural difference that makes Bitcoin earning Bitcoin rewards possible.\
\
As more BTC enters the Stacks network, rates will adjust. But the multiplier effect remains: pairing STX with your BTC and deploying sBTC into DeFi always amplify your returns.

***

{% embed url="<https://www.youtube.com/watch?v=bfWPr_qMQmc>" %}

***

### Additional Resources

* [**\[Github\]**](https://github.com/stx-labs/papers/blob/main/Dual%20Stacking%20Litepaper.pdf) Dual Stacking Litepaper


# How to Start Dual Stacking

Getting starting in Dual Stacking is simple.

<div data-with-frame="true"><figure><img src="/files/4EvBGgMOo3ms5SZxx5zs" alt=""><figcaption><p><a href="http://app.stacks.co/">app.stacks.co</a></p></figcaption></figure></div>

### **Overview of how to start Dual Stacking**

1. **Mint sBTC** → 1:1 Bitcoin-backed. Enroll in dual stacking to earn baseline reward.
2. **Stack STX** → Stack STX alongside your sBTC to multiply returns up to 10x.
3. **Use in DeFi** → Deploy sBTC across protocols while still earning rewards.
4. **Earn sBTC** → and redeem 1:1 for BTC anytime.

PS: your stacked STX continues to earn bitcoin while in dual stacking.

### Dual Stacking Web App

The [Dual Stacking Web App](https://app.stacks.co/) is the primary user interface for participating in Dual Stacking — a mechanism that allows Bitcoin holders to earn BTC-denominated rewards through sBTC, and maximize those rewards by either stacking STX or using sBTC in DeFi.

{% hint style="info" %}
The minimum to mint sBTC via the sBTC Bridge app is currently at 0.001 BTC (100,000 sats).

The minimum to enroll in Dual Stacking with your minted sBTC will be 0.0001 sBTC (10,000 sats).
{% endhint %}

Once connected to the web app, you'll see the dashboard that lays out all the metrics regarding your rewards composition and different methods for boosting rewards. Track your balances, rewards and payouts at anytime.

The 'Boost your rewards' section will layout the steps for you to enroll and boost your rewards. All rewards are distributed in sBTC, redeemable 1:1 for BTC anytime.

<div data-with-frame="true"><figure><img src="/files/x8NNSxrg5BBCIhmqZv8F" alt=""><figcaption><p>Track your balances, rewards and payouts at anytime on the Dual Stacking dashboard.</p></figcaption></figure></div>

Use the Dual Stacking calculator for estimated rewards based on the ratio of sBTC in your wallet and STX stacked. For more details on how your rewards are calculated and the math behind it, check out the section on the Dual Stacking [reward function](/learn/dual-stacking/economic-model#reward-function-parameters).

Start Dual Stacking now with the following wallets:

* [Dual Stack with Fordefi](/learn/dual-stacking/how-to-start-dual-stacking/using-fordefi)
* [Dual Stacking with Asigna](/learn/dual-stacking/how-to-start-dual-stacking/using-asigna)
* [Dual Stack with Leather](/learn/dual-stacking/how-to-start-dual-stacking/using-leather)

### Who is this app for?

{% tabs %}
{% tab title="sBTC holders" %}
At the end of October, users participating in sBTC Rewards program will need to enroll in Dual Stacking in order to continue earning sBTC rewards. This web app is the main way for them to do that.
{% endtab %}

{% tab title="BTC holders" %}
There are relatively few options to earn yield on BTC. This app gives BTC holders an option to earn BTC denominated rewards in an easy, trust minimized way.
{% endtab %}

{% tab title="STX holders" %}
STX holders who have participated in regular Stacking might be intrigued about a new type of Stacking, dual stacking. This app lets them try out a new iteration of a familiar flow.
{% endtab %}
{% endtabs %}

***

It's simple: Stack bitcoin, Earn bitcoin 🟧

For more questions and help with Dual Stacking, reach out to us and the community in our [Discord](https://discord.gg/5DJaBrf) and on our official [Stacks twitter](https://twitter.com/Stacks).


# Dual Stack with Fordefi

A guide in getting started with Dual Stacking using the Fordefi MPC wallet

{% hint style="warning" %}
This guide is specifically for entities or teams that use [Fordefi](https://fordefi.com/). This assumes you have the Fordefi wallet setup with its browser extension and with its mobile app.
{% endhint %}

The Dual Stacking Web App is the primary user interface for participating in Dual Stacking — a mechanism that allows Bitcoin holders to earn BTC-denominated rewards through sBTC, and maximize those rewards by either stacking STX or using sBTC in DeFi.

{% hint style="danger" %}
Ensure that you are using the official Dual Stacking app located at [app.stacks.co](https://app.stacks.co/).
{% endhint %}

For this guide, we'll walkthrough how you can use your Fordefi wallet in enrolling Dual Stacking and participating in DeFi for boosted rewards. This guide assumes you have a dedicated Bitcoin vault and Stacks vault setup in your Fordefi wallet.

If you need assistance in setting up your vaults in Fordefi, check out their dedicated [docs](https://docs.fordefi.com/user-guide/policies).

Before enrolling in Dual Stacking, you'll need sBTC. Peg in BTC to sBTC through the [sBTC bridge](https://app.stacks.co/) (where it remains 1:1 Bitcoin-backed at all times). Check out the dedicated guide on how you can mint sBTC to your Fordefi [wallet](https://docs.stacks.co/build/sbtc/how-to-use-the-sbtc-bridge-with-fordefi).

### Walkthrough for enrolling in Dual Stacking

Here are the necessary steps to enroll your sBTC using Fordefi:

{% stepper %}
{% step %}
**Connect Fordefi to the Dual Stacking app**

Upon popup of the connect wallet modal, select the Fordefi option to connect with. As per the usual flow of connecting your Fordefi wallet with other Stacks apps, it'll prompt you to first select your Bitcoin vault, and then your Stacks vault.

<div data-with-frame="true"><figure><img src="/files/U3bXRjf1cMBACw3uWToT" alt=""><figcaption><p>Select which Bitcoin vault you want to connect with first.</p></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/Bi4dEot9uFSRit5qvdHY" alt=""><figcaption><p>Then choose which Stacks vault you want to connect with.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Enroll now for Dual Stacking**

On the dashboard, you'll be able to see stats regarding your current sBTC in wallet, sBTC in DeFi, STX currently stacked, and estimated APY you could be earning.

Let's get started by enrolling your sBTC into Dual Stacking.

<div data-with-frame="true"><figure><img src="/files/qgwemlI32YQoMqOCgAJT" alt=""><figcaption><p>Click on 'Enroll now' under the 'Enroll for rewards' step.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Create transaction**

Your Fordefi extension will appear with a popup asking you to review the transaction for creation. This will create the transaction which you will later sign and broadcast in your Fordefi mobile wallet.

<div data-with-frame="true"><figure><img src="/files/2Jcn1GUKfRVZAQIt1T8S" alt=""><figcaption><p>Create the transaction to queue it up in your Fordefi wallet for signing and broadcasting.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Sign transaction in Fordefi mobile app**

If you navigate back to your Fordefi web wallet, you'll see the transaction queued up for signatures. Depending on the transaction policy that is setup with your Fordefi vaults, you may need to instruct the designated approvers to all confirm and sign the transaction in their Fordefi mobile wallets.

<div data-with-frame="true"><figure><img src="/files/RituVPA8DdUPPaU5krPd" alt=""><figcaption><p>The 'enroll' transaction will be queued up in your Fordefi web wallet. You'll need to sign the transaction via the mobile wallet.</p></figcaption></figure></div>

Within the Fordefi mobile wallet, you'll see the same transaction waiting for signing. Go ahead and sign the transaction which will then broadcast the transaction to the network.

<div data-with-frame="true"><figure><img src="/files/aaOILcZivZN6gFcjwyFL" alt=""><figcaption><p>Complete all signatures in the Fordefi mobile wallet.</p></figcaption></figure></div>

Your enroll transaction will look like this [here](https://explorer.hiro.so/txid/0x3b4ea853df54825adad3ab475d93be18c6a12f04033c665d4597984786feb608?chain=mainnet).
{% endstep %}

{% step %}
**You are now enrolled in Dual Stacking**

You'll notice your sBTC now enrolled in Dual Stacking and when the rewards cycle will start for your enrolled sBTC.

<div data-with-frame="true"><figure><img src="/files/IRZUOMf87feLC5D0nzce" alt=""><figcaption><p>You are now Dual Stacking!</p></figcaption></figure></div>

The dashboard will also provide a view of your Dual Stacking portfolio.

<div data-with-frame="true"><figure><img src="/files/gwNRsRx0RbXywXylSY0N" alt=""><figcaption><p>View when your sBTC will start earning rewards and the breakdown of rewards composition.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Boost rewards by stacking STX**

So what's next? You could then boost your rewards by stacking STX. Let's start by stacking STX via [StackingDAO](https://www.stackingdao.com/). StackingDAO is a popular stacking option in Stacks as it is a liquid stacking method.

{% hint style="info" %}
There are other options for stacking your STX that you can find [here](https://app.leather.io/stacking).
{% endhint %}

Navigate to the StackingDAO app, connect your wallet, and start stacking. There are many methods to start liquid stacking or native stacking within StackingDAO. In this example, we'll use our STX to liquid stack with sBTC yield.

<div data-with-frame="true"><figure><img src="/files/lm67ZNO74z5jTSlup4fq" alt=""><figcaption><p>Liquid stacking with sBTC yield allows us to stay liquid and earn sBTC while stacking.</p></figcaption></figure></div>

You'll then notice the Dual Stacking app to detect your stacked positions and include that as part of your portfolio's reward composition for boosted rewards.

<div data-with-frame="true"><figure><img src="/files/AGmunJnv2SQ4x0VkaVzC" alt=""><figcaption><p>Notice the change in estimated APY and total portfolio value after stacking.</p></figcaption></figure></div>

Let's then boost reward with Stacks DeFi. This will help reach the maximum APY boost for your sBTC.
{% endstep %}

{% step %}
**Deploy your sBTC to Stacks DeFi protocols**

You'll notice near the bottom of the dashboard page, there is a section highlighting popular DeFi protocols in Stacks. Each one of these protocols are eligible for the boosted rewards you can realize.

<div data-with-frame="true"><figure><img src="/files/JLhtX6gjX5pSSrsrGqXp" alt=""><figcaption></figcaption></figure></div>

Let's deploy sBTC with Zest. Supplying sBTC in Zest will provide users with a supply APY. Confirm the 'Supply' transaction via the same signature flow with Fordefi.

<div data-with-frame="true"><figure><img src="/files/PNOMLEWhP3vyUIDUh92f" alt=""><figcaption></figcaption></figure></div>

After deploying sBTC into Zest, navigate back to the Dual Stacking web app to see your current estimated APY and rewards composition.

<div data-with-frame="true"><figure><img src="/files/x8NNSxrg5BBCIhmqZv8F" alt=""><figcaption></figcaption></figure></div>

Check back on the Dual Stacking dashboard to stay current with your rewards and rewards composition. All rewards are distributed in sBTC, redeemable 1:1 for BTC anytime.
{% endstep %}
{% endstepper %}

***

Reach out to us on [Discord](https://discord.com/invite/stacks-621759717756370964) for any further questions regarding Dual Stacking.


# Dual Stack with Asigna

A guide in getting started with Dual Stacking using the Asigna wallet.

{% hint style="warning" %}
This guide is specifically for entities or teams that use [Asigna](https://www.asigna.io/). This assumes you have the Asigna wallet setup with its browser extension and a multi-signature setup.
{% endhint %}

The Dual Stacking Web App is the primary user interface for participating in Dual Stacking — a mechanism that allows Bitcoin holders to earn BTC-denominated rewards through sBTC, and maximize those rewards by either stacking STX or using sBTC in DeFi.

{% hint style="danger" %}
Ensure that you are using the official Dual Stacking app located at [app.stacks.co](https://app.stacks.co/).
{% endhint %}

For this guide, we'll walkthrough how you can use your Asigna wallet in enrolling Dual Stacking and participating in DeFi for boosted rewards. This guide assumes you have a dedicated Stacks vault setup with multi-signature in your Asigna wallet.

If you need assistance in setting up your vaults in Asigna, check out their dedicated [docs](https://asigna.gitbook.io/asigna).

Before enrolling in Dual Stacking, you'll need sBTC. Peg in BTC to sBTC through the [sBTC bridge](https://app.stacks.co/) (where it remains 1:1 Bitcoin-backed at all times). Check out the dedicated [guide](https://docs.stacks.co/build/sbtc/how-to-use-the-sbtc-bridge-with-asigna) on how you can mint sBTC to your Asigna wallet.

### Walkthrough for enrolling in Dual Stacking

Here are the necessary steps to enroll your sBTC using Asigna:

{% stepper %}
{% step %}
**Connect Asigna to the Dual Stacking app**

Upon popup of the connect wallet modal, select the Asigna option to connect with. As per the usual flow of connecting your Asigna wallet with other Stacks apps, you'll most likely also need to connect the Asigna web wallet view with the Asigna browser extension before connecting with the app.

<div data-with-frame="true"><figure><img src="/files/bRWxLLAmyKZADDaoeHT0" alt=""><figcaption><p>Select which safe (Stacks vault) you want to connect with.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Enroll now for Dual Stacking**

On the dashboard, you'll be able to see stats regarding your current sBTC in wallet, sBTC in DeFi, STX currently stacked, and estimated APY you could be earning.

Let's get started by enrolling your sBTC into Dual Stacking.

Your Asigna extension will appear with a popup asking you to review the transaction for approval. This will create the transaction which you will later sign and broadcast in your Asigna web wallet view.

<div data-with-frame="true"><figure><img src="/files/7nTwi0Ov8ajMb895H3s1" alt=""><figcaption><p>Click on 'Enroll now' under the 'Enroll for rewards' step and approve transaction in the extension popup.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Sign transaction in Asigna web view**

If you navigate back to your Asigna web wallet view, you'll see the transaction queued up for signatures. In this scenario, we have a 2-of-2 multi-signature scheme setup so we'll need to sign the transaction by both parties involved.

<div data-with-frame="true"><figure><img src="/files/KwATSpiKznxXYfF1Ps2O" alt=""><figcaption><p>The first signature of the 2-of-2 setup will need to be signed in the Asigna web wallet view.</p></figcaption></figure></div>

Once the first signature is completed, the second signature will also need to take place in that respective signer's Asigna web wallet view. After signing, that same signer will then need to hit 'Execute' to complete the broadcasting of the transaction.

<div data-with-frame="true"><figure><img src="/files/HshfCjtIiyKZ9CsgSVWR" alt=""><figcaption><p>The second signature of the 2-of-2 setup will need to be signed in the Asigna web wallet view. After all signatures are completed, hit 'Execute' to broadcast the transaction and navigate back to the Dual Stacking app.</p></figcaption></figure></div>

Execute the signed transaction to broadcast it to the Stacks network.

<div data-with-frame="true"><figure><img src="/files/Z4kDcUOveMpnjRc9bAXa" alt=""><figcaption></figcaption></figure></div>

Your enroll transaction will look like this [here](https://explorer.hiro.so/txid/0x3b4ea853df54825adad3ab475d93be18c6a12f04033c665d4597984786feb608?chain=mainnet).
{% endstep %}

{% step %}
**You are now enrolled in Dual Stacking**

You'll notice your sBTC now enrolled in Dual Stacking and when the rewards cycle will start for your enrolled sBTC.

<div data-with-frame="true"><figure><img src="/files/IRZUOMf87feLC5D0nzce" alt=""><figcaption><p>You are now Dual Stacking!</p></figcaption></figure></div>

The dashboard will also provide a view of your Dual Stacking portfolio.

<div data-with-frame="true"><figure><img src="/files/oeVqQdCeByhZEbdXbrLd" alt=""><figcaption></figcaption></figure></div>

<div data-with-frame="true"><figure><img src="/files/gwNRsRx0RbXywXylSY0N" alt=""><figcaption><p>View when your sBTC will start earning rewards and the breakdown of rewards composition.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Boost rewards by stacking STX**

So what's next? You could then boost your rewards by stacking STX. Let's start by stacking STX via [StackingDAO](https://www.stackingdao.com/). StackingDAO is a popular stacking option in Stacks as it is a liquid stacking method.

{% hint style="info" %}
There are other options for stacking your STX that you can find [here](https://app.leather.io/stacking).
{% endhint %}

Navigate to the StackingDAO embedded app within your Asigna web wallet view, connect your wallet, and start stacking. There are many methods to start liquid stacking or native stacking within StackingDAO. In this example, we'll use our STX to liquid stack with sBTC yield.

<div data-with-frame="true"><figure><img src="/files/kxgna2Sd2f4Tb0qdpQfz" alt=""><figcaption><p>Liquid stacking with sBTC yield allows us to stay liquid and earn sBTC while stacking.</p></figcaption></figure></div>

Complete the same 2-of-2 multi-signature flow in your Asigna web wallet views.

<div data-with-frame="true"><figure><img src="/files/dgcV3sMua2FJgWWNgO8W" alt=""><figcaption><p>After all signatures are completed, execute the transaction to broadcast it to the network.</p></figcaption></figure></div>

Navigate back to the Dual Stacking app, and you'll then notice the Dual Stacking app has instantly detect your stacked positions and include that as part of your portfolio's reward composition for boosted rewards.

<div data-with-frame="true"><figure><img src="/files/MbCaWAiJpiY7bEpMErDN" alt=""><figcaption><p>Notice the change in estimated APY and total portfolio value after stacking.</p></figcaption></figure></div>

Let's then boost reward with Stacks DeFi. This will help reach the maximum APY boost for your sBTC.
{% endstep %}

{% step %}
**Deploy your sBTC to Stacks DeFi protocols**

You'll notice near the bottom of the dashboard page, there is a section highlighting popular DeFi protocols in Stacks. Each one of these protocols are eligible for the boosted rewards you can realize.

<div data-with-frame="true"><figure><img src="/files/JLhtX6gjX5pSSrsrGqXp" alt=""><figcaption></figcaption></figure></div>

Let's deploy sBTC with Zest.

{% hint style="info" %}
As with using the embedded StackingDAO app, we'll also be using the embedded Zest app found in the Asigna web wallet view.
{% endhint %}

Supplying sBTC in Zest will provide users with a supply APY. Confirm the 'Supply' transaction via the same signature flow with Asigna.

<div data-with-frame="true"><figure><img src="/files/PNOMLEWhP3vyUIDUh92f" alt=""><figcaption></figcaption></figure></div>

After deploying sBTC into Zest, navigate back to the Dual Stacking web app to see your current estimated APY and rewards composition.

Check back on the Dual Stacking dashboard to stay current with your rewards and rewards composition. All rewards are distributed in sBTC, redeemable 1:1 for BTC anytime.
{% endstep %}
{% endstepper %}

***

Reach out to us on [Discord](https://discord.com/invite/stacks-621759717756370964) for any further questions regarding Dual Stacking.


# Dual Stack with Leather

A guide in getting started with Dual Stacking using the Leather wallet.

{% hint style="warning" %}
This guide is specifically for users that use the Leather wallet. This assumes you have the Leather wallet extension setup. The flow will also be similar for Xverse wallet users.
{% endhint %}

The Dual Stacking Web App is the primary user interface for participating in Dual Stacking — a mechanism that allows Bitcoin holders to earn BTC-denominated rewards through sBTC, and maximize those rewards by either stacking STX or using sBTC in DeFi.

{% hint style="danger" %}
Ensure that you are using the official Dual Stacking app located at [app.stacks.co](https://app.stacks.co/).
{% endhint %}

For this guide, we'll walkthrough how you can use your Leather wallet in enrolling Dual Stacking and participating in DeFi for boosted rewards. This guide assumes you have already setup a Leather wallet extension.

If you need assistance in setting up your Leather wallet extension, check out their webpage [here](https://leather.io/).

Before enrolling in Dual Stacking, you'll need sBTC. Peg in BTC to sBTC through the [sBTC bridge](https://app.stacks.co/) (where it remains 1:1 Bitcoin-backed at all times). Check out the dedicated [guide](https://docs.stacks.co/build/sbtc/how-to-use-the-sbtc-bridge) on how you can mint sBTC to your Leather wallet.

### Walkthrough for enrolling in Dual Stacking

Here are the necessary steps to enroll your sBTC using Leather:

{% stepper %}
{% step %}
**Connect Leather to the Dual Stacking app**

Upon popup of the connect wallet modal, select the Leather option to connect with.

<div data-with-frame="true"><figure><img src="/files/I4SiANEOhz78cIVrIyW0" alt=""><figcaption><p>Confirm connecting in your Leather modal popup.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Enroll now for Dual Stacking**

On the dashboard, you'll be able to see stats regarding your current sBTC in wallet, sBTC in DeFi, STX currently stacked, and estimated APY you could be earning.

<div data-with-frame="true"><figure><img src="/files/d4ksOU2UTsJeqH5xPYmN" alt=""><figcaption></figcaption></figure></div>

Let's get started by enrolling your sBTC into Dual Stacking.

<div data-with-frame="true"><figure><img src="/files/mpj9cYkb4Vq9m4tzyjH2" alt=""><figcaption></figcaption></figure></div>

Your Leather extension will appear with a popup asking you to review the transaction for approval. This will create the transaction which you will sign and broadcast in your Leather web wallet view.

Your enroll transaction will look like this [here](https://explorer.hiro.so/txid/0x3b4ea853df54825adad3ab475d93be18c6a12f04033c665d4597984786feb608?chain=mainnet).
{% endstep %}

{% step %}
**You are now enrolled in Dual Stacking**

You'll notice your sBTC now enrolled in Dual Stacking and when the rewards cycle will start for your enrolled sBTC.

<div data-with-frame="true"><figure><img src="/files/IRZUOMf87feLC5D0nzce" alt=""><figcaption><p>You are now Dual Stacking!</p></figcaption></figure></div>

The dashboard will also provide a view of your Dual Stacking portfolio. Track your balances, rewards and payouts at anytime.

<div data-with-frame="true"><figure><img src="/files/vdAFsO6DOoPwX81Ci5U9" alt=""><figcaption></figcaption></figure></div>

Use the Dual Stacking calculator for estimated rewards based on the ratio of sBTC in your wallet and STX stacked. For more details on your rewards are calculated and the math behind it, check out the section on the [reward function](/learn/dual-stacking/economic-model#reward-function-parameters).

<div data-with-frame="true"><figure><img src="/files/W6vHF862XL8Hp3OFpg9K" alt=""><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Boost rewards by stacking STX**

So what's next? You could then boost your rewards by stacking STX. Let's start by stacking STX via [StackingDAO](https://www.stackingdao.com/). StackingDAO is a popular stacking option in Stacks as it is a liquid stacking method.

{% hint style="info" %}
There are other options for stacking your STX that you can find [here](https://app.leather.io/stacking).
{% endhint %}

Navigate to the StackingDAO app, connect your wallet, and start stacking. There are many methods to start liquid stacking or native stacking within StackingDAO. In this example, we'll use our STX to liquid stack with sBTC yield.

<div data-with-frame="true"><figure><img src="/files/kxgna2Sd2f4Tb0qdpQfz" alt=""><figcaption><p>Liquid stacking with sBTC yield allows us to stay liquid and earn sBTC while stacking.</p></figcaption></figure></div>

Choose the amount in STX that you want to stack and click on 'Confirm Stack', your Leather wallet extension will then appear prompting you to approve transaction.

Navigate back to the Dual Stacking app, and you'll then notice the Dual Stacking app has instantly detect your stacked positions and include that as part of your portfolio's reward composition for boosted rewards.

<div data-with-frame="true"><figure><img src="/files/MbCaWAiJpiY7bEpMErDN" alt=""><figcaption><p>Notice the change in estimated APY and total portfolio value after stacking.</p></figcaption></figure></div>

Let's then boost reward with Stacks DeFi. This will help reach the maximum APY boost for your sBTC.
{% endstep %}

{% step %}
**Deploy your sBTC to Stacks DeFi protocols**

You'll notice near the bottom of the dashboard page, there is a section highlighting popular DeFi protocols in Stacks. Each one of these protocols are eligible for the boosted rewards you can realize.

<div data-with-frame="true"><figure><img src="/files/JLhtX6gjX5pSSrsrGqXp" alt=""><figcaption></figcaption></figure></div>

Let's deploy sBTC with Zest. Supplying sBTC in Zest will provide users with a supply APY. Confirm the 'Supply' transaction via the same signature flow using Leather.

<div data-with-frame="true"><figure><img src="/files/PNOMLEWhP3vyUIDUh92f" alt=""><figcaption></figcaption></figure></div>

After deploying sBTC into Zest, navigate back to the Dual Stacking web app to see your current estimated APY and rewards composition.

<div data-with-frame="true"><figure><img src="/files/vEio8QsoV2BI1rG1LqwR" alt=""><figcaption><p>View a breakdown of rewards per reward cycle.</p></figcaption></figure></div>

Check back on the Dual Stacking dashboard to stay current with your rewards and rewards composition. Depending on when your rewards cycle start for your enrollment, you'll see the rewards breakdown in the middle section. All rewards are distributed in sBTC, redeemable 1:1 for BTC anytime.
{% endstep %}
{% endstepper %}

***

Reach out to us on [Discord](https://discord.com/invite/stacks-621759717756370964) for any further questions regarding Dual Stacking.


# Economic Model

Understanding the economics behind Dual Stacking.

<div data-with-frame="true"><figure><img src="/files/vE7fsVUcDbdSrxaXz4dD" alt=""><figcaption></figcaption></figure></div>

Dual Stacking introduces an economic model in which BTC-denominated rewards scale with the participant’s ratio of sBTC to stacked STX as well as sBTC deployed in DeFi. This creates a direct link between Bitcoin capital and the growth of the Stacks ecosystem.

All participants receive a baseline BTC-denominated reward on the sBTC enrolled in Dual Stacking. They have the option of earning additional rewards by stacking STX as well as deploying sBTC into DeFi.

For Stacking STX, Bitcoin rewards grow based on an individuals STX-to-sBTC ratio relative to other participants, up to 10× the base yield. The system uses a square-root curve, meaning the first stacked STX has the greatest impact, with smaller boosts as more STX is stacked. The DeFi boost is straightforward, you automatically earn 10x multiple for any amount of sBTC deployed in DeFi.

At the same time, an individual's stacked STX continues earning standard [stacking](/learn/block-production/staking) rewards.

{% hint style="info" %}
The following Reward Function Parameters section is taken directly from the [Dual Stacking litepaper](https://github.com/stx-labs/papers/blob/main/Dual%20Stacking%20Litepaper.pdf).
{% endhint %}

#### Reward Function Parameters

* **Rewards Boost Multiplier** – Defines the maximum multiple of base reward attainable by users\
  with the highest STX/BTC ratio. For example, with a 10× multiplier, a user earning 0.5%\
  base reward could reach 5% if staking the maximum effective ratio of STX to BTC.
* **Reward Function Curve** – Defines how rewards scale across intermediate STX/BTC\
  ratios. A square-root curve introduces diminishing returns, encouraging broad\
  participation rather than concentration of rewards among large holders.
* **Max Reference STX/BTC Ratio** – Set to the BTC-weighted 95th percentile of STX/BTC\
  ratios among users. That is, the value above which only 5% of total locked BTC has a\
  higher STX/BTC ratio. Under this approach, for a user to unilaterally set the max\
  reference STX/BTC ratio, the user would need both 5% of the total BTC locked and have\
  the highest STX/BTC ratio for those BTC. This design minimizes manipulation by\
  preventing outliers from disproportionately setting the maximum yield threshold.

To describe the reward function more precisely, we’ll define some terms:

* 𝑌 − 𝑇𝑜𝑡𝑎𝑙 𝐵𝑇𝐶 𝑑𝑖𝑠𝑡𝑟𝑖𝑏𝑢𝑡𝑒𝑑 𝑎𝑠 𝑟𝑒𝑤𝑎𝑟𝑑𝑠 𝑡𝑜 𝑑𝑢𝑎𝑙 𝑠𝑡𝑎𝑐𝑘𝑖𝑛𝑔 𝑑𝑢𝑟𝑖𝑛𝑔 𝑎 𝑆𝑡𝑎𝑐𝑘𝑖𝑛𝑔 𝑐𝑦𝑐𝑙𝑒
* 𝐵<sub>𝑖</sub> − 𝐴𝑚𝑜𝑢𝑛𝑡 𝑜𝑓 𝐵𝑇𝐶 𝑡ℎ𝑒 𝑖𝑡ℎ 𝑢𝑠𝑒𝑟 𝑙𝑜𝑐𝑘𝑠 𝑖𝑛 𝑎 𝑆𝑡𝑎𝑐𝑘𝑖𝑛𝑔 𝑐𝑦𝑐𝑙𝑒
* 𝑆<sub>𝑖</sub> − 𝐴𝑚𝑜𝑢𝑛𝑡 𝑜𝑓 𝑆𝑇𝑋 𝑡ℎ𝑒 𝑖𝑡ℎ 𝑢𝑠𝑒𝑟 𝑙𝑜𝑐𝑘𝑠 𝑖𝑛 𝑎 𝑆𝑡𝑎𝑐𝑘𝑖𝑛𝑔 𝑐𝑦𝑐𝑙𝑒
* 𝑑<sub>𝑖</sub> = 𝑆<sub>𝑖</sub> */* 𝐵<sub>𝑖</sub> − 𝐴𝑚𝑜𝑢𝑛𝑡 𝑜𝑓 𝑆𝑇𝑋 𝑝𝑒𝑟 𝐵𝑇𝐶 𝑡ℎ𝑒 𝑖𝑡ℎ 𝑢𝑠𝑒𝑟 𝑙𝑜𝑐𝑘𝑠 𝑖𝑛 𝑎 𝑆𝑡𝑎𝑐𝑘𝑖𝑛𝑔 𝑐𝑦𝑐𝑙𝑒
* 𝐷 − 𝑀𝑎𝑥 𝑟𝑒𝑓𝑒𝑟𝑒𝑛𝑐𝑒 𝑑<sub>𝑖</sub> , 𝑤ℎ𝑖𝑐ℎ 𝑖𝑠 𝑠𝑒𝑡 𝑡𝑜 𝑡ℎ𝑒 95𝑡ℎ 𝑝𝑒𝑟𝑐𝑒𝑛𝑡𝑖𝑙𝑒 𝑜𝑓 𝐵𝑇𝐶𝑤𝑒𝑖𝑔ℎ𝑡𝑒𝑑 𝑑<sub>𝑖</sub>
* 𝑀 − 𝑟𝑒𝑤𝑎𝑟𝑑𝑠 𝑏𝑜𝑜𝑠𝑡 𝑚𝑢𝑙𝑡𝑖𝑝𝑙𝑖𝑒𝑟 𝑚𝑖𝑛𝑢𝑠 𝑜𝑛𝑒

The first step in our reward function is to determine a normalized ratio, 𝑟<sub>𝑖</sub> , for all users:

$$
𝑟\_𝑖 = 𝑚𝑖𝑛(\frac{𝑑\_𝑖}{𝐷}, 1)
$$

With the normalized ratio, we can then determine normalized weights, *w*<sub>𝑖</sub> , for all users:

$$
𝑤\_𝑖 = 𝐵\_𝑖\cdot(1 + 𝑀\cdot \sqrt{𝑟\_𝑖})
$$

Ultimately, the rewards for each user, *y*<sub>𝑖</sub> , would be:

$$
𝑦\_𝑖 = 𝑌 \cdot \frac{𝑤\_𝑖}{\sum𝑤\_𝑗}
$$

The generalized shape of the reward function is shown in the graph below. The two lines, one\
dark orange and one light orange, show the shape of the yield curves for the expected rewards on\
one’s sBTC holdings only as a result of dual stacking rewards, and the shape of the yield curve\
for one’s combined sBTC and STX as a result of the combination of dual stacking rewards on\
one’s sBTC and the standard stacking rewards for one’s STX.

<div data-with-frame="true"><figure><img src="/files/z9l36KW6Rxk1tesdRVcK" alt=""><figcaption><p>Staking STX alongside BTC amplifies rewards based on a yield curve, up to 10x.</p></figcaption></figure></div>

***

For more detail on the Reward Function parameters and models, refer to the [Dual Stacking litepaper](https://github.com/stx-labs/papers/blob/main/Dual%20Stacking%20Litepaper.pdf).


# Dual Stacking Smart Contract

## Overview

The Dual Stacking contract enables participants to earn boosted sBTC rewards by holding sBTC and optionally stacking STX. It operates in cycles with periodic snapshots to calculate rewards based on holdings and stacking participation.

{% hint style="info" %}
For the live dual stacking contract on mainnet, check out the contract page [here](https://explorer.hiro.so/txid/SP1HFCRKEJ8BYW4D0E3FAWHFDX8A25PPAA83HWWZ9.dual-stacking-v1?chain=mainnet).

On December 15, 2025, the dual stacking contract was upgraded to [`.dual-stacking-v2_0_2`](https://explorer.hiro.so/txid/SP1HFCRKEJ8BYW4D0E3FAWHFDX8A25PPAA83HWWZ9.dual-stacking-v2_0_2?chain=mainnet)
{% endhint %}

### Decentralized Architecture

* Permissionless operations: Anyone can execute critical cycle operations including snapshot capturing, ratio proposal/validation, weight calculation, and reward distribution.
* On-chain data only: All participant data (sBTC balances, STX stacking amounts) is read directly from the blockchain — no off-chain oracles or trusted data sources required.
* Competitive ratio discovery: Multiple participants can propose different golden ratios; the system validates based on mathematical criteria (95th percentile), not admin approval.
* Transparent execution: All operations are executed on-chain with verifiable results and public event logs.
* Self-service enrollment: Users can enroll, opt-out, and manage their participation independently.

### Main Operations

{% stepper %}
{% step %}
**Initialization**

The contract is initialized once with a Stacks block height parameter that is the first one in the Bitcoin block specified, or after it, in case there aren't any STX blocks anchored to it.
{% endstep %}

{% step %}
**Enrollment**

Users can self-enroll for participation with custom reward addresses. DeFi protocols can be enrolled by admin with custom tracking, stacking, and reward addresses. All participants can opt-out or change their addresses at any time.
{% endstep %}

{% step %}
**Snapshots and Cycles**

Anyone can trigger periodic snapshots that capture participant sBTC balances and STX stacking amounts from on-chain data based on predefined block intervals.
{% endstep %}

{% step %}
**Ratio Computation**

After snapshots are complete, anyone can propose a golden ratio (optimal STX/sBTC ratio), tally participant distributions, and validate if their proposal meets the 95th percentile criteria to determine the benchmark for maximum rewards.
{% endstep %}

{% step %}
**Weight Calculation**

Anyone can trigger participant weight calculations using the validated dual stacking formula that provides up to 10x boost (configurable) for those who meet or exceed the golden ratio.
{% endstep %}

{% step %}
**Rewards**

Anyone can trigger reward distribution every cycle based on calculated weights. Administrators can update configurations like APR, yield boost multiplier, snapshot length, and number of snapshots per cycle.
{% endstep %}

{% step %}
**Administrative Controls**

Admins maintain protocol parameters, enroll/opt-out DeFi protocols with special address configurations, manage whitelists and blacklists, and can perform emergency operations if needed.
{% endstep %}
{% endstepper %}

***

## Cycle Structure

* Each cycle consists of a fixed number of snapshots (default 14).
* Each snapshot occurs after a set number of Bitcoin blocks (default 150).
* The total cycle length is thus 2100 Bitcoin blocks by default (14 snapshots × 150 blocks).
* These defaults can be adjusted for production environments (e.g., 1 snapshot per day with appropriate block counts).

## Dual Stacking Formula

Weight Calculation:

$$
w\_i = \cfrac{\[B\_i \cdot (1 + M \cdot \sqrt{r\_i})]}{n}
$$

Where:

* *w*<sub>*i*</sub>*&#x20;= weight for user i*
* *B*<sub>*i*</sub>*&#x20;= sBTC balance of user i (sum across all snapshots)*
* *M = yield boost multiplier (default 9, meaning max boost of 10x)*
* *r*<sub>*i*</sub>*&#x20;= min(d*<sub>*i*</sub>*/D, 1), the ratio adjustment factor*
* *d*<sub>*i*</sub>*&#x20;= S*<sub>*i*</sub>*/B*<sub>*i*</sub>*, user's personal STX/sBTC ratio*
* *S*<sub>*i*</sub>*&#x20;= STX stacked by user i (sum across all snapshots)*
* *D = golden ratio (95th percentile STX/sBTC ratio across all participants)*
* *n = number of snapshots per cycle (default 14)*

Rewards Distribution:

$$
R\_i = (\frac{w\_i}{Σw}) \cdot Total Rewards
$$

Where:

* *R*<sub>*i*</sub>*&#x20;= reward for user i*
* *Σw = sum of all participant weights*
* *Total Rewards = min(pool balance, APR-based cap)*

Key Properties:

* *Participants with d*<sub>*i*</sub>*&#x20;≥ D receive maximum boost of (M+1) x (default 10x).*
* *Participants with d*<sub>*i*</sub>*&#x20;= 0 (no STX stacked) receive base rewards (1x).*
* *Boost scales with the square root of the ratio for intermediate values.*
* *Whitelisted DeFi tracking addresses automatically receive maximum boost without needing to stack STX.*
* *Weights are divided by the number of snapshots per cycle to normalize across the cycle duration.*

***

## Cycle Workflow

The Dual Stacking smart contract operates in cycles, each divided into snapshots. The process ensures accurate reward distribution through a series of permissionless operations that anyone can execute.

{% stepper %}
{% step %}
**Snapshot Phase (Anyone Can Execute)**

* capture-snapshot-balances: Anyone can capture balances for enrolled users after each snapshot.
* advance-to-next-snapshot: Anyone can transition to the next snapshot.
* finalize-snapshots: Anyone can conclude all snapshot data after the final snapshot.
  {% endstep %}

{% step %}
**Ratio Validation Phase (Competitive & Permissionless)**

* propose-golden-ratio: Anyone can propose a golden ratio.
* tally-participant-ratios: The proposer tallies participant ratios relative to their proposed ratio.
* validate-ratio: The proposer validates their proposal — succeeds only if it represents the 95th percentile.
* Multiple proposals can be submitted; the first valid one locks in for the cycle.
  {% endstep %}

{% step %}
**Weight Computation Phase (Anyone Can Execute)**

* calculate-participant-weights: Anyone can calculate participant weights using the dual stacking formula.
* finalize-weight-computation: Anyone can finalize weight computation.
  {% endstep %}

{% step %}
**Reward Distribution Phase (Anyone Can Execute)**

* set-is-distribution-enabled: Anyone can enable reward distribution by determining the available reward pool.
* distribute-rewards: Anyone can distribute rewards to enrolled users based on their weights.
* finalize-reward-distribution: Anyone can finalize reward distribution after all participants are rewarded.
  {% endstep %}

{% step %}
**Cycle Transition (Anyone Can Execute)**

* advance-to-next-cycle: Anyone can advance to the next cycle after all rewards are distributed.
  {% endstep %}
  {% endstepper %}

Note: All operations read data directly from the blockchain (sBTC balances from the sBTC token contract, STX stacking from native Stacks protocol). No off-chain data sources or trusted intermediaries are required.

***

## Public Functions

### 1. Contract Initialization

#### initialize-contract

Activates the contract with an initial cycle.

* Parameters: stx-block-height (uint)
* Assertions:
  * Current Bitcoin block height must be >= the configured cycle start Bitcoin block height.
  * The contract must not be active.
  * The Stacks block height must bracket the configured Bitcoin block height.
* Effect:
  * Initializes state variables for the first cycle and marks the contract as active.
  * Records cycle data and the first snapshot.

#### update-initialize-block

Updates the initialization Bitcoin block height before the contract is activated.

* Parameters: new-bitcoin-block-height (uint)
* Assertions:
  * Contract must not be active.
  * Caller must be the admin.
* Effect:
  * Updates the starting Bitcoin block height for the first cycle.

#### update-cycle-data-before-initialized

Updates both the snapshots per cycle and blocks per snapshot for the first cycle before initialization.

* Parameters: updated-snapshots-per-cycle (uint), updated-blocks-per-snapshot (uint)
* Assertions:
  * Contract must not be active.
  * Caller must be the admin.
* Effect:
  * Sets the cycle structure for the first cycle.

***

### 2. Enrollment

#### enroll

Enrolls the caller for rewards in future cycles.

* Parameters: rewarded-address (optional principal)
* Assertions:
  * Caller must not already be enrolled.
  * Caller must not be blacklisted.
  * Caller must hold at least the minimum required sBTC amount.
* Effect:
  * Adds the caller to the participants map with tracking, stacking, and rewarded addresses set appropriately.
  * Increments the next cycle participant count.

#### enroll-defi

Enrolls a DeFi protocol for rewards with custom addresses (admin only).

* Parameters:
  * defi-contract (principal)
  * tracking-address (principal)
  * rewarded-address (principal)
  * stacking-address (optional principal)
* Assertions:
  * Caller must be the admin.
  * DeFi contract must not already be enrolled.
  * DeFi contract must not be blacklisted.
* Effect:
  * Adds the DeFi protocol to the participants map with custom addresses.
  * Increments the next cycle participant count.

#### enroll-defi-batch

Batch enroll multiple DeFi protocols (admin only).

* Parameters: defi-contracts (list 900 {...})
* Assertions:
  * Caller must be the admin.
* Effect:
  * Enrolls multiple DeFi protocols in a single transaction.

#### opt-out

Allows the caller to opt out of participation in future cycles.

* Assertions:
  * Caller must be enrolled.
* Effect:
  * Removes the caller from the participants map.
  * Decrements the next cycle participant count.

#### opt-out-defi

Opts out a DeFi protocol from participation (admin only).

* Parameters: defi-contract (principal)
* Assertions:
  * Caller must be the admin.
  * DeFi contract must be enrolled.
* Effect:
  * Removes the DeFi protocol from the participants map.

#### opt-out-defi-batch

Batch opt out multiple DeFi protocols (admin only).

* Parameters: defi-contracts (list 200 principal)
* Assertions:
  * Caller must be the admin.
* Effect:
  * Opts out multiple DeFi protocols in a single transaction.

***

### 3. Participant Address Management

* change-reward-address
* change-reward-address-defi
* change-stacking-address-defi
* change-tracking-address-defi
* change-addresses-defi
* change-addresses-defi-batch

(Each function has parameters, admin assertions where applicable, and updates participant/DeFi addresses as described in the original spec.)

***

### 4. Snapshots and Cycles

#### capture-snapshot-balances

Captures snapshot balances for a list of participants at the current snapshot block height. Permissionless.

* Parameters: principals (list of up to 900 principals)
* Assertions:
  * The contract must be active.
  * The current snapshot Stacks block height must be available.
* Effect:
  * Reads sBTC balance from the sBTC token contract for each participant.
  * Reads STX stacked amount from native Stacks protocol (including liquid stacking if enabled).
  * Updates snapshot totals and participant holdings.
  * Tracks stacking and tracking addresses.

#### advance-to-next-snapshot

Advances the contract to the next snapshot within the current cycle. Permissionless.

* Parameters: new-stx-block-height (uint)
* Assertions:
  * The contract must be active.
  * All participants must be snapshotted.
  * Current Bitcoin block height must have reached the next snapshot block.
  * The cycle must not have ended.
  * The Stacks block height must bracket the next snapshot Bitcoin block height.
* Effect:
  * Increments snapshot index.
  * Aggregates snapshot totals into cycle totals.
  * Resets snapshot counters.
  * Records the new snapshot block heights.

#### finalize-snapshots

Finalizes all snapshots for the current cycle after the last snapshot is complete. Permissionless.

* Assertions:
  * The contract must be active.
  * Snapshots must not already be finalized.
  * Must be on the last snapshot of the cycle.
  * All participants must be snapshotted in the final snapshot.
* Effect:
  * Aggregates the final snapshot totals into cycle totals.
  * Marks snapshots as finalized.
  * Sets last operation state to "concluded".
  * Enables the ratio proposal phase.

#### advance-to-next-cycle

Advances the contract to the next cycle after all rewards are distributed. Permissionless.

* Parameters: stx-block-height (uint)
* Assertions:
  * The contract must be active.
  * Current Bitcoin block height must have reached the next cycle.
  * All participants must be rewarded.
  * Reward distribution must be finalized.
  * The Stacks block height must bracket the next cycle Bitcoin block height.
* Effect:
  * Increments cycle ID.
  * Resets state variables for the new cycle.
  * Updates cycle configuration from next-cycle settings.
  * Initializes the first snapshot of the new cycle.

***

### 5. Ratio Computation and Validation

#### propose-golden-ratio

Proposes a golden ratio for the current cycle. Permissionless.

* Parameters: ratio (uint) — proposed ratio scaled by 10^8
* Assertions:
  * Snapshots must be finalized.
  * A ratio must not already be validated for this cycle.
  * The caller must not have already proposed a ratio for this cycle.
* Effect:
  * Records the proposed ratio for the caller.
  * Initializes tracking for participant tallying.
  * Sets last operation state to "proposed-ratio".

#### change-proposed-golden-ratio

Change a previously proposed golden ratio before validation.

* Parameters: ratio (uint)
* Assertions:
  * The caller must have already proposed a ratio.
  * The ratio must not yet be validated.
* Effect:
  * Updates the proposed ratio and resets tally data.

#### tally-participant-ratios

Tallies how many participants have ratios above, below, or equal to the proposed golden ratio.

* Parameters: principals (list of up to 900 principals)
* Assertions:
  * The caller must have proposed a ratio.
  * The ratio must not yet be validated.
  * Must not have already tallied all participants.
* Effect:
  * Computes each participant's STX/sBTC ratio.
  * Tracks sBTC amounts above, below, and equal to the proposed ratio.
  * Increments participants counted.

#### validate-ratio

Validates that the proposed ratio represents the 95th percentile of participant ratios.

* Assertions:
  * The caller must have proposed a ratio.
  * All participants must be tallied.
  * The ratio must not already be validated.
  * If no STX is stacked by anyone, ratio must equal 1.0 (baseline).
  * sBTC above the ratio must be ≤ 5% of total sBTC.
  * sBTC at or above the ratio must be ≥ 5% of total sBTC.
* Effect:
  * Marks the ratio as validated.
  * Records the validated ratio for the cycle.
  * Sets last operation state to "ratio-validated".

#### set-max-percentage-above-ratio

Updates the percentage threshold for validation (admin only).

* Parameters: new-max-percentage-above-ratio (uint) — default 500 = 5%
* Assertions:
  * Caller must be the admin.
* Effect:
  * Updates the validation threshold.

***

### 6. Weight Computation

#### calculate-participant-weights

Calculates participant weights using the dual stacking formula. Permissionless.

* Parameters: principals (list of up to 900 principals)
* Assertions:
  * The ratio must be validated.
  * The current cycle Stacks block height must be available.
* Effect:
  * Retrieves validated golden ratio D.
  * Applies minimum threshold to D to prevent division by zero $$D = max(D, 10^-8)$$.
  * For each participant, computes weight using: $$w\_i = \cfrac{\[B\_i \cdot (1 + M \cdot √r\_i)]}{n}$$
  * Accumulates total weights in total-weights-sum.
  * Records individual weights per tracking address (not per enrolled address).

Notes:

* Multiple enrolled addresses sharing the same tracking address will share the same weight.
* Can be called in batches of up to 900 participants.

#### finalize-weight-computation

Finalizes the weight computation phase. Permissionless.

* Assertions:
  * The ratio must be validated.
  * Weights must not already be finalized.
  * All participants must have weights computed.
* Effect:
  * Marks weights as computed.
  * Sets last operation state to "weights-finalized".
  * Enables the reward distribution phase.

***

### 7. Reward Distribution

#### set-is-distribution-enabled

Prepares the contract to distribute rewards by determining the available reward pool. Permissionless.

* Assertions:
  * The contract must be active.
  * Distribution must not already be enabled.
  * Weights must be computed.
* Effect:
  * Reads the contract's sBTC balance.
  * Calculates rewards to distribute: min(pool balance, APR-based cap).
  * The cap is: $$(CPR × total-weights-sum) / (M + 1)$$
  * Marks rewards as ready for distribution.
  * Sets last operation state to "set-can-distribute".

#### distribute-rewards

Distributes rewards to participants based on their computed weights. Permissionless.

* Parameters: principals (list of up to 900 principals)
* Assertions:
  * Distribution must be enabled.
* Effect:
  * Calculates reward for each participant: (weight / total-weights) × total-rewards
  * Transfers sBTC rewards to rewarded addresses.
  * Marks participants as rewarded.
  * Aggregates rewards per rewarded address.

Notes:

* Can be called in batches of up to 900 participants.
* Multiple enrolled addresses sharing the same rewarded address aggregate rewards and only trigger one transfer per tracking address.

#### finalize-reward-distribution

Marks reward distribution as finalized for the current cycle. Permissionless.

* Assertions:
  * The contract must be active.
  * All participants must be rewarded.
  * Distribution must be enabled.
  * Must not already be finalized.
* Effect:
  * Records the finalization block height.
  * Sets last operation state to "finalized".
  * Enables cycle advancement.
  * Triggers external DeFi protocols to distribute their internal rewards (they monitor this finalization event).

***

### 8. Administrative Controls

* update-admin
* update-min-sbtc-hold-required-for-enrollment
* update-snapshot-length
* update-snapshots-per-cycle
* update-cycle-data
* update-bitcoin-blocks-per-year
* update-APR
* update-yield-boost-multiplier
* set-liquid-stacking
* emergency-withdraw-sbtc

(Each of the above has parameters, admin-only assertions where applicable, and effects described in the original spec. Notable constraints include APR bounds and multiplier bounds.)

***

### 9. Blacklist Management

* add-blacklisted
* add-blacklisted-batch
* remove-blacklisted
* remove-blacklisted-batch

(Admin-only operations to manage blacklist; adding an enrolled address auto opts it out.)

***

### 10. DeFi Whitelist Management

#### whitelist-defi-tracking

Adds a DeFi tracking address to the whitelist (gives maximum weight boost automatically).

* Parameters: defi-rewards-contract (principal)
* Assertions:
  * Caller must be the admin.
  * Address must not already be whitelisted.
* Effect:
  * Adds the tracking address to the whitelist.
  * Whitelisted addresses receive maximum boost (r<sub>i</sub> = 1.0) in weight calculations.
  * During snapshots, whitelisted addresses have their STX stacking recorded as 0 (they don't need to stack STX to receive max boost).

#### remove-whitelisted-defi-tracking

Removes a DeFi tracking address from the whitelist (admin only).

* Parameters: defi-rewards-contract (principal)
* Assertions:
  * Caller must be the admin.
  * Address must be whitelisted.
* Effect:
  * Removes the tracking address from the whitelist.

#### remove-whitelisted-defi-tracking-batch

Batch removes DeFi tracking addresses from the whitelist (admin only).

* Parameters: defi-rewards-contract (list 200 principal)
* Assertions:
  * Caller must be the admin.
* Effect:
  * Removes multiple tracking addresses from the whitelist.

***

## Private Functions

* update-snapshot-for-new-cycle: Resets snapshot counters and sets initial snapshot block heights.
* reset-state-for-cycle: Applies next-cycle configuration, resets flags and totals, records cycle data, updates participant count.
* capture-participant-balances: Reads sBTC and STX stacked at snapshot height, updates holdings and aggregates totals.
* calculate-participant-weight: Computes weight per tracking address using the dual stacking formula (integer math details in original spec).
* tally-user-ratio: Classifies a user's ratio relative to a proposed ratio and accumulates sBTC totals.
* distribute-reward-user: Transfers reward per tracking address and updates rewarded status.
* remove-participant: Deletes participant and decrements counts.
* enroll-defi-one / change-addresses-defi-one: helpers for batch operations.
* is-blacklisted: checks blacklist membership.

(Private functions implement the described effects and integer scaling considerations; refer to function details above for math/scaling behavior.)

***

## Read-Only Functions

### Cycle Information

* get-current-cycle-id
* cycle-data
* get-cycle-current-state
* current-overview-data
* get-yield-cycle-data
* nr-cycles-year
* cycle-percentage-rate

### Snapshot Information

* snapshot-data
* get-stacks-block-height-for-cycle-snapshot
* get-bitcoin-block-height-for-cycle-snapshot

### Reward Information

* get-reward-distribution-status
* is-distribution-ready
* reward-amount-for-cycle-and-address
* reward-amount-for-cycle-and-reward-address
* is-distribution-finalized-for-current-cycle
* get-distribution-finalized-at-height

### Ratio and Weight Information

* get-ratio-data
* get-weight-computation-status
* get-participant-weight

### Participant Information

* is-enrolled-in-next-cycle
* is-enrolled-this-cycle
* get-is-blacklisted
* get-is-blacklisted-list
* get-is-whitelisted-defi
* get-latest-reward-address
* get-participant-cycle-info

### State and Configuration

* get-last-operation-state
* get-admin
* get-is-contract-active
* get-current-bitcoin-block-height
* get-minimum-enrollment-amount
* get-next-action-bitcoin-height
* get-contract-sbtc-balance
* get-apr-data

### STX Stacking Queries

* get-amount-stx-stacked
* get-amount-stx-stacked-at-block-height
* get-amount-stacked-at-block-height
* get-amount-stacked-now


# FAQ

Clarifying some common questions and sharing external resources for Dual Stacking

#### General Dual Stacking Questions

<details>

<summary>Why can't other chains do this?</summary>

Other blockchains pay rewards in what they can mint (ETH, SOL, etc.). They have no mechanism to channel real Bitcoin.

Stacks has Proof of Transfer (PoX): Consensus mechanism that channels Bitcoin from miners to network participants. Operational since 2021. Over 4,000 BTC moved through PoX to date. This architectural difference makes Bitcoin earning Bitcoin rewards possible.

</details>

<details>

<summary>How is this different from wrapped BTC?</summary>

Rewards are paid in sBTC, redeemable for Bitcoin at any time and actual Bitcoin through PoX consensus, not platform tokens.

{% hint style="info" %}
**What is sBTC?**

sBTC is a [SIP-010](https://github.com/stacksgov/sips/blob/main/sips/sip-010/sip-010-fungible-token-standard.md) token on Stacks that can be converted back to BTC on Bitcoin. The key property of sBTC is its 1:1 peg to Bitcoin, meaning 1 sBTC is always equivalent to 1 BTC.
{% endhint %}

</details>

<details>

<summary>When is this live?</summary>

sBTC has been operational since December 2024. Dual Stacking launches November 2025.

{% hint style="info" %}
Coinciding with the Dual Stacking launch, the existing sBTC Rewards Program will sunset on October 31, 2024.
{% endhint %}

</details>

<details>

<summary>What will happen to the sBTC Rewards Program?</summary>

Coinciding with the Dual Stacking launch, the existing sBTC Rewards Program will sunset on October 31, 2024. But don’t worry, you can earn even more sBTC with Dual Stacking - a new way to stack both STX and sBTC to create stronger alignment between Bitcoin capital and the Stacks network.

**Key Dates to be aware of:**

Oct 30: Dual Stacking launches and you can enroll to start earning

Nov 4: sBTC Rewards Program ends and final rewards distributed

Nov 5: First Dual Stacking rewards cycle begins

Nov 20 (estimated): First Dual Stacking rewards cycle ends, rewards distributed\\

</details>

#### Dual Stacking Rewards

<details>

<summary>What are the minimum requirements?</summary>

The minimum to mint sBTC via the sBTC Bridge app is currently at 0.001 BTC (100,000 sats).

The minimum to enroll in Dual Stacking with your minted sBTC will be 0.0001 sBTC (10,000 sats).

Stacking STX is done normally through stacking pools, so no minimum. The Dual Stacking web app will auto-detect if a user is currently stacking STX.

</details>

<details>

<summary>Can I just stack BTC?</summary>

Yes, if you lock BTC only, you still earn base rewards. No STX required to participate.

</details>

<details>

<summary>Where does the yield come from?</summary>

Stacks is the only blockchain with Proof of Transfer—a consensus mechanism that channels BTC from miners to participants who secure the network by Stacking STX. At launch, Dual Stacking rewards will come from Stacks entities who volunteer their Stacking rewards (earned via Proof of Transfer) to Dual Stacking participants as sBTC.

</details>

<details>

<summary>How often are rewards paid out?</summary>

Rewards are paid out roughly every 2 weeks in line with PoX stacking cycles, with the first cycle beginning on November 5, 2025.

</details>

<details>

<summary>How are rewards calculated?</summary>

A Dual Stacking calculator is available in-app to help estimate your annual rewards based on the ratio of BTC/STX you are stacking. The system uses a square-root reward curve that creates diminishing returns, meaning your first STX paired with BTC has the biggest impact on your rewards, while additional STX continues to help at a decreasing rate. Review the [Dual Stacking Litepaper](https://github.com/stx-labs/papers/blob/main/Dual%20Stacking%20Litepaper.pdf) for more details.

</details>

<details>

<summary>How will this impact my existing Stacking rewards?</summary>

Dual Stacking does not modify PoX consensus, meaning there is no direct change to native Stacking rewards. No action is required to continue natively Stacking. Dual Stacking may indirectly impact stacking rewards by increasing more stacking participation overall.

</details>

#### Concerning Dual Stacking Security

<details>

<summary>What are the trust assumptions?</summary>

Dual Stacking operates as a transparent smart contract on the Stacks network. sBTC bridge operations are secured by a federation of [reputable signers](https://www.stacks.co/sbtc), with a 70% threshold of signer approval required for any transaction. No single entity can move funds unilaterally.

</details>

***

### Additional Resources

* [\[Twitter\]](https://x.com/andrerserrano/status/1977845457226178757) Dual Stacking Litepaper Announcement from Andre Serrano
* [\[Github\]](https://github.com/stx-labs/papers/blob/main/Dual%20Stacking%20Litepaper.pdf) Official Dual Stacking Litepaper
* [\[Stacks Forum\]](https://forum.stacks.org/t/stacks-economic-model-unlocking-bitcoin-capital-long-term-growth/18035#dual-stacking-aligning-btc-and-stx-incentives-3) Initial Dual Stacking Announcement
* [\[Stacks Official\]](https://www.stacks.co/dual-stacking) Dual Stacking landing page on stacks.co
* \[[Stacks Blog](https://www.stacks.co/blog/dual-stacking-launches-on-stacks)] Official blog announcement
* \[[Stacks Twitter](https://x.com/Stacks/status/1983900168954286342)] Official twitter announcement
* \[[Dual Stacking App](https://app.stacks.co/)] Official Dual Stacking App
* [\[Explorer\]](https://explorer.hiro.so/txid/SP1HFCRKEJ8BYW4D0E3FAWHFDX8A25PPAA83HWWZ9.dual-stacking-v1?chain=mainnet) `dual-stacking-v1` : Main Dual Stacking Contract


# Bridging

Exploring the plethora of ways to bridge assets to and from Stacks

<div data-with-frame="true"><figure><img src="/files/wUFnVs7DrjK1fJIgBLM2" alt=""><figcaption></figcaption></figure></div>

A blockchain bridge is a protocol or mechanism that serves as a connection between different blockchains, allowing for the transfer of tokens and data between them. Bridges enable the seamless transfer of data and assets between disparate blockchain networks. They break down the silos of individual blockchains and unlock the full potential of a permissionless, borderless Web3.

#### Explore the different bridges available with Stacks

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>USDCx</strong></td><td>Learn how USDC can flow to and from the bitcoin layer 2.</td><td><a href="/pages/hTy1qUMzinpAbk8IMhfB">/pages/hTy1qUMzinpAbk8IMhfB</a></td></tr></tbody></table>


# USDCx

USDCx is a 1:1 USDC-backed stablecoin issued through Circle xReserve and native to Stacks.

<div data-with-frame="true"><figure><img src="/files/wjA4UFQmINiYtjcevP77" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
Developer support for integrating USDCx bridging into applications will be available via Circle’s Bridge Kit SDK in Q1 2026.
{% endhint %}

Stacks now has a fully USDC-backed stablecoin that plugs directly into Circle’s multichain ecosystem and brings stable, interoperable dollar liquidity to Bitcoin’s leading Layer 2.

### What is USDCx?

USDCx is a 1:1 USDC-backed stablecoin issued through Circle xReserve and native to Stacks. It will exist as a SIP-010 token on Stacks.

Circle's xReserve provides cryptographic attestations for deposits and minting, while Circle Gateway and CCTP handle cross-chain movement. The result is USDC on Stacks without third-party bridges, wrapped assets, or fragmented liquidity.

{% hint style="info" %}
For more info on xReserve, check out the dedicated Circle docs [here](https://developers.circle.com/xreserve).
{% endhint %}

### Discover more of USDCx

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Operations</strong></td><td><a href="/pages/aDA3roByHhCXdtqoE7Pw">/pages/aDA3roByHhCXdtqoE7Pw</a></td></tr><tr><td><strong>Contracts</strong></td><td><a href="/pages/5euen0I7KPl2AzuMWXZi">/pages/5euen0I7KPl2AzuMWXZi</a></td></tr><tr><td><strong>Bridge App</strong></td><td><a href="/pages/Ech3VEAa5oTyzTxGGyCS">/pages/Ech3VEAa5oTyzTxGGyCS</a></td></tr><tr><td><strong>FAQ</strong></td><td><a href="/pages/JtJg99znUEacERUKqrLT">/pages/JtJg99znUEacERUKqrLT</a></td></tr></tbody></table>

***

### Security Audits

{% file src="/files/h8RStvkC0Qsovelv3P7e" %}

{% file src="/files/Bha4cQ2I5HkAVIQEuVeq" %}

***

### Additional Resources

* \[[Stacks Blog](https://www.stacks.co/blog/usdcx-launch-stacks-bitcoin-defi)] USDCx Launches on Stacks: Bitcoin Gets Its Top Tier Stablecoin
* \[[Circle Blog](https://www.circle.com/blog/usdcx-on-stacks-now-available-via-circle-xreserve)] USDCx on Stacks now available via Circle xReserve


# Operations

Let's walkthrough each of the operations that enable the bridging of USDC in and out of Stacks.

### Definitions

* **USDC**: Refers to native-chain USDC locked on the source chain that secures USDC-backed token at a 1-to-1 ratio.
* **xReserve smart contract**: Circle deploys and audits the xReserve contract on source blockchains such as Ethereum. It holds USDC deposited by users in reserve when a USDC-backed token is minted on Stacks
* **xReserve attestation service**: Operated by Circle. They monitor USDC deposits into the xReserve smart contract and sign deposit attestations. They also verify withdrawal attestations to release USDC.
* **Stacks attestation service**: Operated by Stacks. They monitor signed deposit attestations to trigger minting of USDCx on Stacks. In addition, they monitor burns of USDCx tokens to sign burn intents which are then forwarded to Circle's xReserve attestation service.
* **USDCx**: A SIP-010 token on Stacks fully backed by USDC.

### Deposits

<div data-with-frame="true"><figure><img src="/files/g1Eu50qzxw93UPdZP76y" alt=""><figcaption></figcaption></figure></div>

For bridging source-chain USDC into the Stacks network.

1. A user deposits USDC from their wallet app into an xReserve smart contract, managed by Circle, on the source chain.
2. The xReserve contract emits a deposit event and locks the funds, holding them in reserve.
3. The xReserve attestation service, managed by Circle, generates and signs a deposit attestation.
4. The Stacks network's attestation service fetches the signed deposit attestation.
5. The Stacks network mints USDC-backed tokens, USDCx, and emits a mint event.
6. The Stacks' USDCx token contract deposits the newly minted USDC-backed tokens into the user’s Stacks wallet.

After completing the deposit process, the user receives an equivalent amount of USDC-backed tokens on Stacks.

### Withdrawals

<div data-with-frame="true"><figure><img src="/files/qWZ4QdqxPjKA3rGyUdfO" alt=""><figcaption></figcaption></figure></div>

For withdrawing USDC from the Stacks network.

1. A user requests to burn USDCx tokens on Stacks and to withdraw USDC on the destination network.
2. The Stacks USDCx token contract burns their USDCx tokens and emits a burn event.
3. The Stacks network's attestation service monitors the burn emitted burn event and then signs a generated burn intent message offchain.
4. The Stacks network's attestation service passes the burn intent message and signature to xReserve, managed by Circle.
5. xReserve verifies the burn and issues a withdrawal attestation.
6. xReserve releases USDC to the user’s wallet on the destination network.

After completing the withdrawal process, the user receives USDC on the destination network.


# Contracts

The USDCx smart contract is deployed on Stacks. It's role mirrors native USDC behavior and verifies Circle’s deposit attestations for minting and emits burn events for redemption.

Below are the integral contracts that make up the USDCx architecture.

### Stacks

<table><thead><tr><th width="125.3046875">Network</th><th>USDCx token contract</th><th>USDC xReserve protocol (entrypoint)</th></tr></thead><tbody><tr><td>Mainnet</td><td><a href="https://explorer.hiro.so/txid/0x07ea0a8d7262acd0cb094006969527351883281e08ebb6535843c5dbbde31ce9?chain=mainnet">SP120SBRBQJ00MCWS7TM5R8WJNTTKD5K0HFRC2CNE.usdcx</a></td><td><a href="https://explorer.hiro.so/txid/0xb5f29114ecdbaf199887433cdd4ca46d177d60875141e1dfb67304b53bf2df11?chain=mainnet">SP120SBRBQJ00MCWS7TM5R8WJNTTKD5K0HFRC2CNE.usdcx-v1</a></td></tr><tr><td>Testnet</td><td><a href="https://explorer.hiro.so/txid/ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx?chain=testnet">ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx</a></td><td><a href="https://explorer.hiro.so/txid/ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx-v1?chain=testnet">ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx-v1</a></td></tr></tbody></table>

### Ethereum

<table><thead><tr><th width="103.1875">Network</th><th>USDC token contract</th><th>xReserve contract</th></tr></thead><tbody><tr><td>Mainnet</td><td><a href="https://etherscan.io/token/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48">0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48</a></td><td><a href="https://etherscan.io/address/0x8888888199b2Df864bf678259607d6D5EBb4e3Ce">0x8888888199b2Df864bf678259607d6D5EBb4e3Ce</a></td></tr><tr><td>Testnet</td><td><a href="https://sepolia.etherscan.io/token/0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238">0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238</a></td><td><a href="https://sepolia.etherscan.io/address/0x008888878f94C0d87defdf0B07f46B93C1934442">0x008888878f94C0d87defdf0B07f46B93C1934442</a></td></tr></tbody></table>


# usdcx-v1

{% code title=".usdcx-v1" lineNumbers="true" expandable="true" %}

```clarity
;; USDCx v1
;;
;; This contract implements the USDC xReserve protocol for bridging USDC between
;; Stacks and other chains.
;;
;; This contract is the main entry point for minting and burning USDCx.

;; An error occurred while recovering a deposit intent signature's
;; public key.
(define-constant ERR_UNABLE_TO_RECOVER_PK (err u100))
;; The length of the deposit intent is invalid.
(define-constant ERR_INVALID_DEPOSIT_BYTE_LENGTH (err u101))
;; The amount of the deposit intent is larger than u128::max.
(define-constant ERR_INVALID_DEPOSIT_AMOUNT_TOO_HIGH (err u102))
;; The max fee of the deposit intent is larger than u128::max.
(define-constant ERR_INVALID_DEPOSIT_MAX_FEE_TOO_HIGH (err u103))
;; The magic bytes of the deposit intent are invalid.
(define-constant ERR_INVALID_DEPOSIT_INTENT_MAGIC (err u104))
;; The hook data length of the deposit intent is invalid.
(define-constant ERR_INVALID_DEPOSIT_HOOK_DATA_LENGTH (err u105))
;; The signature of the deposit intent is invalid.
(define-constant ERR_INVALID_DEPOSIT_SIGNATURE (err u106))
;; The version of the deposit intent is invalid.
(define-constant ERR_INVALID_DEPOSIT_VERSION (err u107))
;; After accounting for fees, the amount of USDCx to mint is zero.
(define-constant ERR_INVALID_DEPOSIT_AMOUNT_ZERO (err u108))
;; The fee amount of the mint is larger than the max fee of the deposit intent.
(define-constant ERR_INVALID_DEPOSIT_FEE_AMOUNT_TOO_HIGH (err u109))
;; The remote domain of the deposit intent is invalid.
(define-constant ERR_INVALID_DEPOSIT_REMOTE_DOMAIN (err u110))
;; The remote token of the deposit intent is invalid.
(define-constant ERR_INVALID_DEPOSIT_REMOTE_TOKEN (err u111))
;; The remote recipient of the deposit intent is invalid.
(define-constant ERR_INVALID_DEPOSIT_REMOTE_RECIPIENT (err u112))
;; This nonce has already been used in a different deposit
(define-constant ERR_INVALID_DEPOSIT_NONCE (err u113))
;; The max fee is greater than or equal to the amount.
(define-constant ERR_INVALID_DEPOSIT_MAX_FEE_GTE_AMOUNT (err u114))
;; The remote recipient length of the deposit intent is invalid.
(define-constant ERR_INVALID_DEPOSIT_REMOTE_RECIPIENT_LENGTH (err u115))
;; The withdrawal amount is less than the minimum withdrawal amount.
(define-constant ERR_INVALID_WITHDRAWAL_AMOUNT_TOO_LOW (err u116))
;; The native domain is not the supported value (currently only 0)
(define-constant ERR_INVALID_NATIVE_DOMAIN (err u117))

;; Magic bytes for deposit encoding
(define-constant DEPOSIT_INTENT_MAGIC 0x5a2e0acd)

;; Supported version for parsing deposit intents
(define-constant DEPOSIT_INTENT_VERSION u1)

;; Supported native-domain for withdrawals
(define-constant ETHEREUM_NATIVE_DOMAIN u0)

;; Allowed `domain` for deposits
(define-constant DOMAIN u10003)

;; Map of used nonces
(define-map used-nonces
  (buff 32)
  bool
)

;; Map of Circle attestor public keys
(define-map circle-attestors
  (buff 33)
  bool
)

;; Minimum amount required to withdrawal USDCx
(define-data-var min-withdrawal-amount uint u0)

;; Helper function to parse a deposit intent from raw bytes.
;; This function takes care of parsing the deposit intent according to the Circle specification.
;; Stacks-specific logic (such as converting the remote recipient to a principal) is handled by other functions.
;;
;; For full validation, including parsing the remote recipient and preventing nonce reuse, use
;; `parse-and-validate-deposit-intent`.
(define-read-only (parse-deposit-intent (deposit-intent (buff 320)))
  (begin
    (asserts! (>= (len deposit-intent) u240) ERR_INVALID_DEPOSIT_BYTE_LENGTH)
    (let (
        (magic (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u0 u4)) u4)))
        (version (buff-to-uint-be (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u4 u8)) u4))))
        (amount-left-bytes (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u8 u24)) u16)))
        (amount (buff-to-uint-be (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u24 u40)) u16))))
        (remote-domain (buff-to-uint-be (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u40 u44)) u4))))
        (remote-token (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u44 u76)) u32)))
        (remote-recipient (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u76 u108)) u32)))
        (local-token (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u108 u140)) u32)))
        (local-depositor (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u140 u172)) u32)))
        (max-fee-left-bytes (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u172 u188)) u16)))
        (max-fee (buff-to-uint-be (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u188 u204)) u16))))
        (nonce (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u204 u236)) u32)))
        (hook-data-len (buff-to-uint-be (unwrap-panic (as-max-len? (unwrap-panic (slice? deposit-intent u236 u240)) u4))))
      )
      (asserts! (is-eq magic DEPOSIT_INTENT_MAGIC)
        ERR_INVALID_DEPOSIT_INTENT_MAGIC
      )
      (asserts! (is-eq amount-left-bytes 0x00000000000000000000000000000000)
        ERR_INVALID_DEPOSIT_AMOUNT_TOO_HIGH
      )
      (asserts! (is-eq max-fee-left-bytes 0x00000000000000000000000000000000)
        ERR_INVALID_DEPOSIT_MAX_FEE_TOO_HIGH
      )
      (asserts! (is-eq (len deposit-intent) (+ u240 hook-data-len))
        ERR_INVALID_DEPOSIT_HOOK_DATA_LENGTH
      )
      (ok {
        magic: magic,
        version: version,
        amount: amount,
        remote-domain: remote-domain,
        remote-token: remote-token,
        remote-recipient: remote-recipient,
        local-token: local-token,
        local-depositor: local-depositor,
        max-fee: max-fee,
        nonce: nonce,
        hook-data: (if (is-eq hook-data-len u0)
          0x
          (unwrap-panic (as-max-len?
            (unwrap-panic (slice? deposit-intent u240 (+ u240 hook-data-len)))
            u80
          ))
        ),
      })
    )
  )
)

;; Recover the attestor public key from a deposit intent and signature.
;; Recovery is done by hashing the deposit intent (via `keccak256`)
;; and then using the `secp256k1-recover?` function.
(define-read-only (recover-deposit-intent-pk
    (deposit-intent (buff 320))
    (signature (buff 65))
  )
  (let (
      (hash (keccak256 deposit-intent))
      (recovered-pk (unwrap! (secp256k1-recover? hash signature) ERR_UNABLE_TO_RECOVER_PK))
    )
    (ok recovered-pk)
  )
)

;; Add or remove a Circle attestor.
;;
;; Can only be called by a caller with the governance role.
(define-public (add-or-remove-circle-attestor
    (public-key (buff 33))
    (enabled bool)
  )
  (begin
    ;; #[filter(public-key, enabled)]
    (try! (contract-call? .usdcx validate-protocol-caller 0x00 contract-caller))
    (map-set circle-attestors public-key enabled)
    (ok true)
  )
)

;; Recover and verify a deposit intent signature.
;;
;; The public key is first recovered (via `recover-deposit-intent-pk`).
;; Then, the public key is checked against the `circle-attestors` map.
(define-read-only (verify-deposit-intent-signature
    (deposit-intent (buff 320))
    (signature (buff 65))
  )
  (begin
    ;; #[filter(deposit-intent, signature)]
    (let ((recovered-pk (try! (recover-deposit-intent-pk deposit-intent signature))))
      (asserts! (default-to false (map-get? circle-attestors recovered-pk))
        ERR_INVALID_DEPOSIT_SIGNATURE
      )
      (ok recovered-pk)
    )
  )
)

;; Convert 32 bytes to a standard principal. This is serialized as
;; 1 version byte, plus 20 hash bytes. This is then left-padded
;; with 11 bytes of 0x00.
;;
;; To support contracts as recipients, `hook-data` can contain a contract name.
;; To use this functionality, `hook-data` MUST be a consensus-serialized buffer
;; of the type { contract-name: (string-ascii 40) }.
;;
;; If `hook-data` is not able to be deserialized, this function falls back
;; to using a standard principal.
(define-read-only (get-remote-recipient
    (remote-recipient-bytes (buff 32))
    (hook-data (buff 80))
  )
  (let (
      (valid-len (asserts! (is-eq (len remote-recipient-bytes) u32)
        ERR_INVALID_DEPOSIT_REMOTE_RECIPIENT_LENGTH
      ))
      (version-byte (unwrap-panic (element-at? remote-recipient-bytes u11)))
      (hash-bytes (unwrap-panic (as-max-len? (unwrap-panic (slice? remote-recipient-bytes u12 u32)) u20)))
      ;; Avoid a VM runtime error when `hook-data` is empty:
      (hook-contract-name (if (is-eq (len hook-data) u0)
        none
        (from-consensus-buff? { contract-name: (string-ascii 40) } hook-data)
      ))
    )
    ;; Must have 0x00 as padding
    (asserts!
      (is-eq
        (unwrap-panic (as-max-len? (unwrap-panic (slice? remote-recipient-bytes u0 u11)) u11))
        0x0000000000000000000000
      )
      ERR_INVALID_DEPOSIT_REMOTE_RECIPIENT
    )
    (ok (unwrap!
      (match hook-contract-name
        contract-name-tup (principal-construct? version-byte hash-bytes
          (get contract-name contract-name-tup)
        )
        (principal-construct? version-byte hash-bytes)
      )
      ERR_INVALID_DEPOSIT_REMOTE_RECIPIENT
    ))
  )
)

;; 32-byte encoded version of the `.usdcx` contract address.
;; This must be used in deposit intents as the `remote-token` field.
(define-read-only (get-valid-remote-token)
  (concat 0x00000000
    (unwrap-panic (as-max-len? (unwrap-panic (to-consensus-buff? .usdcx)) u28))
  )
)

;; Helper function to parse and validate a deposit intent.
;;
;; In addition to basic parsing (done via `parse-deposit-intent`), this function
;; also validates certain Stacks-specific fields, such as the
;; remote token, remote domain, remote recipient, and version.
;;
;; Additionally, this function validates the `amount` and `max-fee` fields.
(define-read-only (parse-and-validate-deposit-intent (deposit-intent (buff 320)))
  (let (
      (parsed-intent (try! (parse-deposit-intent deposit-intent)))
      (remote-recipient (try! (get-remote-recipient (get remote-recipient parsed-intent)
        (get hook-data parsed-intent)
      )))
      (amount (get amount parsed-intent))
    )
    (asserts! (is-eq (get remote-token parsed-intent) (get-valid-remote-token))
      ERR_INVALID_DEPOSIT_REMOTE_TOKEN
    )
    (asserts! (> amount u0) ERR_INVALID_DEPOSIT_AMOUNT_ZERO)
    (asserts! (is-eq (get remote-domain parsed-intent) DOMAIN)
      ERR_INVALID_DEPOSIT_REMOTE_DOMAIN
    )
    (asserts! (is-eq (get version parsed-intent) DEPOSIT_INTENT_VERSION)
      ERR_INVALID_DEPOSIT_VERSION
    )
    (asserts! (>= amount (get max-fee parsed-intent))
      ERR_INVALID_DEPOSIT_MAX_FEE_GTE_AMOUNT
    )
    (asserts! (is-none (map-get? used-nonces (get nonce parsed-intent)))
      ;; This nonce has already been used in a different deposit
      ERR_INVALID_DEPOSIT_NONCE
    )
    (ok (merge parsed-intent { remote-recipient: remote-recipient }))
  )
)

;; Mint USDCx using a deposit intent.
;; This is the main entry point for minting USDCx.
;;
;; In addition to validation performed by `parse-and-validate-deposit-intent`, and
;; `verify-deposit-intent-signature`, this function also validates the `fee-amount`
;; provided by the caller to ensure that zero-amount mints are not possible.
;;
;; If `fee-amount` is non-zero (and less than the deposit's `max-fee`),
;; this function will mint `fee-amount` of USDCx to the caller. This allows
;; for accounts other than the deposit's recipient to cover the STX fee needed to mint.
(define-public (mint
    (deposit-intent (buff 320))
    (signature (buff 65))
    (fee-amount uint)
  )
  (let (
      (parsed-intent (try! (parse-and-validate-deposit-intent deposit-intent)))
      (recovered-pk (try! (verify-deposit-intent-signature deposit-intent signature)))
      (mint-amount (- (get amount parsed-intent) fee-amount))
    )
    (asserts! (>= (get max-fee parsed-intent) fee-amount)
      ERR_INVALID_DEPOSIT_FEE_AMOUNT_TOO_HIGH
    )
    ;; mint to the recipient
    (if (is-eq mint-amount u0)
      true
      (try! (contract-call? .usdcx protocol-mint mint-amount
        (get remote-recipient parsed-intent)
      ))
    )
    (if (is-eq fee-amount u0)
      true
      (try! (contract-call? .usdcx protocol-mint fee-amount tx-sender))
    )
    (map-set used-nonces (get nonce parsed-intent) true)
    (print {
      topic: "mint",
      parsed-intent: parsed-intent,
      attestor-pk: recovered-pk,
      mint-amount: mint-amount,
      fee-amount: fee-amount,
    })
    (ok true)
  )
)

;; Set the minimum withdrawal amount.
;;
;; Can only be called by a caller with the custom role `0x04` role.
(define-public (set-min-withdrawal-amount (new-min-withdrawal-amount uint))
  (begin
    (try! (contract-call? .usdcx validate-protocol-caller 0x04 contract-caller))
    (var-set min-withdrawal-amount new-min-withdrawal-amount)
    (ok true)
  )
)

(define-read-only (get-min-withdrawal-amount)
  (var-get min-withdrawal-amount)
)

;; Burn USDCx for the purpose of withdrawing USDCx from the protocol.
;;
;; This function burns USDCx from the caller's account and emits a `burn` event.
;;
;; The amount must be greater than or equal to the minimum withdrawal amount.
;;
;; `native-domain` must be a supported value (currently only `ETHEREUM_NATIVE_DOMAIN` (u0)).
(define-public (burn
    (amount uint)
    (native-domain uint)
    (native-recipient (buff 32))
  )
  (begin
    (asserts! (>= amount (var-get min-withdrawal-amount))
      ERR_INVALID_WITHDRAWAL_AMOUNT_TOO_LOW
    )
    (asserts! (is-eq native-domain ETHEREUM_NATIVE_DOMAIN)
      ERR_INVALID_NATIVE_DOMAIN
    )
    (try! (contract-call? .usdcx protocol-burn amount tx-sender))
    (print {
      topic: "burn",
      native-domain: native-domain,
      native-recipient: native-recipient,
      sender: tx-sender,
      amount: amount,
    })
    (ok true)
  )
)

```

{% endcode %}

## **USDCx-v1 Contract Summary**

The `usdcx-v1` contract implements the **USDC xReserve protocol** for moving USDC between Stacks and external chains. It serves as the **primary entry point for minting and burning USDCx** based on Circle-issued deposit intents.

This contract handles:

* Parsing and validating deposit intent payloads
* Recovering and verifying Circle attestor signatures
* Enforcing nonce-based replay protection
* Minting USDCx through the `usdcx` token contract
* Burning USDCx to initiate withdrawals
* Managing Circle attestor keys
* Handling Stacks-specific recipient conversions
* Applying fee logic for sponsored mints
* Managing minimum withdrawal thresholds

It works in tandem with the main `usdcx` token contract, which enforces protocol roles (`mint`, `governance`, etc.). All minting/burning occurs through `protocol-mint` and `protocol-burn`.

### Minting USDCx

The entry point for minting USDCx is via the `mint` function. The caller provides a serialized deposit intent, along with a signature, both of which are received off-chain as part of the bridging process. The deposit intent is parsed according to the xReserve specificiation.

There are a few Stacks-specific elements:

* The `remote-token` of the deposit intent MUST be the consensus-serialized bytes of the principal `.usdcx` (where the deployer address is network-dependent), with 0x left-padded.
* The `remote-domain` for Stacks is always `10003`.
* Because Stacks only supports `u128` integers, the deserialization functions throw an error if any 64-byte integers in the deposit intent are larger than `u128::max`. This is allowed according to the xReserve spec.

### **Verifying attestations**

The `.usdcx-v1` contract keeps a `circle-attestors` map to keep track of public keys of valid attestors. When a deposit intent is provided, it must be signed by a public key in this map.

### Burning USDCx

To withdrawal USDCx to another chain, users call `burn`. The specified amount of USDCx is burned from their Stacks account. A `print` event is emitted, which is used for triggering a burn attestation off-chain.

The `.usdcx-v1` contract stores a minimum amount variable. Users must withdraw at least this amount, or the burn fails. Accounts with the role `0x04` can update this variable.


# usdcx-token

{% code title=".usdcx" lineNumbers="true" expandable="true" %}

```clarity
;; USDCx token
;;
;; This contract implements the SIP-010 trait for fungible contracts.
;;
;; This contract utilizes a role-based access control system to manage protocol permissions.
;; There are three roles:
;;
;; - `governance`: Allowed to update the protocol contracts and add/remove roles
;; - `mint`: Allowed to mint and burn tokens
;; - `pause`: Allowed to pause and unpause the protocol
;;

(impl-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)

;; `tx-sender` or `contract-caller` tried to move a token it does not own.
(define-constant ERR_NOT_OWNER (err u4))
;; `contract-caller` tried to use a function it is not authorized to use.
(define-constant ERR_UNAUTHORIZED (err u400))
;; Protocol is paused.
(define-constant ERR_PAUSED (err u401))

(define-fungible-token usdcx-token)

(define-data-var token-name (string-ascii 32) "USDCx")
(define-data-var token-symbol (string-ascii 10) "USDCx")
;; The SIP-16 URI for token metadata
(define-data-var token-uri (optional (string-utf8 256)) (some u"https://ipfs.io/ipfs/bafkreifkhq47bgrlq2z2qgtps65eawgp6xsqkwldz57y2bjpefgo5zvza4"))
(define-constant token-decimals u6)

;; Allowed to update the protocol contracts
(define-constant governance-role 0x00)
;; Allowed to mint and burn tokens
(define-constant mint-role 0x01)
;; Allowed to pause and unpause the protocol
(define-constant pause-role 0x02)

;; Allow protocol to be paused
(define-data-var paused bool false)

;; Mapping of active protocol contracts (by role)
(define-map active-protocol-contracts
  {
    caller: principal,
    role: (buff 1),
  }
  bool
)

;; The contract .usdcx-v1 automatically has the `mint` role
(map-set active-protocol-contracts {
  caller: .usdcx-v1,
  role: mint-role,
}
  true
)
;; Default the contract deployer as having the `governance` role
(map-set active-protocol-contracts {
  caller: tx-sender,
  role: governance-role,
}
  true
)

;; SIP-010 functions

(define-public (transfer
    (amount uint)
    (sender principal)
    (recipient principal)
    (memo (optional (buff 34)))
  )
  (begin
    (asserts! (or (is-eq tx-sender sender) (is-eq contract-caller sender))
      ERR_NOT_OWNER
    )
    (try! (ft-transfer? usdcx-token amount sender recipient))
    (match memo
      to-print (print to-print)
      0x
    )
    (ok true)
  )
)

(define-read-only (get-name)
  (ok (var-get token-name))
)

(define-read-only (get-symbol)
  (ok (var-get token-symbol))
)

(define-read-only (get-decimals)
  (ok token-decimals)
)

(define-read-only (get-balance (who principal))
  (ok (ft-get-balance usdcx-token who))
)

(define-read-only (get-balance-available (who principal))
  (ok (ft-get-balance usdcx-token who))
)

(define-read-only (get-balance-locked (who principal))
  (ok (ft-get-balance usdcx-token who))
)

(define-read-only (get-total-supply)
  (ok (ft-get-supply usdcx-token))
)

(define-read-only (get-token-uri)
  (ok (var-get token-uri))
)

;; Protocol caller validation

;; Checks whether the contract-caller is a protocol contract
(define-read-only (is-protocol-caller
    (contract-flag (buff 1))
    (contract principal)
  )
  (validate-protocol-caller contract-flag contract)
)

;; Validate that a given principal is a protocol contract
(define-read-only (validate-protocol-caller
    (contract-flag (buff 1))
    (contract principal)
  )
  (begin
    ;; Check that the caller has the required role
    (asserts!
      (default-to false
        (map-get? active-protocol-contracts {
          caller: contract,
          role: contract-flag,
        })
      )
      ERR_UNAUTHORIZED
    )
    (ok true)
  )
)

;; Protocol pausing

(define-read-only (is-protocol-paused)
  (var-get paused)
)

;; Validate that protocol is not paused
(define-read-only (validate-protocol-active)
  (ok (asserts! (not (is-protocol-paused)) ERR_PAUSED))
)

;; --- Protocol functions

;; Transfer tokens from one account to another.
;; Only the `mint` role is allowed to call this function.
(define-public (protocol-transfer
    (amount uint)
    (sender principal)
    (recipient principal)
  )
  (begin
    ;; #[filter(amount, sender, recipient)]
    (try! (validate-protocol-active))
    (try! (validate-protocol-caller mint-role contract-caller))
    (ft-transfer? usdcx-token amount sender recipient)
  )
)

;; Mint tokens to an account.
;; Only the `mint` role is allowed to call this function.
(define-public (protocol-mint
    (amount uint)
    (recipient principal)
  )
  (begin
    ;; #[filter(amount, recipient)]
    (try! (validate-protocol-active))
    (try! (validate-protocol-caller mint-role contract-caller))
    (ft-mint? usdcx-token amount recipient)
  )
)

;; Burn tokens from an account.
;; Only the `mint` role is allowed to call this function.
(define-public (protocol-burn
    (amount uint)
    (owner principal)
  )
  (begin
    ;; #[filter(amount, owner)]
    (try! (validate-protocol-active))
    (try! (validate-protocol-caller mint-role contract-caller))
    (ft-burn? usdcx-token amount owner)
  )
)

;; Set the name of the token.
;; Only the `governance` role is allowed to call this function.
(define-public (protocol-set-name (new-name (string-ascii 32)))
  (begin
    ;; #[filter(new-name)]
    (try! (validate-protocol-active))
    (try! (validate-protocol-caller governance-role contract-caller))
    (ok (var-set token-name new-name))
  )
)

;; Set the symbol of the token.
;; Only the `governance` role is allowed to call this function.
(define-public (protocol-set-symbol (new-symbol (string-ascii 10)))
  (begin
    ;; #[filter(new-symbol)]
    (try! (validate-protocol-active))
    (try! (validate-protocol-caller governance-role contract-caller))
    (ok (var-set token-symbol new-symbol))
  )
)

;; Set the SIP-16 URI for token metadata.
;; Only the `governance` role is allowed to call this function.
(define-public (protocol-set-token-uri (new-uri (optional (string-utf8 256))))
  (begin
    ;; #[filter(new-uri)]
    (try! (validate-protocol-active))
    (try! (validate-protocol-caller governance-role contract-caller))
    (ok (var-set token-uri new-uri))
  )
)

;; Helper function to mint tokens to multiple recipients.
;; Only the `mint` role is allowed to call this function.
(define-private (protocol-mint-many-iter (item {
  amount: uint,
  recipient: principal,
}))
  ;; #[allow(unchecked_data)]
  (ft-mint? usdcx-token (get amount item) (get recipient item))
)

;; Mint tokens to multiple recipients.
;; Only the `mint` role is allowed to call this function.
(define-public (protocol-mint-many (recipients (list 200 {
  amount: uint,
  recipient: principal,
})))
  (begin
    ;; #[filter(recipients)]
    (try! (validate-protocol-active))
    (try! (validate-protocol-caller mint-role contract-caller))
    (ok (map protocol-mint-many-iter recipients))
  )
)

;; Set an active protocol caller.
;; Only the `governance` role is allowed to call this function.
(define-public (set-active-protocol-caller
    (caller principal)
    (role (buff 1))
    (enabled bool)
  )
  (begin
    ;; #[filter(caller, role, enabled)]
    (try! (validate-protocol-active))
    (try! (validate-protocol-caller governance-role contract-caller))
    (map-set active-protocol-contracts {
      caller: caller,
      role: role,
    }
      enabled
    )
    (ok true)
  )
)

;; Pause the protocol.
;; Only the `pause` role is allowed to call this function.
(define-public (pause)
  (begin
    (try! (validate-protocol-caller pause-role contract-caller))
    (print {
      topic: "pause",
      paused: true,
      caller: contract-caller,
    })
    (ok (var-set paused true))
  )
)

;; Unpause the protocol.
;; Only the `pause` role is allowed to call this function.
(define-public (unpause)
  (begin
    (try! (validate-protocol-caller pause-role contract-caller))
    (print {
      topic: "pause",
      paused: false,
      caller: contract-caller,
    })
    (ok (var-set paused false))
  )
)

```

{% endcode %}

## **USDCx-Token Contract Summary**

This contract implements **USDCx**, a SIP-010 fungible token on Stacks with a **role-based access control system** and **pause functionality** for protocol safety. It exposes the standard SIP-010 interface for transfers, supply queries, and metadata, while providing protocol-only functions for minting, burning, governance updates, and pausing.

#### **Roles**

The contract defines three privileged roles:

* **Governance (`governance-role`)** – manages protocol configuration, updates token metadata, and assigns roles.
* **Mint (`mint-role`)** – authorized to mint, burn, and perform protocol-level transfers.
* **Pause (`pause-role`)** – authorized to pause and unpause the protocol.

A protocol pause halts state-changing operations for safety. The contract deployer automatically receives the **governance** role. The companion contract `.usdcx-v1` automatically receives the **mint** role.

***

### Function-by-Function Breakdown

### **SIP-010 Standard Functions**

#### **`transfer(amount, sender, recipient, memo)`**

Transfers USDCx between principals, following SIP-010 rules. The function checks that the sender is either `tx-sender` or `contract-caller` (for contracts managing escrow or vaults) and then performs the transfer. An optional memo is logged on-chain.

#### **`get-name()`**, **`get-symbol()`**, **`get-decimals()`**

Standard SIP-010 metadata getters returning token name, symbol, and decimal precision.

#### **`get-balance(who)`**, **`get-balance-available(who)`**, **`get-balance-locked(who)`**

Returns the token balance for the given principal. In this implementation, all three accessor functions return the same SIP-010 balance value.

#### **`get-total-supply()`**

Returns the total USDCx supply minted minus burned.

#### **`get-token-uri()`**

Returns the token metadata URI.

***

### **Protocol Caller Validation**

These functions enforce the contract’s role-based permissions.

#### **`is-protocol-caller(role, contract)`**

Checks whether the specified contract principal holds the required role.

#### **`validate-protocol-caller(role, contract)`**

Ensures the caller has the correct role. If not, returns `ERR_UNAUTHORIZED`.

#### **`is-protocol-paused()`**

Returns whether the protocol is currently paused.

#### **`validate-protocol-active()`**

Asserts that the protocol is not paused, otherwise returns `ERR_PAUSED`.

***

### **Protocol-Only Token Operations**

These functions enable minting/burning/transfers strictly for authorized protocol contracts.

#### **`protocol-transfer(amount, sender, recipient)`**

Performs a protocol-level transfer on behalf of another contract. Only callers with the **mint role** can use it. Fails if the protocol is paused.

#### **`protocol-mint(amount, recipient)`**

Mints new USDCx to a principal. Restricted to the **mint role** and disabled when paused.

#### **`protocol-burn(amount, owner)`**

Burns tokens from a principal’s balance. Also restricted to the **mint role** and disabled when paused.

#### **`protocol-mint-many(recipients)`**

Batch-mints tokens to multiple recipients in a single call. Each item includes `{ amount, recipient }`. Only callable by entities with the **mint role**.

***

### **Governance Functions**

Only the **governance role** may call these functions.

#### **`protocol-set-name(new-name)`**

Updates the token’s SIP-010 name.

#### **`protocol-set-symbol(new-symbol)`**

Updates the token’s SIP-010 ticker symbol.

#### **`protocol-set-token-uri(new-uri)`**

Updates the SIP-016 metadata URI.

#### **`set-active-protocol-caller(caller, role, enabled)`**

Adds or removes a principal from a specific protocol role.\
Used for rotating systems, updating companion contracts, or delegating new responsibility.

***

### **Pause Controls**

These functions allow the protocol to halt operations for safety or maintenance.

#### **`pause()`**

Pauses the contract, disabling minting, burning, and all protocol-only actions. Only callable by the **pause role**.

#### **`unpause()`**

Re-enables the protocol after a pause. Also restricted to the **pause role**.

Both functions emit an on-chain event for transparency.


# USDCx Bridge App

<div data-with-frame="true"><figure><img src="/files/ZaqNINNMUlBSunxSXza9" alt=""><figcaption><p><a href="http://bridge.stacks.co/">https://bridge.stacks.co</a></p></figcaption></figure></div>

The USDCx Bridge app is maintained by Stacks Labs and is powered by Circle xReserve.

Acquire USDCx through the [official bridge app](https://bridge.stacks.co/) or migrate your aeUSDC into USDCx to take advantage of better liquidity and improved trust assumptions.

At launch, the USDCx bridge on Stacks supports transfers between Ethereum and Stacks. The first aeUSDC–USDCx liquidity pool will be available on Bitflow in early January.

Support for additional Circle / CCTP-compatible networks is on the roadmap and will roll out in Q1 2026, enabling broader interoperability across Circle’s multichain USDC ecosystem.


# Migrating aeUSDC

Migrate your aeUSDC tokens to USDCx.

### What is aeUSDC?

aeUSDC on Stacks is a bridged form of USDC managed by Allbridge. Now that USDCx is live on Stacks, aeUSDC holders should upgrade to USDCx for better liquidity, better UX and improved trust assumptions.

aeUSDC was first released in 2023. It will be gradually depreciated in favor of USDCx.

{% hint style="warning" %}
Minting aeUSDC is disabled. Users will not be able to mint new aeUSDC. Only transfers from Stacks to Ethereum enabled.
{% endhint %}

### Why should you migrate your aeUSDC to USDCx?

* **Better liquidity** → USDCx gives you deeper liquidity and smoother swaps, powered by a more connected market.
* **Better UX** → Enjoy a cleaner, faster experience with tools and apps built for real usability, not workarounds.
* **Trust & reputation via attestations** → Onchain attestations backed by trusted issuers, Circle, strengthen transparency, credibility, and confidence.

***

### How to migrate aeUSDC to USDCx

There are two primary ways to migrate aeUSDC tokens to USDCx. We’ll explain both of them here.

<details>

<summary>Swap via Bitflow's Conversion Pool</summary>

aeUSDC holders can use the aeUSDC/USDC pool on Bitflow. This is the fastest and cheapest way to migrate to USDCx.

* Navigate to Swaps in the [Bitflow app](https://app.bitflow.finance/trade).
* Connect your wallet.
* Select aeUSDC as the “From” token.
* Set the amount you want to migrate. You may decide to migrate your full aeUSDC balance at once, or test a small amount first before migrating the full balance.
* Select USDCx as the “To” token.
* Click “Swap” button to initiate the swap. You’ll need to sign the transaction requests from your wallet in order to complete the transaction.

{% embed url="<https://x.com/katemparkman/status/2031419834903212277>" %}

</details>

<details>

<summary>Bridge via Allbridge Classic</summary>

Users can bridge aeUSDC back to Ethereum and then bridge back to mint USDCx on Stacks.

* Navigate to the [Allbridge](https://app.allbridge.io/bridge?from=STX\&to=ETH\&asset=aeUSDC) app.
* Choose “Stacks” in the dropdown menu in the “From” field
* Choose “Ethereum” in the dropdown menu in the “To” field
* Choose “aeUSDC” as the asset.
* Connect your wallet.
* Set the amount you want to migrate. You may decide to migrate your full aeUSDC balance at once, or test a small amount first before migrating the full balance.
* Note that it may take 60 minutes (six confirmation blocks) to complete the transaction.
* Once you have migrated aeUSDC back to USDC on Ethereum, you can use the USDCx Stacks bridge to deposit USDC on Stacks. <http://bridge.stacks.co/>

</details>


# FAQ

<details>

<summary>What's the purpose of having stablecoins on Stacks?</summary>

Stablecoins make capital move. They enable institutions to lend and borrow, and they give users access to liquidity without leaving the Bitcoin economy.

</details>

<details>

<summary>Why is it USDCx and not native USDC on Stacks?</summary>

USDCx is a 1:1 USDC-backed stablecoin issued through Circle xReserve and native to Stacks. xReserve provides cryptographic attestations for deposits and minting, while Circle Gateway and CCTP handle cross-chain movement. The result is USDC on Stacks without third-party bridges, wrapped assets, or fragmented liquidity.

With this setup, Stacks now has a fully USDC-backed stablecoin that plugs directly into Circle’s multichain ecosystem and brings stable, interoperable dollar liquidity to Bitcoin’s leading Layer 2. USDCx will always be fully backed by USDC on the source chain.<br>

</details>

<details>

<summary>Which networks are supported for USDCx interoperabiity?</summary>

Currently, interoperability is between Ethereum and Stacks. Other Circle/CCTP-compatible networks will be added in the future.

</details>

<details>

<summary>How is USDCx different from aeUSDC?</summary>

aeUSDC on Stacks is a bridged form of USDC managed by Allbridge. Now that USDCx is live on Stacks, aeUSDC holders should upgrade to USDCx for better liquidity, better UX and improved trust assumptions. aeUSDC was first released in 2023. It will be gradually depreciated in favor of USDCx.

</details>

<details>

<summary>How does USDCx differ from the other stablecoins already on Stacks?</summary>

USDCx is a fully USDC-backed, cryptographically attested dollar asset that moves across chains through Circle’s native infrastructure. It works everywhere USDC works, from Ethereum to Solana and beyond, all while settling on Bitcoin through Stacks.

With USDCx, developers get a reliable dollar rail to build with, users get predictable liquidity, and protocols get a trusted base asset for markets and collateral. It provides the missing piece for deeper liquidity, healthier markets, and real Bitcoin-denominated yield.

* Deeper liquidity pools on Stacks DeFi protocols
* Simplified user experience with Circle-managed reserves
* Institutional confidence and proven infrastructure
* Bitcoin capital flowing freely to where it's most productive

</details>

<details>

<summary>What will happen to aeUSDC?</summary>

aeUSDC will be gradually depreciated in favor of USDCx. Now that USDCx is live on Stacks, aeUSDC holders should upgrade to USDCx for better liquidity, better UX and improved trust assumptions.

</details>


# Introduction

Build powerful apps, secured by Bitcoin.

<div data-with-frame="true"><figure><img src="/files/LYPzSeLHD8MmxSVFXRfN" alt=""><figcaption></figcaption></figure></div>

<details>

<summary><strong>New to building with Stacks? Check out these weekly virtual meets!</strong></summary>

* **Clarity Working Group**: An open, developer-focused initiative dedicated to supporting builders across the Stacks ecosystem. The group brings together experienced Clarity engineers (“Clarity giga chads”), auditors, educators, grant project teams, and new developers to collaborate, learn, and advance smart contract development on Bitcoin. Check out the calendar [link](https://www.addevent.com/event/yc0x95fky8y4) to join every other Tuesday.
* **AI BTC Working Group:** Join the **AI BTC Working Group**'s (WG) weekly meeting on AIBTC's twitter account, where they delve into the exciting intersection of AI and Bitcoin. Check out the calendar [link](https://www.addevent.com/event/c3qjy462xr82) to join every Thursday.

</details>

<details>

<summary><strong>Join the Stackers community!</strong></summary>

Stackers is a community of people building on Bitcoin with Stacks.

The purpose of the Stackers community comes down to guided paths for learning and starting a project on Stacks, developer support from community members, and the best place to hear about new events, initiatives, and opportunities to build.

Join the [Stackers](https://www.skool.com/stackers)!

</details>

{% hint style="info" %}
Stacks ranks #5 among all crypto ecosystems for new developers in 2025! \[source: [Electric Capital](https://x.com/Stacks/status/1978563911948370403)]
{% endhint %}

### Hello, Builders 👋

Stacks is a fast, low-cost, builder-friendly layer 2 network on Bitcoin. It’s built on Bitcoin, inheriting Bitcoin’s battle-tested security. By jumping into our docs, you’re joining the Stacks builder community that’s bringing a global onchain economy to Bitcoin.

If you're here on this page, hopefully you've already gotten a good sense of *what* Stacks' purpose is, if not, head to the [Learn](https://docs.stacks.co/learn/) section. Or if you're still on the edge of *why* you should build with Stacks, head to [Why Build with Stacks](/get-started/readme/why-build-with-stacks).

***

### How to use these docs

The Stacks documentation is organized into a set of top-level sections, each aligned to a distinct stage of a developer’s journey—from learning core concepts to building applications and operating infrastructure.

{% tabs %}
{% tab title="Learn" %}
**How does the Stacks network&#x20;*****actually*****&#x20;work?**\
The [Learn](https://docs.stacks.co/learn/) section focuses on building a strong academic foundation. It explains how Stacks functions as a Bitcoin layer 2, providing clarity and context around the network’s design and mechanics.

Topics include Proof of Transfer (PoX), Bitcoin finality, block production, the transaction lifecycle, and more. If you want a deep understanding of how Stacks anchors to Bitcoin and why it works the way it does, this is the best place to start.
{% endtab %}

{% tab title="Build" %}
**How do you build on Stacks?**\
This section is for experienced developers, but are new to Stacks, who are in the exploratory phase of understanding the general workflow of building apps on Stacks. These guides focus on accomplishing specific tasks—writing contracts, integrating wallets, working with sBTC or USDC—without extensive explainers.

It includes curated quick starts for smart contract development with Clarinet and frontend development with Stacks.js, along with step-by-step guides covering common use cases such as integrating sBTC, onboarding users, working with price oracles, and more.
{% endtab %}

{% tab title="Operate" %}
**How do you run Stacks infrastructure?**\
The [Operate](/operate/run-a-node) section is designed for node operators and infrastructure providers. It covers how to run and manage Stacks nodes, signers, and miners.

If you’re responsible for operating or maintaining Stacks-related infrastructure, this section contains the resources you’ll need.
{% endtab %}

{% tab title="Reference" %}
**Where do you look up technical details such as types, definitions, and configuration?**\
The [Reference](/reference/node-operations/readme-1) section contains authoritative technical documentation for Stacks devtools and APIs. This includes function and type definitions for Clarity and Stacks.js, API endpoint schemas, and interactive API playgrounds.

If you’re an experienced Stacks developer looking to quickly reference a specific method, type, or API response, this section is built for fast lookup and precision.
{% endtab %}

{% tab title="Tutorials" %}
**Looking for a more guided, lesson-oriented experience?**\
The [Tutorials](https://docs.stacks.co/tutorials/) section is designed for complete beginner developers who want structured, long-form lessons rather than quick answers.

These tutorials provide step-by-step walkthroughs alongside in-depth explanations of the underlying concepts. The goal isn’t just to help you complete a task, but to help you understand *why* things work the way they do as you build.

If you’re a complete beginner and prefer a classroom-style, concept-driven learning experience—this section is the best place to start.
{% endtab %}

{% tab title="Cookbook" %}
**Looking for a specific code snippet?**\
The [Cookbook](https://docs.stacks.co/cookbook/) section is for developers beyond the exploratory phase who require a specific, concrete code solution quickly for an existing application.This section provides focused, reusable Clarity and Stacks.js code snippets that solve common problems or demonstrate specific patterns—designed to be referenced, copied, and adapted rather than read end-to-end.

There is also a subsection of example Clarity contracts where you'll find **starter contracts** that demonstrate common patterns and best practices in Clarity, as well as **notable production contracts** currently used by popular Stacks applications.
{% endtab %}
{% endtabs %}

***

### Pick your learning path

We all have different styles of learning. If you've already got a good concept of web3 fundamentals and want to get a quick taste of what the DevEx is like on Stacks, then check out the [Developer Quickstart](/get-started/developer-quickstart). Or find the path that clicks for you — and if bandwidth allows, tackle them all!

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><h4><strong>Try the Developer Quickstart</strong></h4></td><td>Your 0→1 guide for building a Clarity contract and app on Stacks.</td><td><a href="/pages/p6d1myaV7lKCOE4oa6Ux">/pages/p6d1myaV7lKCOE4oa6Ux</a></td></tr><tr><td><h4><strong>Start Learning Clarity</strong></h4></td><td>An easy starting point for learning smart contracts.</td><td><a href="/pages/48ff153e1ee28201ac1d99cfbf5a64f08708e2a0">/pages/48ff153e1ee28201ac1d99cfbf5a64f08708e2a0</a></td></tr><tr><td><h4><strong>Bitcoin Primer Tutorial</strong></h4></td><td>A comprehensive end-to-end experience to building full-stack dApps on Bitcoin.</td><td><a href="/spaces/skGYu79qDNfITOqDNU3s/pages/EQcxwjO33WM06SIolnxb">/spaces/skGYu79qDNfITOqDNU3s/pages/EQcxwjO33WM06SIolnxb</a></td></tr><tr><td><h4><strong>Earn a Stacks Developer Degree</strong></h4></td><td>A hands-on Stacks bootcamp by LearnWeb3.</td><td><a href="https://learnweb3.io/degrees/stacks-developer-degree/">https://learnweb3.io/degrees/stacks-developer-degree/</a></td></tr><tr><td><h4><strong>Watch Our Hands-On Videos</strong></h4></td><td>Developer insights and workshops from the Stacks ecosystem</td><td><a href="https://www.youtube.com/@stacks-developers">https://www.youtube.com/@stacks-developers</a></td></tr><tr><td><h4><strong>Clarity Development Using Clarinet</strong></h4></td><td>The smart contract toolkit for Stacks</td><td><a href="/pages/UK5Kgh2MHLoQvfoFVnLr">/pages/UK5Kgh2MHLoQvfoFVnLr</a></td></tr></tbody></table>

***

### Who should use what

| If you are…                                                                               | First check out...                                                                                                                                                                          |
| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Completely new to building with Stacks                                                    | [Developer Quickstart](/get-started/developer-quickstart)                                                                                                                                   |
| Learning smart contract development                                                       | [Clarity Crash Course](/get-started/clarity-crash-course), [Learn Clarinet](/clarinet/overview)                                                                                             |
| Preferring a structured, guided course that shows you every step to build full-stack apps | [Stacks Developer Degree](https://learnweb3.io/degrees/stacks-developer-degree/), [Bitcoin Primer](/tutorials/bitcoin-primer/introduction), [EasyA](https://www.easya.io/challenges/stacks) |
| Wanting to integrate sBTC in your app                                                     | [sBTC guides](/more-guides/sbtc)                                                                                                                                                            |
| Launching a token                                                                         | [Create Tokens](/get-started/create-a-token)                                                                                                                                                |
| Interested in security / auditing / grants                                                | [Stacks Bug Bounties](https://immunefi.com/bug-bounty/stacks/information/), [Ecosystem Bounties](https://stacks.foundation/grants#bounties)                                                 |
| Curious about current use cases                                                           | [Use Cases](/get-started/use-cases)                                                                                                                                                         |
| Searching for a complete list of devtools                                                 | [Stacks Devtools Catalog](/stacks-devtools-catalog)                                                                                                                                         |

***

### Still got questions?

We know, it's a lot. But we, along with our large community, are always more than welcome to help you throughout your journey with Stacks.

* [**Stacks Discord**](https://discord.gg/stacks): Connect with other developers and our team
* [**Stacks Forum**](https://forum.stacks.org/): Ask questions and share projects
* [**Stacks Twitter**](https://x.com/StacksDevs)**:** Follow us on Twitter and ask us questions there
* [**Stackers**](https://www.skool.com/stackers): A community to hear about new events, initiatives, and opportunities to build.


# Why Build with Stacks

Diving into the question of why we're all here

{% embed url="<https://youtu.be/eqFFX4Sx9mY?si=XcH6Bo3nTQusW0Tp>" %}

### Why build with Stacks

Build on Bitcoin with Stacks because builders don’t need a new base layer — they need a better app layer. Stacks anchors to Bitcoin finality while enabling clear, auditable contracts and expressive logic, making BTC useful beyond holding. With production-ready tooling and one of the most active Bitcoin L2 developer communities, you get momentum, collaboration, and Bitcoin-aligned product-market fit from day one. If you want Bitcoin capital with real applications, Stacks is the path of least resistance and greatest leverage.

### What does it mean to build with Stacks

Building with Stacks means creating applications and smart contracts that ***extend*** the power of Bitcoin without altering Bitcoin itself. It’s about inheriting Bitcoin’s security, finality, and economic gravity, while gaining the expressiveness needed for decentralized apps, ownership-first systems, and programmable digital assets.

Developers use easy, LISP-like contracts written in the Clarity language, interact with the chain using familiar tooling like Stacks.js, automate on-chain responsiveness with Chainhooks, enable Bitcoin programmability via sBTC, and tap into indexed on-chain data through reliable APIs.

Ultimately, **building with Stacks is a mindset**: leverage Bitcoin as the base layer, but experiment boldly at the application layer—where users keep custody of their bitcoin via sBTC, transactions enforce intent, and decentralized systems become useful enough for everyday life.

### Benefits of building with Stacks

<details>

<summary>🌐 Global Community</summary>

***Diverse and Vibrant:*** Stacks has a massive global builder community where collaboration happens at internet speed, not conference speed. You plug into shared momentum, talent, diversity, and distribution across a network anchored by Bitcoin.

* \[[Hiro YT](https://youtu.be/jjSbIKRb8Z8?si=JRzdbiBWq9mLKVaz)] Meeting Rockstar Web3 Builders at the EasyA x Stacks Hackathon
* \[[StacksDevs](https://x.com/StacksDevs/status/1991506865394774371)] Photos from the Stacks Hacker House in Buenos Aires
* \[[Stacks YT](https://youtu.be/UB6pkG58wYo?si=ITiW7xhz8odfa59T)] How Stacks Took Over Miami

</details>

<details>

<summary>🎨 Creator Tools</summary>

***The Bitcoin-Backed Creator Economy:*** From artists to influencers, creators are seeking smarter ways to capture value. With Stacks, you can push the boundaries of monetization, powered by Bitcoin capital and programmable Clarity contracts.

* \[[Hiro Blog](https://www.hiro.so/blog/what-is-bitcoin-culture-see-it-through-bitcoin-nfts)] What is “Bitcoin Culture?” See it through Bitcoin NFTs
* \[[Hiro Blog](https://www.hiro.so/blog/building-an-accelerator-for-african-creators-with-osinachi-africas-foremost-nft-artist)] Building an Accelerator for African Creators With Osinachi, Africa’s Foremost NFT Artist
* \[[Hiro Blog](https://www.hiro.so/blog/a-look-inside-gammas-create-portal-and-how-it-empowers-nft-creators)] A Look Inside Gamma’s Create Portal and How It Empowers NFT Creators

</details>

<details>

<summary>🛠️ Developer Experience</summary>

***Built for Builders:*** Stacks offers everything you need — tooling, infra, and hands-on support. Backed by one of the largest on-chain dev communities, it’s a place to collaborate, level up, and build the future together.

* \[[Hiro YT](https://youtu.be/gPG6ZFGpYo0?si=hMxIxGJjuoggfD8Q)] Exploring Web3 Developer Tooling With the Clarinet Team
* \[[Bitcoin Builders YT](https://youtu.be/RCHbqfaUbHQ?si=j5BLw6lCIYAq52RI)] What is the Dev Experience for Bitcoin Layers?

</details>

<details>

<summary>🏗️ Builder Programs</summary>

***Support at Every Step:*** Stacks runs specialized builder programs that give you capital, feedback, and community validation, not just swag and tweets. You get structured support that compounds long after demo day.

* \[[Stacks Ascent](https://stacks.org/ascent)] From Code to Company
* \[[Stacks Foundation](https://stacks.org/grants)] Grants & Bounty Programs

</details>


# Developer Quickstart

Your 0→1 guide for building a Clarity contract and app on Stacks.

<div data-with-frame="true"><figure><img src="/files/N2wd5Efp1L2sDoCVPZ3s" alt=""><figcaption></figcaption></figure></div>

**Welcome to the Stacks Developer Quickstart Guide!**\
This is your fast-track path for understanding what you'll need to become a Stacks developer. In this guide, you’ll build a real Clarity smart contract, wire up a functioning Stacks app, and pick up about 75% of the practical knowledge every Stacks builder needs. Whether you’re shipping your first project or leveling up your skills, this guide takes you from zero to deployed—quickly and confidently.

### What you'll achieve

By the end of this quickstart, you’ll have built an onchain app by:

* Building a Clarity smart contract with Clarinet
* Utilize the 1:1 Bitcoin-backed token, sBTC
* Deploying your smart contract to Stacks' testnet
* Interacting with your deployed contract from a frontend app

{% hint style="success" %}
**Why Stacks?**

Stacks is a fast, low-cost, builder-friendly layer 2 network on Bitcoin. It’s built on Bitcoin, inheriting Bitcoin’s battle-tested security. By jumping into this guide, you’re joining the Stacks community that’s bringing a global onchain economy to Bitcoin.
{% endhint %}

### What You'll Build

The app you'll build will be a message board contract. Users can add a new message to store on-chain for a fee of 1 satoshi in sBTC. Other functionality to read data from the contract will also be handled. Besides sBTC, there will be other things that'll be introduced to you such as post-conditions, Bitcoin read access, unit testing, wallet connectivity, BNS, Hiro, and more. Hopefully all this will give you a good flavor of what you can expect in the Stacks builder ecosystem.

Let's start building on Bitcoin! :orange\_square:

{% hint style="info" %}
**Prerequisites**

* Basic familiarity with web development
* Basic familiarity with web3 concepts
* A modern web browser
* Node.js
* Visual Studio Code or any other popular IDE
  {% endhint %}

### Set Up Your Developer Environment

{% stepper %}
{% step %}
**Install Clarinet**

Clarinet is the popular CLI tool to build, test, and deploy smart contracts on the Stacks blockchain.

Below are a few different ways to install Clarinet on your machine using your terminal. Refer to the dedicated [installation](/clarinet/overview) guide in the 'Learn Clarinet' section for more information.

{% tabs %}
{% tab title="Homebrew" %}

```bash
brew install clarinet
```

{% endtab %}

{% tab title="Winget" %}

```bash
winget install clarinet
```

{% endtab %}

{% tab title="Source" %}

```bash
sudo apt install build-essential pkg-config libssl-dev
git clone https://github.com/stx-labs/clarinet
cd clarinet
cargo clarinet-install
```

{% endtab %}

{% tab title="Binary" %}

```bash
wget -nv https://github.com/stx-labs/clarinet/releases/latest/download/clarinet-linux-x64-glibc.tar.gz -O clarinet-linux-x64.tar.gz
tar -xf clarinet-linux-x64.tar.gz
chmod +x ./clarinet
mv ./clarinet /usr/local/bin
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}
**Install Clarity Extension**

You'll also want to install the Clarity Extension for your code editor. The official one is '[Clarity - Stacks Labs](https://marketplace.visualstudio.com/items?itemName=StacksLabs.clarity-stacks)' which is maintained by [Stacks Labs](https://stackslabs.com/).

<details>

<summary>What is Clarity?</summary>

Clarity is Stacks' smart contract language, designed for safety and predictability.

Clarity is inspired by LISP and uses a functional programming approach. Everything in Clarity is an expression wrapped in parentheses. This can be a bit overwhelming at first if you are used to languages like JavaScript or Solidity, but the learning curve is short and Clarity is a simple language to understand once you dive in and start using it.

Check out the [Clarity Crash Course](/get-started/clarity-crash-course) for a quick primer.

</details>

<div data-with-frame="true"><figure><img src="/files/HsjqQTVdPGDUlEvRUSZD" alt=""><figcaption><p>The 'Clarity - Stacks Labs' extension as it appears in Visual Studio Code.</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Install a Stacks wallet**

There are many Stacks supported wallets in the market. For this guide, we'll be using the [Leather](https://leather.io/) wallet. Leather supports Stacks, Bitcoin, and other Bitcoin related meta-protocols. Download and install its browser extension so you can interact with your smart contract later on in this guide. Make sure to switch to the **Testnet** network in your wallet settings. Later on, we'll show you how to get testnet STX and sBTC tokens that you'll use for contract interaction.
{% endstep %}
{% endstepper %}

### Create a Clarity smart contract

{% stepper %}
{% step %}
**Create a new Clarinet project**

Let's start by creating a new Clarinet project which will house our smart contract. The `clarinet new` command sets up everything you need for smart contract development, including a testing framework, deployment configurations, and a local development environment.

{% code title="terminal" %}

```
clarinet new my-stacks-contracts
```

{% endcode %}

A Clarinet project will be scaffolded with the below:

{% code title="terminal" expandable="true" %}

```
Created directory my-stacks-contracts
Created directory contracts
Created directory settings
Created directory tests
Created file Clarinet.toml
Created file settings/Mainnet.toml
Created file settings/Testnet.toml
Created file settings/Devnet.toml
Created directory .vscode
Created file .vscode/settings.json
Created file .vscode/tasks.json
Created file .gitignore
Created file .gitattributes
Created file package.json
Created file tsconfig.json
Created file vitest.config.ts

----------------------------
Hint: what's next?
Switch to the newly created directory with:

  $ cd my-stacks-contracts

Once you are ready to write your contracts, run the following commands:

  $ clarinet contract new <contract-name>
    Create new contract scaffolding, including test files.

  $ clarinet check
    Check contract syntax for all files in ./contracts.
```

{% endcode %}
{% endstep %}

{% step %}
**Generate your contract**

Now that we have our project structure, let's create a smart contract. Navigate into your project directory and use Clarinet's contract generator:

```sh
$ cd my-stacks-contracts
$ clarinet contract new message-board
Created file contracts/message-board.clar
Created file tests/message-board.test.ts
Updated Clarinet.toml with contract message-board
```

Clarinet automatically creates both your contract file and a corresponding test file.
{% endstep %}
{% endstepper %}

### Write your Clarity smart contract

{% stepper %}
{% step %}
**Define constants**

Open `contracts/message-board.clar` and remove its existing content. This is where we'll start writing our own Clarity smart contract.

Let's first define some constants:

* contract owner to establish control access
* custom error codes to handle errors in functions

<pre class="language-clarity" data-title="message-board.clar"><code class="lang-clarity">;; Simple Message Board Contract
;; This contract allows users to read and post messages for a fee in sBTC.

;; Define contract owner
<strong>(define-constant CONTRACT_OWNER tx-sender)
</strong>
;; Define error codes
<strong>(define-constant ERR_NOT_ENOUGH_SBTC (err u1004))
</strong><strong>(define-constant ERR_NOT_CONTRACT_OWNER (err u1005))
</strong><strong>(define-constant ERR_BLOCK_NOT_FOUND (err u1003))
</strong></code></pre>

You'll notice in the `CONTRACT_OWNER` constant that `tx-sender` is set in place as the value. When this contract is deployed, the Clarity VM will determine who the `tx-sender` is based on who deployed the contract. This allows the hardcoded `tx-sender` to always point to the principal that deployed the contract.
{% endstep %}

{% step %}
**Define data storage**

We'll then need to define some data storage:

* A map to store key-value pairs of the message id and its related metadata
* A data variable to count the total number of messages added

<pre class="language-clarity" data-title="message-board.clar"><code class="lang-clarity">;; Define a map to store messages
;; Each message has an ID, content, author, and Bitcoin block height timestamp
<strong>(define-map messages
</strong>  uint
  {
    message: (string-utf8 280),
    author: principal,
    time: uint,
  }
)

;; Counter for total messages
<strong>(define-data-var message-count uint u0)
</strong></code></pre>

{% endstep %}

{% step %}
**Define an add message function**

Next up is our main function of the contract. This function allows users to add a new message to the contract for a fee of 1 satoshi in sBTC. Invoking this function will change the state of our contract and update the data storage pieces we setup before.

<pre class="language-clarity" data-title="message-board.clar" data-expandable="true"><code class="lang-clarity">;; Public function to add a new message for 1 satoshi of sBTC
;; @format-ignore
<strong>(define-public (add-message (content (string-utf8 280)))
</strong>  (let ((id (+ (var-get message-count) u1)))
    (try! (restrict-assets? contract-caller 
      ((with-ft 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token "sbtc-token" u1))
      (unwrap!
        ;; Charge 1 satoshi of sBTC from the caller
        (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
          transfer u1 contract-caller current-contract none
        )
        ERR_NOT_ENOUGH_SBTC
      )
    ))
    ;; Store the message with current Bitcoin block height
    (map-set messages id {
      message: content,
      author: contract-caller,
      time: burn-block-height,
    })
    ;; Update message count
    (var-set message-count id)
    ;; Emit event for the new message
    (print {
      event: "[Stacks Dev Quickstart] New Message",
      message: content,
      id: id,
      author: contract-caller,
      time: burn-block-height,
    })
    ;; Return the message ID
    (ok id)
  )
)
</code></pre>

There's quite a lot going on in this function above that covers in-contract post-conditions, calling the official sBTC token contract, reading Bitcoin state, emitting events, and etc. We'll break it down for you:

<details>

<summary>Define public function and params</summary>

```clarity
(define-public (add-message (content (string-utf8 280)))
    ;; function body
)
```

By using the `define-public` function, we can literally create a public function where anyone can invoke.

* `(add-message ... )` : the custom name of the public function
* `(content (string-utf8 280))` : the custom parameter name and type

</details>

<details>

<summary>Create let variable binding for next message id</summary>

```clarity
(let ((id (+ (var-get message-count) u1)))
    ;; body expressions
)
```

Creates a "local" variable that can be used inside the function body only. This `id` variable will be used to represent the new message id being added.

</details>

<details>

<summary>Transfer 1 satoshi of sBTC from user to the contract</summary>

<pre class="language-clarity"><code class="lang-clarity">(try! (restrict-assets? contract-caller 
  ((with-ft 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token "sbtc-token" u1))
  (unwrap!
    ;; Charge 1 satoshi of sBTC from the caller
<strong>    (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
</strong>      transfer u1 contract-caller current-contract none
    )
    ERR_NOT_ENOUGH_SBTC
  )
))
</code></pre>

This snippet calls the external .`sbtc-token` contract to transfer sBTC.

The `restrict-assets?` acts as an in-contract post-condition to protect user and contract funds when calling external contracts to transfer assets.

</details>

<details>

<summary>Store message data in mapping</summary>

```clarity
(map-set messages id {
  message: content,
  author: contract-caller,
  time: burn-block-height,
})
```

The function `map-set` will allow the existing mapping of `messages` to add a new key-value pair consisting of the metadata of the new message.

We'll be using the current Bitcoin block height (via `burn-block-height`) as a way to capture the time of when this new message was added. Through `burn-block-height` , Clarity allows us to have read access into the Bitcoin state at anytime.

</details>

<details>

<summary>Update the message-count variable</summary>

```clarity
(var-set message-count id)
```

Increments the existing data variable of `message-count` with the `let` id variable.

</details>

<details>

<summary>Emit an event to the network</summary>

```clarity
(print {
  event: "[Stacks Dev Quickstart] New Message",
  message: content,
  id: id,
  author: contract-caller,
  time: burn-block-height,
})
```

The `print` function will allow us to emit a custom event to the Stacks network.

Emitting events on Stacks serves several critical purposes:

1. **Transparency**: Events provide an on-chain record of actions and transactions, ensuring transparency.
2. **Notification**: They serve as a signal mechanism for users and external applications, notifying them of specific occurrences on Stacks.
3. **State Tracking**: Developers can use events to track changes in the state of smart contracts without querying the chain continuously.
4. **Efficient Data Handling**: By emitting events, webhook services, such as Hiro's [Chainhooks](https://docs.hiro.so/en/tools/chainhooks), can filter and handle relevant data efficiently, reducing the on-chain computation load.

</details>

<details>

<summary>Return final response</summary>

<pre class="language-clarity"><code class="lang-clarity">;; Return the message ID
<strong>(ok id)
</strong></code></pre>

Public functions *must* return a ResponseType (using either `ok` or `err`). In this case, we'll return a response type with an inner value of the new message id.

</details>
{% endstep %}

{% step %}
**Add sBTC contract requirements**

Since we're working with sBTC in our local developer environment, we'll need to make sure Clarinet can recognize this. Clarinet can automatically wire up the official sBTC contracts so you can build and test sBTC flows locally.

In our case, all we'll need to do is add the [`.sbtc-deposit`](https://explorer.hiro.so/txid/SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-deposit?chain=mainnet) contract as a project requirement.

{% code title="terminal" %}

```
clarinet requirements add SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-deposit
```

{% endcode %}

You'll notice in the `add-message` public function, we're making an external contract call to the [`.sbtc-token`](https://explorer.hiro.so/txid/0xead2080826685a98886891cbd9b288d367ae19b357353c71fff4a3330da582c8?chain=mainnet) contract. This is the official sBTC token contract that contains the [SIP-010](https://github.com/stacksgov/sips/blob/main/sips/sip-010/sip-010-fungible-token-standard.md) standard `transfer` function that we are invoking.

Check out the dedicated [sBTC integration](/clarinet/integrations/sbtc) page to learn more.
{% endstep %}

{% step %}
**Allow contract owner to withdraw funds**

In the beginning of our contract, we defined a constant to store the Stacks principal of the contract owner. Having a contract owner allows for specific access control of the contract that is entitled to the owner. Let's allow the owner to be able to withdraw the accumulated sBTC fees that were sent by anyone who created a new message in the contract.

<pre class="language-clarity" data-expandable="true"><code class="lang-clarity">;; Withdraw function for contract owner to withdraw accumulated sBTC
(define-public (withdraw-funds)
  (begin
<strong>    (asserts! (is-eq tx-sender CONTRACT_OWNER) (err u1005))
</strong>    (let ((balance (unwrap-panic (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
        get-balance current-contract
      ))))
      (if (> balance u0)
        (contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token
          transfer balance current-contract CONTRACT_OWNER none
        )
        (ok false)
      )
    )
  )
)
</code></pre>

You'll notice in the highlighted line that the function performs an `asserts!` check to confirm that the `tx-sender` calling the contract is in fact the `CONTRACT_OWNER` . If it is in fact the owner of the contract, the function body proceeds with transferring the balance of sBTC to the owner or else it'll throw an error that we defined earlier.

{% hint style="info" %}
The usage of `tx-sender` versus another Clarity keyword, `contract-caller` , is always a tricky concept because it determines who actually initiated the transaction versus who invoked the current function. Both of them can have certain implications on security based on the context of your code. Check out the dedicated [blog](https://www.setzeus.com/public-blog-post/clarity-carefully-tx-sender), written by community dev Setzeus, to learn when you should use either or.
{% endhint %}
{% endstep %}

{% step %}
**Implement read only functions**

We'll round out our contract with important read only functions that will return us needed data from the contract.

<pre class="language-clarity" data-expandable="true"><code class="lang-clarity">;; Read-only function to get a message by ID
(define-read-only (get-message (id uint))
  (map-get? messages id)
)

;; Read-only function to get message author
(define-read-only (get-message-author (id uint))
  (get author (map-get? messages id))
)

;; Read-only function to get message count at a specific Stacks block height
(define-read-only (get-message-count-at-block (block uint))
<strong>  (ok (at-block
</strong>    (unwrap! (get-stacks-block-info? id-header-hash block) ERR_BLOCK_NOT_FOUND)
    (var-get message-count)
  ))
)
</code></pre>

You'll notice the usage of a `at-block` function in the highlighted line of code. The `at-block` function evaluates the inner expression *as if* it were evaluated at the end of a specific Stacks block.
{% endstep %}

{% step %}
**Test your contract**

Now with the actual writing of your contract complete, we now need to test its functionality. There's a few different ways we can go about iterating and testing the functionality of your contract.

* Contract interaction in the [Clarinet REPL](/clarinet/contract-interaction)
* Running your contract in a [local blockchain environment](/clarinet/local-blockchain-development)
* Fuzz testing with [Rendezvous](https://stx-labs.github.io/rendezvous/)
* Writing unit tests with the [Clarinet JS SDK](/clarinet/testing-with-clarinet-sdk)

We'll go with unit testing for now. In your `tests` folder, open up the related `message-board.test.ts` file and let's use the unit test written below.

<pre class="language-typescript" data-title="tests/message-board.test.ts" data-line-numbers data-expandable="true"><code class="lang-typescript">import { Cl, ClarityType } from "@stacks/transactions";
import { describe, expect, it } from "vitest";

const accounts = simnet.getAccounts();
const deployer = accounts.get("deployer")!;
const address1 = accounts.get("wallet_1")!;

describe("example tests", () => {
  let content = "Hello Stacks Devs!"

<strong>  it("allows user to add a new message", () => {
</strong>    let currentBurnBlockHeight = simnet.burnBlockHeight;

    let confirmation = simnet.callPublicFn(
      "stacks-dev-quickstart-message-board",
      "add-message",
      [Cl.stringUtf8(content)],
      address1
    )

    const messageCount = simnet.getDataVar("stacks-dev-quickstart-message-board", "message-count");
    
    expect(confirmation.result).toHaveClarityType(ClarityType.ResponseOk);
    expect(confirmation.result).toBeOk(messageCount);    
    expect(confirmation.events[1].data.value).toBeTuple({
      author: Cl.standardPrincipal(address1),
      event: Cl.stringAscii("[Stacks Dev Quickstart] New Message"),
      id: messageCount,
      message: Cl.stringUtf8(content),
      time: Cl.uint(currentBurnBlockHeight),
    });
  });

<strong>  it("allows contract owner to withdraw funds", () => {
</strong>    simnet.callPublicFn(
      "stacks-dev-quickstart-message-board",
      "add-message",
      [Cl.stringUtf8(content)],
      address1
    )
    
    simnet.mineEmptyBurnBlocks(2);

    let confirmation = simnet.callPublicFn(
      "stacks-dev-quickstart-message-board",
      "withdraw-funds",
      [],
      deployer
    )
    
    expect(confirmation.result).toBeOk(Cl.bool(true));
    expect(confirmation.events[0].event).toBe("ft_transfer_event")
    expect(confirmation.events[0].data).toMatchObject({
      amount: '1',
      asset_identifier: 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token::sbtc-token',
      recipient: deployer,
      sender: `${deployer}${".stacks-dev-quickstart-message-board"}`,
    })
  })
});

</code></pre>

You'll notice we have two `it` blocks setup to test out 2 different scenarios:

1. Allows user to add a new message
2. Allows owner to withdraw sBTC funds

Run the test via `npm run test` to confirm that the two scenarios are functioning as intended.

{% code title="terminal" %}

```bash
$ npm run test

 ✓ tests/message-board.test.ts (2 tests) 46ms
   ✓ message board tests (2)
     ✓ allows user to add a new message 26ms
     ✓ allows contract owner to withdraw funds 19ms

 Test Files  1 passed (1)
      Tests  2 passed (2)
   Start at  14:05:07
   Duration  886ms (transform 40ms, setup 42ms, collect 8ms, tests 46ms, environment 699ms, prepare 4ms)
```

{% endcode %}

Great! Now that your contract is working as intended, let's deploy the contract to testnet.
{% endstep %}
{% endstepper %}

### Get testnet faucet tokens

{% stepper %}
{% step %}
**Navigate to the Hiro Platform faucet**

[Hiro](https://www.hiro.so/platform) is a platform to build and scale Bitcoin apps, including custom data streams, onchain alerts, API key management, and more. Create an account and navigate to the top tab of 'Faucet'. On the Faucet page, you can request testnet STX and/or sBTC. We'll be needing both so fund your Leather wallet account with both.

<div data-with-frame="true"><figure><img src="/files/its78Nq5ojgWif0J0dXb" alt=""><figcaption></figcaption></figure></div>

Grab the testnet Stacks address from your Leather wallet and paste it in the recipient field.

{% hint style="warning" %}
**Important**: Switch to the **Testnet** network in your wallet settings
{% endhint %}
{% endstep %}

{% step %}
**Confirm testnet tokens in your wallet**

Open up your Leather extension to confirm that you've received testnet STX and sBTC. You might need to enable the viewing of the sBTC token in your wallet under 'Manage tokens'.

<div data-with-frame="true"><figure><img src="/files/svwahFPrUtsvCUylmRYm" alt=""><figcaption></figcaption></figure></div>

With both testnet STX and sBTC, you're ready to deploy your contract and interact with it from a front-end client.
{% endstep %}
{% endstepper %}

### Deploy your Clarity smart contract

{% stepper %}
{% step %}
**Generate testnet deployment plan**

You'll first want to input a mnemonic seed phrase in the `settings/Testnet.toml` file and specify the account derivation path that you want to use for deploying the contract. The account should be the same one you used to request testnet STX to. This will be the account that actually deploys the contract and becomes the contract owner.

<pre data-title="settings/Testnet.toml"><code>[network]
name = "testnet"
stacks_node_rpc_address = "https://api.testnet.hiro.so"
deployment_fee_rate = 10

[accounts.deployer]
<strong>mnemonic = "&#x3C;YOUR TESTNET MNEMONIC>"
</strong>derivation = "m/44'/5757'/0'/0/0"
</code></pre>

Then generate a deployment plan for the testnet network. Deployment plans are YAML files that describe how contracts are published or called.

{% hint style="warning" %}
For more information on configuring deployment plans, check out the specific guide [here](/clarinet/contract-deployment).
{% endhint %}

{% code title="terminal" %}

```bash
$ clarinet deployments generate --testnet --medium-cost
Analyzing contracts...
Calculating deployment costs...
Generating deployment plan
Created file deployments/default.testnet-plan.yaml
```

{% endcode %}
{% endstep %}

{% step %}
**Deploy contract to testnet**

Once your deployment plan is generated and configured properly, go ahead and deploy the contract to testnet.

{% code title="terminal" %}

```bash
clarinet deployments apply --testnet
```

{% endcode %}

If the contract was successfully deployed, you should see the below confirmation:

```
Broadcasting transactions to https://api.testnet.hiro.so
Publish ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3.message-board Transaction confirmed
```

{% hint style="info" %}
A sample of the contract we just created above is already deployed to testnet [here](https://explorer.hiro.so/txid/ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3.stacks-dev-quickstart-message-board?chain=testnet). Check out its contract page on the Stacks Explorer and directly interact with its functions.
{% endhint %}
{% endstep %}
{% endstepper %}

### Use stacks.js on the frontend

{% stepper %}
{% step %}
**Connect wallet**

Using [stacks.js](/stacks.js/overview) packages on the frontend will allow our frontend app to authenticate wallets, call our contract functions, and interact with the Stacks network.

We'll first want to connect and authenticate our Leather wallet extension with our frontend app. The stacks.js monorepo contains several underlying packages specific to different use cases. The package `@stacks/connect` is the main connectivity package used in Stacks.

In the snippet below, you'll notice we have 3 functions setup to handle `connectWallet` , `disconnectWallet`, and for `getBns` . All 3 functions will be integral in how we want to display the 'Connect' and 'Disconnect' button in the UI.

{% hint style="info" %}
Retrieving a wallet account's associated [BNS](/learn/network-fundamentals/bitcoin-name-system) is a staple of Stacks and for web3 identity. Check out [BNSv2](https://www.bnsv2.com/) for more information and for availably public API endpoints you could use.
{% endhint %}

<pre class="language-typescript" data-title="src/App.tsx" data-expandable="true"><code class="lang-typescript">import { connect, disconnect } from '@stacks/connect'
import type { GetAddressesResult } from '@stacks/connect/dist/types/methods'
import { useState } from 'react'

function App() {
  let [isConnected, setIsConnected] = useState&#x3C;boolean>(false)
  let [walletInfo, setWalletInfo] = useState&#x3C;any>(null)
  let [bns, setBns] = useState&#x3C;string>('')

<strong>  async function connectWallet() {
</strong>    let connectionResponse: GetAddressesResult = await connect()
    let bnsName = await getBns(connectionResponse.addresses[2].address)

    setIsConnected(true)
    setWalletInfo(connectionResponse)
    setBns(bnsName)
  }

<strong>  async function disconnectWallet() {
</strong>    disconnect();
  }
  
<strong>  async function getBns(stxAddress: string) {
</strong>    let response = await fetch(`https://api.bnsv2.com/testnet/names/address/${stxAddress}/valid`)
    let data = await response.json()

    return data.names[0].full_name
  }
  
  return (
    &#x3C;>
      &#x3C;h3>Stacks Dev Quickstart Message Board&#x3C;/h3>
      {isConnected ? (
        &#x3C;button onClick={disconnectWallet}>{
<strong>          bns ? bns : walletInfo.addresses[2].address
</strong>        }&#x3C;/button>
      ) : (
        &#x3C;button onClick={connectWallet}>connect wallet&#x3C;/button>
      )}
    &#x3C;/>
  )
}
</code></pre>

The `connect()` method comes with ability to configure how you want the wallet selector modal to appear for your app. You can decide which wallets to have only appear as an option or allow any wallet that follows the SIP-030 standard to appear as an available Stacks wallet.

<div data-with-frame="true"><figure><img src="/files/guB3RlKBsfc5GXjo6xH3" alt=""><figcaption><p>The Stacks Connect wallet selector modal</p></figcaption></figure></div>
{% endstep %}

{% step %}
**Call \`add-message\` public function**

Next, we'll setup a `stx_callContract` to invoke the `add-message` public function of our contract. This function will accept a string content to be passed into our contract call.

<pre class="language-typescript" data-expandable="true"><code class="lang-typescript">import { request } from '@stacks/connect'
import type { TransactionResult } from '@stacks/connect/dist/types/methods'
import { Cl, Pc } from '@stacks/transactions'
import { useState } from 'react'

function App() {
  // ...
  let [content, setContent] = useState&#x3C;string>('')

  async function addMessage() {
    let postCond_1 = Pc.principal('ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3')
      .willSendEq(1)
      .ft('ST1F7QA2MDF17S807EPA36TSS8AMEFY4KA9TVGWXT.sbtc-token', 'sbtc-token')
  
<strong>    let result: TransactionResult = await request('stx_callContract', {
</strong>      contract: 'ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3.stacks-dev-quickstart-message-board',
      functionName: 'add-message',
      functionArgs: [Cl.stringUtf8(content)],
      network: 'testnet',
      postConditions: [postCond_1],
      postConditionMode: 'deny',
      sponsored: false
    })
  
    setContent('')
  }

  return (
    &#x3C;>
      // ...
      &#x3C;span className='input-container'>
        &#x3C;button onClick={addMessage}>add-message&#x3C;/button>
        &#x3C;input type="text" onChange={e => setContent(e.target.value)}/>
      &#x3C;/span>
    &#x3C;/>
  )
}
</code></pre>

You'll notice in the transaction data object that we pass into our string literal method of `stx_callContract`, that we're setting up post-conditions. [Post-Conditions](/post-conditions/overview) for the frontend are declared to protect user assets. The `Pc` helper from `@stacks/transactions` helps us to declare post-condition statements for any type of asset and equality operator.

Invoking our `addMessage` function will prompt the user's connected wallet to prompt a transaction confirmation popup. This popup will display all of the relevant information of the transaction as well as the post-condition statements that we've declared.

<div data-with-frame="true"><figure><img src="/files/gjZDQB2hR3XLieSwt4fP" alt=""><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Call read-only function**

As how we've created a few read-only functions in our contract, we'll also want to call these from the frontend to retrieve certain contract data.

Let's setup a `fetchCallReadOnlyFunction` to invoke our contract's `get-message-count-at-block` read-only function. For this, we'll fetch the current Stacks block height from the Hiro API endpoint and pass that returned value into our read-only function.

<pre class="language-typescript" data-expandable="true"><code class="lang-typescript">// ...
import type { ClarityValue } from '@stacks/connect/dist/types/methods'
import { Cl, fetchCallReadOnlyFunction } from '@stacks/transactions'

function App() {
  // ...  
  async function getMessageCountAtBlock() {
<strong>    let response = await fetch('https://api.testnet.hiro.so/v2/info', {
</strong>      headers: {
        "x-api-key": "&#x3C;HIRO_API_KEY>"
      }
    })
    let data = await response.json()
    let stacksBlockHeight = data.stacks_tip_height

    let result: ClarityValue = await fetchCallReadOnlyFunction({
      contractAddress: 'ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3',
      contractName: 'stacks-dev-quickstart-message-board',
      functionName: 'get-message-count-at-block',
<strong>      functionArgs: [Cl.uint(stacksBlockHeight)],
</strong>      network: 'testnet',
      senderAddress: 'ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3',
    })
  }
  
  // ...
</code></pre>

{% hint style="info" %}
For the complete set of available API endpoints for the Stacks network, check out the [Hiro docs](https://docs.hiro.so/). But first create an API key from the [Hiro Platform](https://platform.hiro.so/) to determine your API rate plan.
{% endhint %}
{% endstep %}
{% endstepper %}

And that's it, you've successfully created an sBTC powered Clarity smart contract which can be interacted with from a frontend app. There's obviously much more you can do to complete this but you've got some of the basics down pat now. Go ahead and finish creating the frontend functions to call on the other contract functions we have.

***

### Further Improvements

This is just the beginning. There are many ways we can improve upon this app. Here are some suggestions for you to extend the functionality of this app:

* Deploy to mainnet and share your project with the community
* Use [Chainhooks](https://docs.hiro.so/en/tools/chainhooks) to index emitted events from the contract
* Integrate the [`sbtc`](/more-guides/sbtc/bridging-bitcoin) library so users can directly bridge their BTC to sBTC in-app
* Utilize SIP-009 NFTs to uniquely identify each message for each author

***

### Next Steps

Now that you have the basics down, here are some ways to continue your Stacks development journey:

**Learn More About Clarity**

* [**Clarity Crash Course**](https://docs.stacks.co/docs/clarity-crash-course): Quick introduction to Clarity concepts
* [**Clarity Book**](https://book.clarity-lang.org/): Comprehensive guide to Clarity development
* [**Clarity Reference**](https://docs.stacks.co/docs/clarity): Complete documentation of Clarity functions

**Development Tools**

* [**Clarinet**](https://github.com/stx-labs/clarinet): Local development environment for Clarity
* [**Hiro Platform**](https://platform.hiro.so/): API management
* [**Stacks Explorer**](https://explorer.stacks.co/): View transactions and contracts

**Community Resources**

* [**Stacks Discord**](https://discord.gg/stacks): Connect with other developers
* [**Stacks Forum**](https://forum.stacks.org/): Ask questions and share projects


# Clarity Crash Course

The Stacks ecosystem has its own smart contract programming language called Clarity.

<div data-with-frame="true"><figure><img src="/files/If9XEExEuBIXptdz4tSX" alt=""><figcaption></figcaption></figure></div>

### Intro

This is designed for people with some programming experience who are new to Clarity. You don't need prior smart contract development experience, but if you have experience with languages like Solidity, you'll pick this up quickly.

Once you've briefly familiarized yourself with the language, consider the [Clarity Book](https://book.clarity-lang.org/) or the course [Clarity Universe](https://clarity-lang.org/universe) to continue your learning.

{% hint style="info" %}
Clarity is developed as a joint effort of [Hiro PBC](https://hiro.so/), [Algorand](http://algorand.com/), and various other stakeholders, that originally targets the Stacks blockchain. The Clarity source code can be found in the stacks-core repo [here](https://github.com/stacks-network/stacks-core).
{% endhint %}

### Your First Clarity Smart Contract

We're going to walkthrough a basic Clarity smart contract using the [Clarity Playground](https://play.stackslabs.com/), an online REPL environment where you can write and run Clarity code in the browser. Visit that link and it will open up a new example contract for you on the left view, with an interactive REPL on the right view.

<div data-with-frame="true"><figure><img src="/files/iD2xBEegqJPGoRzWYWhV" alt=""><figcaption><p>The example counter contract provided when visiting the Clarity Playground</p></figcaption></figure></div>

{% hint style="info" %}
Clarity Playground is a new tool to write and run Clarity code directly in the browser. With Clarity Playground, developers can test out concepts, try new ideas, or just, well…play around. Learn more [here](https://www.hiro.so/blog/meet-clarity-playground).
{% endhint %}

The example contract you'll see is a simple counter contract that will store the value of a `count` in a data variable and `increment` the count value by invoking a defined public function.

{% code title="counter.clar" %}

```clarity
(define-data-var count uint u0)
(define-data-var contract-owner principal tx-sender)
(define-data-var cost uint u10)

(define-read-only (get-count)
  (var-get count)
)

(define-public (increment)
  (begin
    (print u"incrementing count")
    (ok (var-set count (+ (var-get count) u1)))
  )
)
```

{% endcode %}

Clarity's syntax is inspired by LISP: everything is an expression wrapped in parentheses. Function definitions, variable declarations, and parameters are lists inside lists. This makes Clarity concise and readable once you get used to it. Here are some characteristics of Clarity you'll notice:

{% stepper %}
{% step %}
**Everything in parentheses is an expression**

Clarity treats everything as expressions inside parentheses. Function definitions are calls to built-in functions; the function body is an expression. This uniformity helps reasoning about programs in Clarity.
{% endstep %}

{% step %}
**Uses LISP-like nesting**

Expect nested parentheses and expressions. You’ll often read code as lists inside lists, where each parentheses-enclosed group represents a call or expression.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
In Clarity, there are public, private, and read-only functions:

* public: can modify chain state and be called externally.
* private: can modify state but only be called within the contract.
* read-only: will fail if they attempt to modify state.
  {% endhint %}

Let's expand on these ideas by walking through that example counter contract line by line.

#### Defining data variables

The built-in Clarity function of `define-data-var` allows you to define a new persisted variable for the contract. Only modifiable by the contract.

```clarity
;; defining a `count` variable to store a variable unsigned integer value
(define-data-var count uint u0)

;; defining a `contract-owner` for a specific `principal` value
(define-data-var contract-owner principal tx-sender)

;; defining a `cost` variable with an initial unsigned integer value of 10
(define-data-var cost uint u10)
```

#### Defining a read-only function to read the current count value

The built-in Clarity function of `define-read-only` defines a public read-only function. Cannot modify data maps or call mutating functions. May return any type.

```clarity
;; allows anyone to read the current `count` value in the contract
(define-read-only (get-count)
  (var-get count)
)
```

#### Defining a public function to increment the count value

This function prints a log event saying it's incrementing a counter, then reads the current counter, adds 1, saves it back on-chain, and returns success.

```clarity
;; Defines a public function named increment that anyone can call
(define-public (increment)
  ;; Starts a begin block, which allows multiple expressions to run in order.
  (begin
    ;; Logs/prints the text "incrementing count" (as a Unicode string) to 
    ;; the transaction output or event stream.
    (print u"incrementing count")
    ;; adds u1 to the current count and wraps the resulting value in a response type
    (ok (var-set count (+ (var-get count) u1)))
  )
)
```

### Interact With Your Contract

The Clarity Playground allows you to call your functions on the right side view via a REPL console that runs a simnet environment.

<details>

<summary><strong>What is Simnet?</strong></summary>

Simnet is optimized for providing fast feedback loops at the cost of correctness. Simnet does not provide a full simulated blockchain environment, so there are no concepts of transaction fees, new blocks, or consensus mechanisms.

Instead, simnet focuses on letting you quickly iterate on your code and test the code of the contract locally through unit testing and integration testing. It’s a good preliminary debugging step before introducing the additional variables that come with a fully-fledged blockchain environment.

Simnet is a local environment spun up on your machine and is a private instance—you cannot share a simnet environment with other devs and collaborate with them—and further, simnet has no persistent state. It resets with each run.

</details>

On page load of the Clarity Playground, the example counter contract is automatically deployed to the REPL console on the right side. If you made any changes to the contract in the code editor on the left view, be sure to click on Deploy.

Calling contracts in the console or calling any externally deployed contracts will need to be passed into the built-in Clarity function called `contract-call?` .

Follow the steps below to interact with your counter contract:

{% stepper %}
{% step %}
**Call the read-only \`get-count\` function**

In the bottom right Clarity command console, paste in the below command to call your `get-count` function to see the current `count` value.

{% code title="clarity command console" %}

```clarity
(contract-call? .contract-0 get-count)
```

{% endcode %}

The console should return an initial value of `u0` since we haven't incremented the `count` yet.
{% endstep %}

{% step %}
**Call the public \`increment\` function**

Now let's finally increment our count value. In the bottom right Clarity command console, paste in the below command to call your `increment` function, which will increment the `count` value by 1.

The console should return a value of `(ok true)` . This means the public function executed successfully and the count should have incremented.

{% code title="clarity command console" %}

```clarity
(contract-call? .contract-0 increment)
```

{% endcode %}
{% endstep %}

{% step %}
**Call our \`get-count\` function again**

To see if our count value was really incremented, let's call our read-only `get-count` function once again.

{% code title="clarity command console" %}

```clarity
(contract-call? .contract-0 get-count)
```

{% endcode %}

The console should now returns a value of `u1` which is exactly what we'd expect.

<div data-with-frame="true"><figure><img src="/files/HkNHFWcgZ8OIobq9t1XW" alt=""><figcaption></figcaption></figure></div>
{% endstep %}
{% endstepper %}

Great! You just interacted with your first Clarity smart contract. Hopefully this gives you a good introduction to how the Clarity smart contract language looks and feels.

***

### Read Access into Bitcoin

Clarity smart contracts on the Stacks layer can also read Bitcoin state and can be triggered by standard Bitcoin transactions. This is because Stacks nodes also run Bitcoin nodes as part of consensus, and they read and index Bitcoin state.

Reading Bitcoin state in Clarity is made by possible by the built-in function: `get-burn-block-info?` and the keyword `burn-block-height` .

* `burn-block-height` : This keyword returns the current block height of the underlying burnchain: Bitcoin. Check out the example snippet below:

```clarity
(> burn-block-height u1000) 
;; returns true if the current height of the underlying burn blockchain has passed 1000 blocks.
```

* `get-burn-block-info?` : This function fetches block data of the burnchain: Bitcoin. Check out the example snippet below:

```clarity
(get-burn-block-info? header-hash u677050)
;; Returns (some 0xe671...)
```

<details>

<summary>Verifying bitcoin transactions in Clarity</summary>

One of the most popular Clarity contracts that leverages read access into Bitcoin is the `clarity-bitcoin-lib` contract, maintained by Friedger. This contract intakes data of a bitcoin transaction and will verify that it was indeed mined in a Bitcoin block.

For more info: <https://github.com/friedger/clarity-bitcoin>

</details>

***

### Flexible and secure modularization

Many DAOs of the major Stacks apps implement a familiar contract design and architecture. This familiarity is inspired by the [ExecutorDAO](https://github.com/MarvinJanssen/executor-dao) framework, written by Marvin Janssen. This ExecutorDAO framework leverages the flexibility of having modularization in your smart contracts by compartmentalizing duties.

The core tenets of the ExecutorDAO framework that make this possible are:

1. Proposals are smart contracts.
2. The core executes, the extensions give form.
3. Ownership control happens via sending context.

{% tabs %}
{% tab title="Main DAO contract" %}
The main DAO contract acts as the core contract where its sole purpose is to execute proposals and to keep a list of authorised extensions.

{% code title="dao.clar" expandable="true" %}

```clarity
(use-trait proposal-trait .proposal-trait.proposal-trait)
(use-trait extension-trait .extension-trait.extension-trait)

;; ...

;; --- Authorisation check
(define-private (is-self-or-extension)
	(ok (asserts! (or (is-eq tx-sender (as-contract tx-sender)) (is-extension contract-caller)) err-unauthorised))
)

;; ...

;; --- Admin function to execute proposals
(define-public (execute (proposal <proposal-trait>) (sender principal))
	(begin
		(try! (is-self-or-extension))
		(asserts! (map-insert executed-proposals (contract-of proposal) block-height) err-already-executed)
		(print {event: "execute", proposal: proposal})
		(as-contract (contract-call? proposal execute sender))
	)
)
```

{% endcode %}
{% endtab %}

{% tab title="A proposal extension contract" %}
This proposal contract updates the whitelist of an example `.nft-escrow` contract that is owned by the main DAO contract. This proposal contract implements the `proposal-trait` and is passed into the main DAO contract's `execute` function for final approved execution.

{% code title="proposal.clar" %}

```clarity
(impl-trait .proposal-trait.proposal-trait)

(define-public (execute (sender principal))
	(contract-call? .nft-escrow set-whitelisted .some-nft true)
)
```

{% endcode %}
{% endtab %}
{% endtabs %}

***

### Testing Clarity Smart Contracts

Once you get to writing more advanced smart contracts, properly testing them is paramount to protecting anyone who interacts with your contract.

{% hint style="danger" %}
Smart contracts are immutable once deployed. Bugs are permanent. Test them thoroughly.
{% endhint %}

* [Rendezvous Fuzz Testing](/rendezvous/overview): Use Rendezvous to hammer your contract with random inputs. It helps expose edge cases and vulnerabilities.
* [Unit Testing in Clarinet](/clarinet/testing-with-clarinet-sdk): Unit testing verifies that individual contract functions behave as expected.

***

### Auditing Clarity Smart Contracts

Auditors provide an independent, expert review of your smart contracts to identify vulnerabilities, logic flaws, edge cases, or design risks that might be missed during development. Here are a few Clarity smart contract auditors that are part of the Stacks community.

* [**List of professional auditors**](https://www.stacks.co/explore/ecosystem?category=Auditors#tools)

***

### Deploying Clarity Smart Contracts

When you deploy a Clarity smart contract, you're uploading its code to the Stacks blockchain, making it immutable and publicly accessible. Deployment involves submitting a transaction that includes the smart contract code and specific parameters. Once deployed, the contract's logic is fixed, providing transparency and security by ensuring that no further changes can be made.

{% hint style="warning" %}
Do note that not all methods below will support the latest Clarity version.
{% endhint %}

Here are a few different ways to deploy a Clarity smart contract:

<details>

<summary>Clarinet</summary>

Clarinet is the CLI tool for all things Clarity contract development. Deploying contracts via Clarinet is by far the most conventional and common method. Using Clarinet also provides a myriad amount of configuration options for how you want your deployment to look like.

Check out the dedicated guide [here](/clarinet/contract-deployment) to learn how you can deploy contracts with Clarinet.

</details>

<details>

<summary>Stacks.js</summary>

Stacks.js is the frontend javascript library for interacting with the Stacks network. Many token launchpads, that enable no-code solutions for deploying a token, utilize Stacks.js for deploying contracts on the frontend or backend script.

Check out the dedicated guide [here](/stacks.js/contract-deployment) to learn how you can deploy contracts with Stacks.js.

</details>

<details>

<summary>Stacks Explorer Sandbox</summary>

The Sandbox in the [Stacks Explorer](https://explorer.stacks.co/) is an interactive Clarity code editor allowing you to write contracts, call functions of existing contracts, and also deploy contracts directly.

<div data-with-frame="true"><figure><img src="/files/Jiow9PXsHxpZ2uAQ4hJI" alt=""><figcaption></figcaption></figure></div>

</details>

***

### Smart Contract Monitoring & Alerts

Utilize tools that provide the event-driven infrastructure developers need to observe, index, and react to on-chain activity.

<details>

<summary>Contract Monitoring</summary>

The [Contract Monitoring](https://platform.hiro.so/contract-monitoring) features, available in the Hiro Platform, enable you to set alerts when specific functions are called in your smart contracts. This enables you to detect and respond to suspicious contract activities, enhancing the security of your app throughout the contract lifecycle.

</details>

<details>

<summary>Chainhooks</summary>

[Chainhooks](https://docs.hiro.so/tools/chainhook) indexes Stacks & Bitcoin data, exposes queryable APIs, tracks contract state and transactions. You simply describe your chainhook filters and consume webhooks. The service handles queueing, retries, tier limits, observability, and parity between testnet and mainnet.

</details>

***

### Additional Resources

This brief overview should get your feet wet with Clarity. For deeper learning, we recommend:

* [Clarity Book](https://book.clarity-lang.org/title-page.html)
* [Clarity Universe](https://clarity-lang.org/universe)
* [Clarity Playground](https://play.stackslabs.com/)
* [Clarity Camp](https://learn.stacks.org/course/clarity-camp)
* \[[StacksGov](https://github.com/stacksgov/sips/blob/main/sips/sip-002/sip-002-smart-contract-language.md)] SIP-002 The Clarity Smart Contract Language
* \[[Hiro Blog](https://www.hiro.so/blog/web3-programming-languages-clarity-vs-solidity)] Web3 Programming Languages: Clarity vs. Solidity
* \[[Stacks YT](https://youtu.be/hFqH1bJEvnw?si=yQADCvRNNjotuAga)] How Stacks' Language Clarity Enables Next Gen Smart Contracts
* \[[StacksDevs YT](https://www.youtube.com/watch?v=WZe1DgJ1w-E)] How Stacks’ Smart Contract Language Prevents Exploitation
* \[[Chainlink YT](https://youtu.be/OAVwd6SNJVU?si=UgfjmisBRbIYv27U)] Marvin Janssen: Clarity Smart Contracts for Stacks
* [100+ Days of Clarity video series by Setzeus](https://youtube.com/playlist?list=PLFHm9eE6H5uhNQ4cUXRE-4HkXF1ekS0ZG\&si=q0NmD-e9_QBomK3a)
* \[[waits.dev](https://waits.dev/writing/clarity-vs-solidity)] Clarity vs Solidity

If you prefer jumping into Clarity's reference materials for definitions on all its types, functions, and keywords, head to [Clarity's Reference section](/reference/clarity/functions) of the docs.


# Create a Token

Many Stacks projects need tokens to establish membership or as an incentive for building a thriving Web3 community. When building a project, you need to not only think about whether your project needs a token (and if so, what type), but also what other Stacks tokens your app will need to interact with.

Rather than needing to work with external libraries, Clarity has built-in functions that make working with fungible and non-fungible tokens a breeze. Below are the 3 different types of tokens available on Stacks. Click into any one of them to learn what they are and the different ways to have them launched for your project.

### Fungible Tokens

Fungible tokens on Stacks are digital assets that are interchangeable and identical in value, much like traditional currencies such as the dollar or bitcoin. They are typically used for utilities like payments, rewards, and participation rights within decentralized applications on the Stacks blockchain.

[**Launch a fungible token**](/get-started/create-a-token/fungible-tokens)

### Non-Fungible Tokens

Non-fungible tokens (NFTs) on Stacks are unique digital assets that cannot be exchanged on a one-to-one basis, as each token holds distinct information and value. They are often used for representing ownership of digital art, collectibles, and other unique items within decentralized applications on the Stacks network. NFTs provide a way to authenticate and trade the unique characteristics of digital goods securely.

[**Launch a non-fungible token**](/get-started/create-a-token/non-fungible-tokens)

### Semi-Fungible Tokens

Semi-fungible tokens (SFTs) are a type of digital asset that possess qualities of both fungible and non-fungible tokens. Initially, SFTs can be exchanged on a one-to-one basis like fungible tokens because they represent identical assets or goods, often in specific series or batches. However, once redeemed or utilized, they transform into non-fungible tokens, acquiring unique attributes or identification. This makes SFTs versatile for applications such as event tickets, vouchers, or gaming items where controlled fungibility is beneficial.

[**Launch a semi-fungible token**](/get-started/create-a-token/semi-fungible-tokens)


# Fungible Tokens

A guide to help you create your own fungible tokens

<div data-with-frame="true"><figure><img src="/files/5VW9Qcu8xsagNVCFC0O5" alt=""><figcaption></figcaption></figure></div>

Creating a fungible token on Stacks can happen a few different ways — using no-code launchpads or writing your own Clarity smart contract. This guide helps you pick the best path for your goals and gives you the implementation details to ship confidently, whether you’re deploying with clicks or code.

### Custom Development

For developers who want full control over their token implementation, here’s how to create a custom SIP-010 token on Stacks using Clarity. But before you deploy the token contract, you must have your token contract conform to the SIP-010 trait standard.

{% stepper %}
{% step %}
**Define SIP-010 fungible token trait**

<details>

<summary><strong>What is SIP-010?</strong></summary>

[SIP-010](https://github.com/stacksgov/sips/blob/main/sips/sip-010/sip-010-fungible-token-standard.md) is the standard for defining fungible tokens on Stacks. Defining a common interface (known in Clarity as a "trait") allows different smart contracts, apps, and wallets to interoperate with fungible token contracts in a reusable way.

</details>

Below is an implementation of the SIP-010 trait standard for fungible tokens. You can use the existing minimal standard SIP-010 trait or extend it by adding in your own custom traits. But the requirements of the SIP-010 traits are necessary to have at the minimum.

{% code title="SIP-010 trait implementation" expandable="true" %}

```clarity
(define-trait sip-010-trait
  (
    ;; Transfer from the caller to a new principal
    (transfer (uint principal principal (optional (buff 34))) (response bool uint))

    ;; the human readable name of the token
    (get-name () (response (string-ascii 32) uint))

    ;; the ticker symbol, or empty if none
    (get-symbol () (response (string-ascii 32) uint))

    ;; the number of decimals used, e.g. 6 would mean 1_000_000 represents 1 token
    (get-decimals () (response uint uint))

    ;; the balance of the passed principal
    (get-balance (principal) (response uint uint))

    ;; the current total supply (which does not need to be a constant)
    (get-total-supply () (response uint uint))

    ;; an optional URI that represents metadata of this token
    (get-token-uri () (response (optional (string-utf8 256)) uint))
  )
)
```

{% endcode %}

All we are doing here is defining the function signatures for functions we'll need to implement in our token contract, which we can see a simple version of below.
{% endstep %}

{% step %}
**Implement SIP-010 trait in token contract**

Any token contract that wants to conform to the SIP-010 fungible token standard for Stacks needs to have this trait "implemented" in their token contract. See the below minimal token contract example of how this is done.

{% code title="token-contract-clar" expandable="true" %}

```clarity
;; This contract implements the SIP-010 community-standard Fungible Token trait.
(impl-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)

;; Define the FT, with no maximum supply
(define-fungible-token clarity-coin)

;; Define errors
(define-constant ERR_OWNER_ONLY (err u100))
(define-constant ERR_NOT_TOKEN_OWNER (err u101))

;; Define constants for contract
(define-constant CONTRACT_OWNER tx-sender)
(define-constant TOKEN_NAME "Clarity Coin")
(define-constant TOKEN_SYMBOL "CC")
(define-constant TOKEN_DECIMALS u6) ;; 6 units displayed past decimal, e.g. 1.000_000 = 1 token

(define-data-var token-uri (string-utf8 256) u"https://hiro.so") ;; utf-8 string with token metadata host

;; SIP-010 function: Get the token balance of a specified principal
(define-read-only (get-balance (who principal))
  (ok (ft-get-balance clarity-coin who))
)

;; SIP-010 function: Returns the total supply of fungible token
(define-read-only (get-total-supply)
  (ok (ft-get-supply clarity-coin))
)

;; SIP-010 function: Returns the human-readable token name
(define-read-only (get-name)
  (ok TOKEN_NAME)
)

;; SIP-010 function: Returns the symbol or "ticker" for this token
(define-read-only (get-symbol)
  (ok TOKEN_SYMBOL)
)

;; SIP-010 function: Returns number of decimals to display
(define-read-only (get-decimals)
  (ok TOKEN_DECIMALS)
)

;; SIP-010 function: Returns the URI containing token metadata
(define-read-only (get-token-uri)
  (ok (some (var-get token-uri)))
)

;; Properly updates token URI by emitting a SIP-019 token metadata update notification
(define-public (set-token-uri (value (string-utf8 256)))
    (begin
        (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_OWNER_ONLY)
        (var-set token-uri value)
        (ok (print {
              notification: "token-metadata-update",
              payload: {
                contract-id: current-contract,
                token-class: "ft"
              }
            })
        )
    )
)

;; Mint new tokens and send them to a recipient.
;; Only the contract deployer can perform this operation.
(define-public (mint (amount uint) (recipient principal))
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_OWNER_ONLY)
    (ft-mint? clarity-coin amount recipient)
  )
)

;; SIP-010 function: Transfers tokens to a recipient
;; Sender must be the same as the caller to prevent principals from transferring tokens they do not own.
(define-public (transfer
  (amount uint)
  (sender principal)
  (recipient principal)
  (memo (optional (buff 34)))
)
  (begin
    ;; #[filter(amount, recipient)]
    (asserts! (or (is-eq tx-sender sender) (is-eq contract-caller sender)) ERR_NOT_TOKEN_OWNER)
    (try! (ft-transfer? clarity-coin amount sender recipient))
    (match memo to-print (print to-print) 0x)
    (ok true)
  )
)
```

{% endcode %}

This is the Clarity code we need in order to create an fungible token, with one additional function, `mint` that allows us to actually create a new fungible tokens. This `mint` function is not needed to adhere to the trait.

The token contract example above is passing in an already deployed trait on mainnet into the `impl-trait` function. You can use this same deployed trait for your own token contract as well.

{% hint style="success" %}
Deployed SIP-010 trait contracts you can directly implement in your custom token contract:

* \[mainnet] [SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait](https://explorer.hiro.so/txid/SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard?chain=mainnet)
* \[testnet] [ST1NXBK3K5YYMD6FD41MVNP3JS1GABZ8TRVX023PT.sip-010-trait-ft-standard.sip-010-trait](https://explorer.hiro.so/txid/ST1NXBK3K5YYMD6FD41MVNP3JS1GABZ8TRVX023PT.sip-010-trait-ft-standard?chain=testnet)

Reminder: when implementing these deployed traits in your contract, be sure to also add them as a contract requirement in Clarinet.
{% endhint %}
{% endstep %}
{% endstepper %}

### No-code Platforms

Use community built no-code platforms that can quickly help you deploy tokens.

<details>

<summary>STX.City</summary>

[STX.CITY](https://stx.city/) is a one-click platform for launching tokens on Stacks. The platform is a comprehensive toolkit for memecoin creators, enabling them to grow their communities through features like AMM listing support (such as on [Alex](https://alexgo.io/), [Velar](https://velar.com/), and [Stackswap](https://app.stackswap.org/)), airdrops, token donations, and burn mechanisms.

Check out [this](https://www.hiro.so/blog/building-stx-city-as-a-solo-dev-on-stacks) blog post by the founder of STX.City for more information.

</details>

### Best Practices

Here are some things to consider when creating your token and after your token is launched.

<details>

<summary>How to format the token metadata?</summary>

Example token metadata taken from the sBTC token:

```json
// https://ipfs.io/ipfs/bafkreibqnozdui4ntgoh3oo437lvhg7qrsccmbzhgumwwjf2smb3eegyqu

{
  "sip": 16,
  "name": "sBTC",
  "description": "BTC is a 1:1 Bitcoin-backed asset on the Stacks Bitcoin L2 that will allow developers to leverage the security, network effects, and .5T in latent capital of the Bitcoin network.",
  "image": "https://ipfs.io/ipfs/bafkreiffe46h5voimvulxm2s4ddszdm4uli4rwcvx34cgzz3xkfcc2hiwi",
  "properties": {
    "decimals": 8,
    "external_url": "https://sbtc.tech"
  }
}
```

Check out the [SIP-016](https://github.com/stacksgov/sips/blob/main/sips/sip-016/sip-016-token-metadata.md) standard for how you should define the schema of your metadata.

</details>

<details>

<summary>How would I properly update my token metadata?</summary>

If you plan on updating your token's metadata in the future, you should definitely implement a [SIP-019](https://github.com/stacksgov/sips/blob/main/sips/sip-019/sip-019-token-metadata-update-notifications.md) compliant token metadata update notification. Take a look at the example token contract above and you'll notice the `set-token-uri` function emits a SIP-019 compliant print event.

```clarity
;; ...
(define-public (set-token-uri (value (string-utf8 256)))
    (begin
        (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_OWNER_ONLY)
        (var-set token-uri value)
        (ok (print {
              notification: "token-metadata-update",
              payload: {
                contract-id: current-contract,
                token-class: "ft"
              }
            })
        )
    )
)
;; ...
```

Hiro’s [Token Metadata API](https://www.hiro.so/token-metadata-api) watches for that specific print event (specifically the notification of "token-metadata-update") on the network and auto-updates the API’s database to reflect a change in the existing token’s metadata.

If your token contract did not implement this print event, you could use the helper contract below to invoke a function that'll emit the same print event notification. Just invoke the `ft-metadata-update-notify` function of this contract below:

[SP1H6HY2ZPSFPZF6HBNADAYKQ2FJN75GHVV95YZQ.token-metadata-update-notify](https://explorer.hiro.so/txid/SP1H6HY2ZPSFPZF6HBNADAYKQ2FJN75GHVV95YZQ.token-metadata-update-notify?chain=mainnet)

</details>

### Additional Resources

* \[[dev.to](https://dev.to/kamalthedev/ethereum-vs-bitcoin-a-deep-dive-into-token-standards-erc-20-vs-sip-10-vs-brc20-vs-stx20-12na)] A Deep Dive into Token Standards: ERC-20 vs. SIP-10 vs. BRC20 vs. STX20
* \[[StacksGov](https://github.com/stacksgov/sips/blob/main/sips/sip-010/sip-010-fungible-token-standard.md)] SIP-010 Standard Trait Definition for Fungible Tokens
* \[[StacksGov](https://github.com/stacksgov/sips/blob/main/sips/sip-016/sip-016-token-metadata.md)] SIP-016 Schema Definition for Metadata for Digital Assets
* \[[StacksGov](https://github.com/stacksgov/sips/blob/main/sips/sip-019/sip-019-token-metadata-update-notifications.md)] SIP-019 Notifications for Token Metadata Updates
* \[[contract](https://explorer.hiro.so/txid/SP1H6HY2ZPSFPZF6HBNADAYKQ2FJN75GHVV95YZQ.token-metadata-update-notify?chain=mainnet)] SP1H6HY2ZPSFPZF6HBNADAYKQ2FJN75GHVV95YZQ.token-metadata-update-notify
* \[[StacksDevs YT](https://youtu.be/v0_Mexz3KJ8?si=iGMyxQX2lSktOTWp)] Fungible Token Standard (SIP-10) Tutorial For Bitcoin L2 Stacks
* \[[LearnWeb3](https://learnweb3.io/lessons/sip-010-fungible-tokens-and-traits/)] SIP-010 Fungible Tokens & Traits
* \[[Medium @n.campos.rojas](https://medium.com/@n.campos.rojas/learn-how-to-create-fungible-tokens-on-stacks-versus-on-ethereum-a6dae4986863)] Learn how to create fungible tokens on Stacks (versus on Ethereum)


# Non-Fungible Tokens

A guide to help you create your own non-fungible tokens

<div data-with-frame="true"><figure><img src="/files/EKR5GTOen3rzj7VQrR9O" alt=""><figcaption></figcaption></figure></div>

Create an NFT with Stacks because it builds **on Bitcoin** — inheriting the security and permanence of the most durable chain via Proof-of-Transfer. Clarity smart contracts make logic easy to audit, reducing the guessing and attack surface common in NFT projects. Plus, Stacks NFTs tap into a Bitcoin-aligned community that values ownership, longevity, and real on-chain utility.

### Custom Development

For developers who want full control over their token implementation, here’s how to create a custom SIP-009 NFT on Stacks using Clarity. But before you deploy the NFT contract, you must have your NFT contract conform to the SIP-009 trait standard.

{% stepper %}
{% step %}
**Define SIP-009 non-fungible token trait**

<details>

<summary><strong>What is SIP-009?</strong></summary>

[SIP-009](https://github.com/stacksgov/sips/blob/main/sips/sip-009/sip-009-nft-standard.md) is the standard for defining fungible tokens on Stacks. Defining a common interface (known in Clarity as a "trait") allows different smart contracts, apps, and wallets to interoperate with non-fungible token contracts in a reusable way. Its primary purpose is to ensure that NFTs are composable and different tools know how to interact with them.

</details>

Below is an implementation of the SIP-009 trait standard for non-fungible tokens. You can use the existing minimal standard SIP-009 trait or extend it by adding in your own custom traits. But the requirements of the SIP-009 traits are necessary to have at the minimum.

{% code title="NFT trait standard" expandable="true" %}

```clarity
(define-trait nft-trait
  (
    ;; Last token ID, limited to uint range
    (get-last-token-id () (response uint uint))

    ;; URI for metadata associated with the token
    (get-token-uri (uint) (response (optional (string-ascii 256)) uint))

     ;; Owner of a given token identifier
    (get-owner (uint) (response (optional principal) uint))

    ;; Transfer from the sender to a new principal
    (transfer (uint principal principal) (response bool uint))
  )
)
```

{% endcode %}

All we are doing here is defining the function signatures for functions we'll need to implement in our NFT contract, which we can see a simple version of below.
{% endstep %}

{% step %}
**Implement SIP-009 trait in NFT contract**

Any NFT contract that wants to conform to the SIP-009 non-fungible token standard for Stacks needs to have this trait "implemented" in their NFT contract. See the below minimal NFT contract example of how this is done.

{% code title="non-fungible-token.clar" expandable="true" %}

```clarity
;; This contract implements the SIP-009 community-standard Non-Fungible Token trait
(impl-trait 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait)

;; Define the NFT's name
(define-non-fungible-token Your-NFT-Name uint)

;; Keep track of the last minted token ID
(define-data-var last-token-id uint u0)

;; Define constants
(define-constant CONTRACT_OWNER tx-sender)
(define-constant COLLECTION_LIMIT u1000) ;; Limit to series of 1000

(define-constant ERR_OWNER_ONLY (err u100))
(define-constant ERR_NOT_TOKEN_OWNER (err u101))
(define-constant ERR_SOLD_OUT (err u300))

(define-data-var base-uri (string-ascii 256) "https://your.api.com/path/to/collection/{id}")

;; SIP-009 function: Get the last minted token ID.
(define-read-only (get-last-token-id)
  (ok (var-get last-token-id))
)

;; SIP-009 function: Get link where token metadata is hosted
(define-read-only (get-base-uri (token-id uint))
  (ok (some (var-get base-uri)))
)

;; SIP-009 function: Get the owner of a given token
(define-read-only (get-owner (token-id uint))
  (ok (nft-get-owner? Your-NFT-Name token-id))
)

;; SIP-019 compliant token metadata update notification
(define-public (set-base-uri (value (string-ascii 256)))
    (begin
        (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_OWNER_ONLY)
        (var-set base-uri value)
        (ok (print {
              notification: "token-metadata-update",
              payload: {
                token-class: "nft",
                contract-id: current-contract,
              }
            })
        )
    )
)

;; SIP-009 function: Transfer NFT token to another owner.
(define-public (transfer (token-id uint) (sender principal) (recipient principal))
  (begin
    ;; #[filter(sender)]
    (asserts! (is-eq tx-sender sender) ERR_NOT_TOKEN_OWNER)
    (nft-transfer? Your-NFT-Name token-id sender recipient)
  )
)

;; Mint a new NFT.
(define-public (mint (recipient principal))
  ;; Create the new token ID by incrementing the last minted ID.
  (let ((token-id (+ (var-get last-token-id) u1)))
    ;; Ensure the collection stays within the limit.
    (asserts! (< (var-get last-token-id) COLLECTION_LIMIT) ERR_SOLD_OUT)
    ;; Only the contract owner can mint.
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_OWNER_ONLY)
    ;; Mint the NFT and send it to the given recipient.
    (try! (nft-mint? Your-NFT-Name token-id recipient))

    ;; Update the last minted token ID.
    (var-set last-token-id token-id)
    ;; Return a success status and the newly minted NFT ID.
    (ok token-id)
  )
)
```

{% endcode %}

This is the Clarity code we need in order to create an NFT, with one additional function, `mint` that allows us to actually create a new NFT. This `mint` function is not needed to adhere to the trait.

The token contract example above is passing in an already deployed trait on mainnet into the `impl-trait` function. You can use this same deployed trait for your own NFT contract as well.

{% hint style="success" %}
Deployed SIP-009 trait contracts you can directly implement in your custom token contract:

* \[mainnet] SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait
* \[testnet] ST1NXBK3K5YYMD6FD41MVNP3JS1GABZ8TRVX023PT.nft-trait

Reminder: when implementing these deployed traits in your contract, be sure to also add them as a contract requirement in Clarinet.
{% endhint %}
{% endstep %}
{% endstepper %}

### Best Practices

Here are some things to consider when creating your NFT and after your NFT is launched.

<details>

<summary>How to format the NFT metadata?</summary>

Check out the [SIP-016](https://github.com/stacksgov/sips/blob/main/sips/sip-016/sip-016-token-metadata.md) standard for how you should define the schema of your metadata.

</details>

<details>

<summary>How would I properly update my NFT metadata?</summary>

If you plan on updating your NFT's metadata in the future, you should definitely implement a function that emits a [SIP-019](https://github.com/stacksgov/sips/blob/main/sips/sip-019/sip-019-token-metadata-update-notifications.md) compliant token metadata update notification. Take a look at the example NFT contract above and you'll notice the `set-base-uri` function emits a SIP-019 compliant print event.

<pre class="language-clarity"><code class="lang-clarity">;; ...
(define-public (set-base-uri (value (string-ascii 256)))
    (begin
        (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_OWNER_ONLY)
        (var-set base-uri value)
        (ok (print {
              notification: "token-metadata-update",
              payload: {
<strong>                token-class: "nft",
</strong>                contract-id: current-contract,
              }
            })
        )
    )
)
;; ...
</code></pre>

Hiro’s [Token Metadata API](https://www.hiro.so/token-metadata-api) watches for that specific print event (specifically the notification of "token-metadata-update") on the network and auto-updates the API’s database to reflect a change in the existing NFT’s metadata.

If your NFT contract did not implement this print event, you could use the helper contract below to invoke a function that'll emit the same print event notification. Just invoke the `nft-metadata-update-notify` function of this contract below:

[SP1H6HY2ZPSFPZF6HBNADAYKQ2FJN75GHVV95YZQ.token-metadata-update-notify](https://explorer.hiro.so/txid/SP1H6HY2ZPSFPZF6HBNADAYKQ2FJN75GHVV95YZQ.token-metadata-update-notify?chain=mainnet)

</details>

### Additional Resources

* \[[Stacks](https://www.stacks.co/explore/nfts)] Explore NFTs on Stacks
* \[[Clarity Book](https://book.clarity-lang.org/ch10-01-sip009-nft-standard.html)] SIP009: the NFT standard
* \[[StacksGov](https://github.com/stacksgov/sips/blob/main/sips/sip-010/sip-010-fungible-token-standard.md)] SIP-009 Standard Trait Definition for Non-Fungible Tokens
* \[[StacksGov](https://github.com/stacksgov/sips/blob/main/sips/sip-016/sip-016-token-metadata.md)] SIP-016 Schema Definition for Metadata for Digital Assets
* \[[StacksGov](https://github.com/stacksgov/sips/blob/main/sips/sip-019/sip-019-token-metadata-update-notifications.md)] SIP-019 Notifications for Token Metadata Updates
* \[[contract](https://explorer.hiro.so/txid/SP1H6HY2ZPSFPZF6HBNADAYKQ2FJN75GHVV95YZQ.token-metadata-update-notify?chain=mainnet)] SP1H6HY2ZPSFPZF6HBNADAYKQ2FJN75GHVV95YZQ.token-metadata-update-notify
* \[[Hiro YT](https://youtu.be/Hejsz-pivM4?si=SrOlgC9KK6YQvEy7)] How to Display NFTs in a Wallet Using the Token Metadata API
* \[[Hiro YT](https://youtu.be/xwbXNgSvMkk?si=Dl8KEL2KsmPy1kON)] A Beginner's Overview of the Megapont Ape NFT Clarity Smart Contract
* \[[Hiro YT](https://youtu.be/Ajuq6j2NXM8?si=Gj-Z5sxJ28FRyPmN)] Stacker Chat with Muneeb Ali: Diving Deeper into Bitcoin NFTs
* \[[Hiro Blog](https://www.hiro.so/blog/breaking-down-nft-code-snippets-in-clarity)] Breaking Down NFT Code Snippets in Clarity
* \[[Hiro Blog](https://www.hiro.so/blog/how-sigle-built-nft-gated-features-in-their-app)] How Sigle Built NFT-Gated Features in Their App


# Semi-Fungible Tokens

A guide to help you create your own semi-fungible tokens

Semi-fungible tokens (SFTs) are a hybrid token structure that embraces parts of both FTs (fungible tokens) and NFTs. SFTs are interchangeable (like FTs) and can be traded between users like cash—1 SFT has the same value as another SFT in the same collection. But each SFT also has a unique identifier (like NFTs).

SFTs are also particularly well suited for Web3 gaming and applications that need to issue lots of different tokens because SFTs enable different asset classes to be managed by a single smart contract (which as a developer is easier to manage and as a user results in cheaper transaction fees).

### Custom Development

For developers who want full control over their SFT implementation, here’s how to create a custom SIP-013 SFT on Stacks using Clarity. But before you deploy the SFT contract, you must have your SFT contract conform to the SIP-013 trait standard.

{% stepper %}
{% step %}

#### Define SIP-013 semi-fungible token trait

<details>

<summary><strong>What is SIP-013?</strong></summary>

[SIP-013](https://github.com/stacksgov/sips/blob/main/sips/sip-013/sip-013-semi-fungible-token-standard.md) is the standard for defining semi-fungible tokens on Stacks. Defining a common interface (known in Clarity as a "trait") allows different smart contracts, apps, and wallets to interoperate with semi-fungible token contracts in a reusable, standard way.

</details>

Below is an implementation of the SIP-013 trait standard for semi-fungible tokens. You can use the existing minimal standard SIP-013 trait or extend it by adding in your own custom traits. But the requirements of the SIP-013 traits are necessary to have at the minimum.

{% code title="SFT trait standard" expandable="true" %}

```clarity
(define-trait sip013-semi-fungible-token-trait
	(
		;; Get a token type balance of the passed principal.
		(get-balance (uint principal) (response uint uint))

		;; Get the total SFT balance of the passed principal.
		(get-overall-balance (principal) (response uint uint))

		;; Get the current total supply of a token type.
		(get-total-supply (uint) (response uint uint))

		;; Get the overall SFT supply.
		(get-overall-supply () (response uint uint))

		;; Get the number of decimal places of a token type.
		(get-decimals (uint) (response uint uint))

		;; Get an optional token URI that represents metadata for a specific token.
		(get-token-uri (uint) (response (optional (string-ascii 256)) uint))

		;; Transfer from one principal to another.
		(transfer (uint uint principal principal) (response bool uint))

		;; Transfer from one principal to another with a memo.
		(transfer-memo (uint uint principal principal (buff 34)) (response bool uint))
	)
)

```

{% endcode %}

All we are doing here is defining the function signatures for functions we'll need to implement in our SFT contract, which we can see a simple version of below.

**\[optional] transfer-many specification**\
SIP013 Semi-fungible tokens can also optionally implement the trait `sip013-transfer-many-trait` to offer a built-in "transfer-many" features for bulk token transfers.

{% code title="SFT transfer many trait" %}

```clarity
(define-trait sip013-transfer-many-trait
	(
		;; Transfer many tokens at once.
		(transfer-many ((list 200 {token-id: uint, amount: uint, sender: principal, recipient: principal})) (response bool uint))

		;; Transfer many tokens at once with memos.
		(transfer-many-memo ((list 200 {token-id: uint, amount: uint, sender: principal, recipient: principal, memo: (buff 34)})) (response bool uint))
	)
)
```

{% endcode %}
{% endstep %}

{% step %}

#### Implement SIP-013 trait in SFT contract

Any SFT contract that wants to conform to the SIP-013 semi-fungible token standard for Stacks needs to have this trait "implemented" in their SFT contract. See the below minimal SFT contract example of how this is done.

{% code title="semi-fungible-token.clar" expandable="true" %}

```clarity
(impl-trait 'SPDBEG5X8XD50SPM1JJH0E5CTXGDV5NJTKAKKR5V.sip013-semi-fungible-token-trait.sip013-semi-fungible-token-trait)
(impl-trait 'SPDBEG5X8XD50SPM1JJH0E5CTXGDV5NJTKAKKR5V.sip013-transfer-many-trait.sip013-transfer-many-trait)

(define-fungible-token semi-fungible-token)
(define-non-fungible-token semi-fungible-token-id {token-id: uint, owner: principal})
(define-map token-balances {token-id: uint, owner: principal} uint)
(define-map token-supplies uint uint)

(define-constant contract-owner tx-sender)

(define-constant err-owner-only (err u100))
(define-constant err-insufficient-balance (err u1))
(define-constant err-invalid-sender (err u4))

(define-private (set-balance (token-id uint) (balance uint) (owner principal))
	(map-set token-balances {token-id: token-id, owner: owner} balance)
)

(define-private (get-balance-uint (token-id uint) (who principal))
	(default-to u0 (map-get? token-balances {token-id: token-id, owner: who}))
)

(define-read-only (get-balance (token-id uint) (who principal))
	(ok (get-balance-uint token-id who))
)

(define-read-only (get-overall-balance (who principal))
	(ok (ft-get-balance semi-fungible-token who))
)

(define-read-only (get-total-supply (token-id uint))
	(ok (default-to u0 (map-get? token-supplies token-id)))
)

(define-read-only (get-overall-supply)
	(ok (ft-get-supply semi-fungible-token))
)

(define-read-only (get-decimals (token-id uint))
	(ok u0)
)

(define-read-only (get-token-uri (token-id uint))
	(ok none)
)

;; #[allow(unchecked_params)]
(define-public (transfer (token-id uint) (amount uint) (sender principal) (recipient principal))
	(let
		(
			(sender-balance (get-balance-uint token-id sender))
		)
		(asserts! (or (is-eq sender tx-sender) (is-eq sender contract-caller)) err-invalid-sender)
		(asserts! (<= amount sender-balance) err-insufficient-balance)
		(try! (ft-transfer? semi-fungible-token amount sender recipient))
		(try! (tag-nft-token-id {token-id: token-id, owner: sender}))
		(try! (tag-nft-token-id {token-id: token-id, owner: recipient}))
		(set-balance token-id (- sender-balance amount) sender)
		(set-balance token-id (+ (get-balance-uint token-id recipient) amount) recipient)
		(print {type: "sft_transfer", token-id: token-id, amount: amount, sender: sender, recipient: recipient})
		(ok true)
	)
)

(define-public (transfer-memo (token-id uint) (amount uint) (sender principal) (recipient principal) (memo (buff 34)))
	(begin
		(try! (transfer token-id amount sender recipient))
		(print memo)
		(ok true)
	)
)

(define-private (transfer-many-iter (item {token-id: uint, amount: uint, sender: principal, recipient: principal}) (previous-response (response bool uint)))
	(match previous-response prev-ok (transfer (get token-id item) (get amount item) (get sender item) (get recipient item)) prev-err previous-response)
)

(define-public (transfer-many (transfers (list 200 {token-id: uint, amount: uint, sender: principal, recipient: principal})))
	(fold transfer-many-iter transfers (ok true))
)

(define-private (transfer-many-memo-iter (item {token-id: uint, amount: uint, sender: principal, recipient: principal, memo: (buff 34)}) (previous-response (response bool uint)))
	(match previous-response prev-ok (transfer-memo (get token-id item) (get amount item) (get sender item) (get recipient item) (get memo item)) prev-err previous-response)
)

(define-public (transfer-many-memo (transfers (list 200 {token-id: uint, amount: uint, sender: principal, recipient: principal, memo: (buff 34)})))
	(fold transfer-many-memo-iter transfers (ok true))
)

(define-public (mint (token-id uint) (amount uint) (recipient principal))
	(begin
		(asserts! (is-eq tx-sender contract-owner) err-owner-only)
		(try! (ft-mint? semi-fungible-token amount recipient))
		(try! (tag-nft-token-id {token-id: token-id, owner: recipient}))
		(set-balance token-id (+ (get-balance-uint token-id recipient) amount) recipient)
		(map-set token-supplies token-id (+ (unwrap-panic (get-total-supply token-id)) amount))
		(print {type: "sft_mint", token-id: token-id, amount: amount, recipient: recipient})
		(ok true)
	)
)

(define-private (tag-nft-token-id (nft-token-id {token-id: uint, owner: principal}))
	(begin
		(and
			(is-some (nft-get-owner? semi-fungible-token-id nft-token-id))
			(try! (nft-burn? semi-fungible-token-id nft-token-id (get owner nft-token-id)))
		)
		(nft-mint? semi-fungible-token-id nft-token-id (get owner nft-token-id))
	)
)
```

{% endcode %}

This is the Clarity code we need in order to create a SFT, with an additional function, `mint` that allows us to actually create a new SFT. This `mint` function is not needed to adhere to the trait.

The token contract example above is passing in already deployed traits on mainnet into the `impl-trait` function. You can use these same deployed traits for your own SFT contract as well.

{% hint style="success" %}
Deployed SIP-013 trait contracts you can directly implement in your custom token contract:

* \[mainnet] SPDBEG5X8XD50SPM1JJH0E5CTXGDV5NJTKAKKR5V.sip013-semi-fungible-token-trait
* \[mainnet] SPDBEG5X8XD50SPM1JJH0E5CTXGDV5NJTKAKKR5V.sip013-transfer-many-trait

Reminder: when implementing these deployed traits in your contract, be sure to also add them as contract requirements in Clarinet.
{% endhint %}
{% endstep %}
{% endstepper %}

### Best Practices

<details>

<summary>How to deal with post-conditions on SFTs?</summary>

Check out the SIP-013 standard for more info on dealing with post-conditions for SFTs.

</details>

### Additional Resources

* \[[StacksGov](https://github.com/stacksgov/sips/blob/main/sips/sip-013/sip-013-semi-fungible-token-standard.md)] SIP-013 Standard Trait Definition for Semi-Fungible Tokens
* \[[Hiro YT](https://youtu.be/a7c8aBiIkD4?si=k4cUS5DHrUsnm7Q9)] A Walkthrough of a SIP013 Implementation of SFTs on Stacks
* \[[DegenLab](https://docs.degenlab.io/gamefistacks/sfts/general-idea-and-base-sfts-static-deployments)] Example of SFT implementation with DegenLab


# Build a Frontend

Interact with your contracts with a proper frontend app

<div data-with-frame="true"><figure><img src="/files/vgfmcZ7TQADCMjs58D4C" alt=""><figcaption></figcaption></figure></div>

A major part of building full-stack Stacks applications is creating a well designed UI with a solid UX. One of your primary tools for this is stacks.js, a JavaScript/Typescript library that simplifies working with contracts, wallets, and the Stacks network.

{% hint style="info" %}
This section assumes you have basic knowledge in front-end development and bootstrapping frontend frameworks.
{% endhint %}

### Basic components to your Stacks frontend app

* [Authentication](/get-started/build-a-frontend/authentication)
* [Post-Conditions](/get-started/build-a-frontend/post-conditions)
* [Sending Transactions](/get-started/build-a-frontend/sending-transactions)

### Stacks brand designs for your app's UI

Access the latest Stacks brand design resources at [stacks.co/brand](https://stacks.co/brand). Find and download Stacks brand design materials directly from the linked Figma space.

{% embed url="<https://www.figma.com/design/afyAaHa2vGCR0KU1BHiske/Stacks-Brand?node-id=256-790&t=qXPWrrQ10iytre1c-1>" %}

***

### Additional Resources

* \[[Hiro Blog](https://www.hiro.so/blog/lean-devops-strategies-for-your-web3-project)] Lean DevOps Strategies for Your Web3 Project
* \[[Hiro Blog](https://www.hiro.so/blog/introducing-stacks-js-starters-launch-a-frontend-in-just-a-few-clicks)] Introducing Stacks.js Starters: Launch a Frontend in Just a Few Clicks


# Authentication

<div data-with-frame="true"><figure><img src="/files/8G3n6bcIUfxROVVeqbBv" alt=""><figcaption></figcaption></figure></div>

Authenticating (connecting wallets) with a Stacks-supported wallet is a common task when building Stacks apps. On a web2 app, authentication usually means sending credentials to a central provider, which then verifies you and controls access. In web3, authentication uses a wallet and cryptographic signatures with libraries like stacks.js, letting users prove identity without a central party holding the keys.

{% hint style="info" %}
To learn more about how wallets and accounts work with Stacks, check out this [section](/learn/network-fundamentals/wallets-and-accounts) in Learn.
{% endhint %}

Below is a simple example showing how to set up front-end authentication with `@stacks/connect` and access user data in the UI. The stacks.js monorepo contains several underlying packages specific to different use cases. The package `@stacks/connect` is the main connectivity package used in Stacks.

## Authentication on the frontend

Using `@stacks/connect` on the frontend will allow our frontend app to authenticate wallets, call our contract functions, and interact with the Stacks network.

In the snippet below, you'll notice we have 3 functions setup to handle `connectWallet` , `disconnectWallet`, and for `getBns` . All 3 functions will be integral in how we want to display the 'Connect' and 'Disconnect' button in the UI.

{% hint style="info" %}
Retrieving a wallet account's associated [BNS](/learn/network-fundamentals/bitcoin-name-system) is a staple of Stacks and for web3 identity. Check out [BNSv2](https://www.bnsv2.com/) for more information and for availably public API endpoints you could use.
{% endhint %}

<pre class="language-typescript" data-title="src/App.tsx" data-expandable="true"><code class="lang-typescript">import { connect, disconnect } from '@stacks/connect'
import type { GetAddressesResult } from '@stacks/connect/dist/types/methods'
import { useState } from 'react'

function App() {
  let [isConnected, setIsConnected] = useState&#x3C;boolean>(false)
  let [walletInfo, setWalletInfo] = useState&#x3C;any>(null)
  let [bns, setBns] = useState&#x3C;string>('')

<strong>  async function connectWallet() {
</strong>    let connectionResponse: GetAddressesResult = await connect()
    let bnsName = await getBns(connectionResponse.addresses[2].address)

    setIsConnected(true)
    setWalletInfo(connectionResponse)
    setBns(bnsName)
  }

<strong>  async function disconnectWallet() {
</strong>    disconnect();
  }
  
<strong>  async function getBns(stxAddress: string) {
</strong>    let response = await fetch(`https://api.bnsv2.com/testnet/names/address/${stxAddress}/valid`)
    let data = await response.json()

    return data.names[0].full_name
  }
  
  return (
    &#x3C;>
      &#x3C;h3>Stacks Dev Quickstart Message Board&#x3C;/h3>
      {isConnected ? (
        &#x3C;button onClick={disconnectWallet}>{
<strong>          bns ? bns : walletInfo.addresses[2].address
</strong>        }&#x3C;/button>
      ) : (
        &#x3C;button onClick={connectWallet}>connect wallet&#x3C;/button>
      )}
    &#x3C;/>
  )
}
</code></pre>

The `connect()` method comes with the ability to configure how you want the wallet selector modal to appear for your app. You can decide which wallets to have only appear as an option or allow any wallet that follows the SIP-030 standard to appear as an available Stacks wallet.

For the complete guides check out the [Stacks Connect](/stacks-connect/connect-wallet) section.


# Post-Conditions

A unique security mechanism on Stacks to protect user funds

### What are post-conditions?

Post-conditions are assertions about an on-chain transaction that must be met; otherwise, the transaction will abort during execution. Post-conditions act as a safety net, allowing you to specify what state changes can occur in a transaction. This logic helps limit the amount of damage that can be done to a user and their assets, whether due to a bug or malicious behavior.

Post conditions are an additional safety feature built into the Stacks protocol itself that help to protect end users. Rather than being a feature of Clarity smart contracts, they are implemented on the client side and meant to be an additional failsafe against malicious contracts.

Post conditions are a set of conditions that must be met before a user's transaction will execute. The primary goal behind post conditions is to limit the amount of damage that can be done to a user's assets due to a bug, intentional or otherwise.

They are sent as part of the transaction when the user initiates it, meaning we need to implement post-conditions on the frontend. Whenever you are transferring an asset (fungible or non-fungible) from one address to another, you should take advantage of post conditions.

{% hint style="info" %}
Head to the dedicated section on [post-conditions](/post-conditions/overview) for more in-depth information.
{% endhint %}

We're going to use [stacks.js](https://github.com/stx-labs/stacks.js/tree/b7f0ed3f87cd4c5bfb7ab3c4bd8787c2018e3cec/packages/transactions#post-conditions) to familiarize ourselves with constructing post-conditions on the frontend. And there are several different ways to construct post-conditions based on asset type.

### Simple example

In this example, we are attaching a post-condition statement to a contract call transaction to protect the user's assets in the event the contract is malicious.

<pre class="language-typescript"><code class="lang-typescript">import { request } from '@stacks/connect'
import type { TransactionResult } from '@stacks/connect/dist/types/methods'
import { Pc } from '@stacks/transactions'

let postCond_1 = Pc.principal('ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3')
  .willSendEq(1)
  .ft('ST1F7QA2MDF17S807EPA36TSS8AMEFY4KA9TVGWXT.sbtc-token', 'sbtc-token')

let result: TransactionResult = await request('stx_callContract', {
  // ...
<strong>  postConditions: [postCond_1],
</strong>  postConditionMode: 'deny',
  // ...
})
</code></pre>

Let's walkthrough the example above line-by-line to see what's happening when you attach a post-condition statement to a transaction.

{% stepper %}
{% step %}

#### Declare post-condition statement

```typescript
let postCond_1 = Pc
  // Specify who the sender of the expected sBTC transfer will originate from
  .principal('ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3')
  // Specify the equality operator of the amount expected to be sent
  .willSendEq(1)
  // Specify the fungible token's contract principal and asset name
  .ft('ST1F7QA2MDF17S807EPA36TSS8AMEFY4KA9TVGWXT.sbtc-token', 'sbtc-token')
```

In this statement, you are declaring that the principal (usually the user that'll call this function) `ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3` should only expect to send out *exactly* 1 satoshi of sBTC during the execution of this contract call transaction.
{% endstep %}

{% step %}

#### Include post-condition statement to transaction params

<pre class="language-typescript"><code class="lang-typescript">let result: TransactionResult = await request('stx_callContract', {
  // ...
<strong>  postConditions: [postCond_1],
</strong>  // ...
})
</code></pre>

The transaction param of `postConditions` accepts an array of different post-condition statements. This means you can declare many post-condition statements of what the user should expect to happen during the execution of the transaction. This include any asset transfers coming from the user or from a contract.
{% endstep %}

{% step %}

#### Determine post-condition mode

The other related transaction param of `postConditionMode` is a special setting that is useful when you want to deal with other unexpected asset transfer events that the developer or user may not be aware of.

<pre class="language-typescript"><code class="lang-typescript">let result: TransactionResult = await request('stx_callContract', {
  // ...
  postConditions: [postCond_1],
<strong>  postConditionMode: 'deny',
</strong>  // ...
})
</code></pre>

By setting the `postConditionMode` to `deny` we are stating that if any other asset transfers, besides the ones we've declared, happen during the execution of the transaction, then force the entire transaction to fail.
{% endstep %}
{% endstepper %}

### How post-conditions appear to the user

Since post-conditions are declared on your frontend code, they also need to be visually displayed to users. Stacks-supported wallets handle that by displaying post-conditions on the transaction confirmation modals that popup when a user needs to confirm/approve a transaction.

<div data-with-frame="true"><figure><img src="https://284917788-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZz9BLmTU9oydDpL3qiUh%2Fuploads%2FflyarkGxrtWJErCd2H38%2Fexample-post-condition-leather.png?alt=media&#x26;token=e910e87f-0566-4dbc-aeb6-0a18e4203f61" alt=""><figcaption><p>Post-conditions when appeared in a wallet's transaction confirmation modal</p></figcaption></figure></div>

After transaction confirmation and broadcasting, users are also able to see what post-conditions were set in their transaction on the transaction page of the Stacks Explorer. This gives users and developers more confidence in analyzing transactions.

<div data-with-frame="true"><figure><img src="https://284917788-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZz9BLmTU9oydDpL3qiUh%2Fuploads%2FBVxwJKkmC1qdeitSktWu%2Fpost-conditions-explorer.png?alt=media&#x26;token=8e5aba16-7333-47b6-a402-b30f9e4cfd51" alt=""><figcaption><p>Analyze post-conditions set in transactions on the transactions page of the Stacks Explorer</p></figcaption></figure></div>

***

### Additional Resources

* \[[Post-Conditions](/post-conditions/overview)] Dedicated section on post-conditions in these docs
* \[[Hiro YT](https://youtu.be/xXgQB8NfdEY?si=eSZp4tlLOCkkqGRS)] ELI5: Post-Conditions on Stacks


# Sending Transactions

<div data-with-frame="true"><figure><img src="/files/9JJqCEYCMZHZ0l8t49hO" alt=""><figcaption></figcaption></figure></div>

Any Stacks app is going to require sending transactions at some point, so how do we do that?

{% hint style="warning" %}
When you send Stacks transactions, don't forget to utilize post-conditions.
{% endhint %}

### Invoking contract call transactions

In our example below, we're going to be showing how to invoke a contract function from the frontend which will prompt a user's wallet to confirm transaction. For this, we'll setup a `stx_callContract` to invoke the `add-message` public function of our contract taken from the [Developer Quickstart](/get-started/developer-quickstart). This function will accept a string content to be passed into our contract call.

<pre class="language-typescript" data-expandable="true"><code class="lang-typescript">import { request } from '@stacks/connect'
import type { TransactionResult } from '@stacks/connect/dist/types/methods'
import { Cl, Pc } from '@stacks/transactions'
import { useState } from 'react'

function App() {
  // ...
  let [content, setContent] = useState&#x3C;string>('')

  async function addMessage() {
    let postCond_1 = Pc.principal('ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3')
      .willSendEq(1)
      .ft('ST1F7QA2MDF17S807EPA36TSS8AMEFY4KA9TVGWXT.sbtc-token', 'sbtc-token')
  
<strong>    let result: TransactionResult = await request('stx_callContract', {
</strong>      contract: 'ST11V9ZN6E6VG72SHMAVM9GDE30VD3VGW5Q1W9WX3.stacks-dev-quickstart-message-board',
      functionName: 'add-message',
      functionArgs: [Cl.stringUtf8(content)],
      network: 'testnet',
      postConditions: [postCond_1],
      postConditionMode: 'deny',
      sponsored: false
    })
  
    setContent('')
  }

  return (
    &#x3C;>
      // ...
      &#x3C;span className='input-container'>
        &#x3C;button onClick={addMessage}>add-message&#x3C;/button>
        &#x3C;input type="text" onChange={e => setContent(e.target.value)}/>
      &#x3C;/span>
    &#x3C;/>
  )
}
</code></pre>

Let's breakdown some of the transaction params we specified in our string literal method of `stx_callContract`

* `contract` : this requires the full contract principal of the target contract.
* `functionName` : the name of the public function in the contract.
* `functionArgs` : an array of the required function arguments in the same order as coded in the actual function of the Clarity contract. The `Cl` namespace has type converter methods that help with converting your argument into the required Clarity type.
* `network` : the target network the contract is deployed on.
* `postConditions` & `postConditionMode` : [Post-Conditions](/post-conditions/overview) for the frontend are declared to protect user assets. The `Pc` helper from `@stacks/transactions` helps us to declare post-condition statements for any type of asset and equality operator.
* `sponsored` : if the transaction fees will be sponsored or not.

Invoking our `addMessage` function will prompt the user's connected wallet to prompt a transaction confirmation popup. This popup will display all of the relevant information of the transaction as well as the post-condition statements that we've declared.

Invoking a contract function is just one example of sending transactions from the frontend. There is also calling read-only functions, initiating asset transfer transactions, and etc.

### Invoking asset transfer transactions

The `request` object also supports native asset transfers for both STX, fungible tokens, and non-fungible tokens. Here is an example of creating an sBTC transfer transaction on the frontend.

Since sBTC is a SIP-010 fungible token, we'll invoke the `stx_transferSip10Ft` method.

```typescript
import { request } from '@stacks/connect';

let response = await request('stx_transferSip10Ft', {
    asset: 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token',
    amount: 1,
    recipient: 'SP202X1VHZMN5S90T44N7SSQ496PYQD66XCPA7BNK',
    network: 'mainnet',
});
```

***

### Additional Resources

* \[[Learn Stacks.js](/stacks.js/overview)] Head to the Learn Stacks.js section to see more examples


# Path to Production

Security resources and best practices before & after production.

<div data-with-frame="true"><figure><img src="/files/ZmM8X0Mbh2S259cM2xbh" alt=""><figcaption></figcaption></figure></div>

## Overview

Whether you build in traditional software or Web3, you never want to see a bug. You want users to interact with that code as it’s intended to function. You want their assets to be safe. You want their personal information to be private. Matter of fact, you want your assets and information to be secure too. That’s why the concept of production-hardening code exists.

Let’s talk about best practices and some steps you can take to harden your project before mainnet production.

<details>

<summary>What are security issues specific to web3?</summary>

Blockchains are immutable, so any mistakes or vulnerabilities you deploy are permanently on-chain for all to see. Oops. This is even more true on Stacks because Clarity contracts are not compiled and are human-readable on-chain.

Alongside immutability, there are a few other security issues specific to Web3 that are worth mentioning here:

* **Decentralization**: Web3 applications operate in a decentralized environment, meaning there is no central authority to mediate disputes, recover lost funds, or fix bugs.
* **Public code**: Smart contract code is public. While in the long run, public, open source code makes for a more resilient system, it comes with attack vectors such as unchecked external contract calls, reentrancy attacks, unguarded state modifications, integer overflows/underflows, and more.
* **Economic incentives**: Smart contracts often handle real assets, in the form of digital tokens and NFTs, and the public can see those assets, introducing a higher level of risk. Mistakes in code can lead to significant financial loss.
* **Blockchain networks**: Different networks operate under different consensus algorithms that require additional consideration for security.
* **Private Key Management**: Unlike centralized systems where credentials can be reset, losing a private key in Web3 often means losing access to funds permanently.
* **Contract dependencies**: Your code may depend on other smart contracts, such as an oracle or a bridge, which can introduce third-party risk to your project.

</details>

***

## Pre-Production Ready Checklist

To ensure your app or smart contract is production-ready, we pulled together a simple checklist that you can use during your development.

{% stepper %}
{% step %}

### Specific Clarity/Stacks.js best practices

* [**Post-conditions**](/post-conditions/overview): Post conditions are an additional safety feature built into the Stacks chain itself that help to protect end users. Rather than being a function of Clarity smart contracts, they are implemented on the client side and meant to be an additional failsafe against malicious contracts.
* [**Usage of `tx-sender` vs `contract-caller`**](https://www.setzeus.com/public-blog-post/clarity-carefully-tx-sender) : The usage of `tx-sender` versus another Clarity keyword, `contract-caller` , is always a tricky concept because it determines who actually initiated the transaction versus who invoked the current function. Both of them can have certain implications on security based on the context of your code.
* Write meaningful error codes to improve error handling
* Adopt a modular contract design approach

<details>

<summary>Other Clarity/Stacks.js security resources</summary>

* [Certik](https://www.certik.com/resources/blog/clarity-best-practices-and-checklist): Clarity: Best Practices and Checklists
* [Halborn](https://www.halborn.com/blog/post/understanding-clarity-the-future-of-secure-smart-contracts): Understanding Clarity: The Future of Secure Smart Contracts
* [Beosin](https://www.beosin.com/resources/stacks-and-its-clarity-contract-security): Stacks and its Clarity Contract Security
* [Jude Nelson](https://stacks.org/bringing-clarity-to-8-dangerous-smart-contract-vulnerabilities/): Bringing ‘Clarity’ to 8 Dangerous Smart Contract Vulnerabilities

</details>
{% endstep %}

{% step %}

### Plan for Fail-Safes and Emergency Upgrades

While contracts are immutable once deployed, you can deploy new versions of your contracts to upgrade your app. Make sure you have a deployment plan in place, so you can deploy a hot fix in the event you need to.

* [**ExecutorDAO framework**](https://github.com/MarvinJanssen/executor-dao): Adopt best practices for Clarity modularity that allows for contract upgradeability, strict access control, extensions, emergency proposals, and more.
  {% endstep %}

{% step %}

### Implement comprehensive testing tools

* [**Unit tests**](/clarinet/testing-with-clarinet-sdk)
* [**Fuzzing**](/rendezvous/overview)
* [**Devnet**](/clarinet/local-blockchain-development)
  {% endstep %}

{% step %}

### Private Key Management

You’d be surprised how many hacks stem from simple security breaches. Make sure you securely manage your private keys related to your project. That includes things like always using hardware wallets, regularly rotate keys, enforce access controls for who on your team can use keys, and consider implementing a multi-sig for your treasury or other sensitive operations.

* [**Encrypted Mnemonics**](/clarinet/contract-deployment#encrypted-mnemonics): Learn how you can safely encrypt private keys when deploying locally.
  {% endstep %}

{% step %}

### Testing on Testnet

Testing contracts and applications on the Stacks testnet before deploying to the mainnet is crucial for ensuring the reliability and security of your project. Furthermore, the testnet provides an invaluable opportunity for gathering user feedback and stress-testing the application under various conditions, thereby enhancing overall confidence in the code before live deployment.

* [**Deploying to testnet**](/clarinet/contract-deployment)
* [**Testnet faucets**](https://platform.hiro.so/faucet): The Platform offers testnet faucets of STX and sBTC
  {% endstep %}

{% step %}

### Simulate mainnet tests

If your contract relies heavily on already deployed external contracts or other forms of mainnet data, simulate your contracts as if it was already on mainnet. Instead of generating mock data locally (a time-intensive process that introduces its own risks and challenges), you can now rely on data that you’re confident will match what you’ll find on mainnet—because that’s exactly where the data now comes from.

* [**Mainnet Execution Simulation**](/clarinet/mainnet-execution-simulation): Leverage mainnet data in simnet/unit tests with Clarinet.
* [**stxer**](https://stxer.xyz/)**:** A community built simulation UI tool.
  {% endstep %}

{% step %}

### Crowdsource community testing/review

To effectively crowdsource community beta testing for your application in Stacks, engage with various online platforms where Stacks developers and users congregate. Utilize places such as the Stacks community Forum or Discord channels to reach out to potential testers. Leverage social media platforms and GitHub repositories to announce the beta testing phase, inviting users to contribute feedback. Offer incentives such as exclusive early access features or branded merchandise to motivate participation and gather diverse insights that can enhance the robustness of your app.

* [**Stacks Discord**](https://discord.gg/stacks): Connect with other developers and our team
* [**Stacks Forum**](https://forum.stacks.org/): Ask questions and share projects
* [**Stacks Twitter**](https://x.com/StacksDevs)**:** Follow us on Twitter and ask us questions there
  {% endstep %}

{% step %}

### Formal audits

Paying for formal smart contract auditors is an essential investment for ensuring the security and reliability of your blockchain application. By engaging reputable audit firms, you can gain a comprehensive understanding of potential risks and strategies to mitigate them, thus enhancing the trustworthiness of your application.

* [**List of professional auditors**](https://www.stacks.co/explore/ecosystem?category=Auditors#tools)
  {% endstep %}
  {% endstepper %}

***

## Post-Production Ready Checklist

{% stepper %}
{% step %}

### **Adopt Lean DevOps Strategies**

To ensure a smooth deployment process, adopt lean DevOps strategies, which include continuous integration and continuous delivery (CI/CD) pipelines. As discussed in[ Lean DevOps Strategies for Your Web3 Project](https://www.hiro.so/blog/lean-devops-strategies-for-your-web3-project), leveraging tools like GitHub Actions and GitLab CI/CD can help automate your deployment pipelines while ensuring code quality and consistency.
{% endstep %}

{% step %}

### Monitor contract activity

* [**Chainhooks**](https://docs.hiro.so/en/tools/chainhooks): Chainhooks is a webhook service for the Stacks blockchain that lets you register event streams and define precise filters to capture on-chain data as it happens.
  {% endstep %}

{% step %}

### Regularly Update Dependencies

Always keep your dependencies up to date, especially for any libraries and frameworks you’ve used in your development. This can help reduce any vulnerabilities originating from those third-party packages.
{% endstep %}

{% step %}

### Stay up to date with @StacksDevs

Follow us on [Twitter](https://x.com/StacksDevs) and [Youtube](https://www.youtube.com/@stacks-developers) for the latest developer updates.
{% endstep %}
{% endstepper %}


# Use Cases

Exploring different use cases for building with Stacks, on Bitcoin.

<div data-with-frame="true"><figure><img src="/files/0fXWeDG7MY46Yw4OfsCu" alt=""><figcaption></figcaption></figure></div>

Stacks extends Bitcoin's functionality, enabling a variety of decentralized applications. Here are some use cases for you to explore and incite new ideas.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><h4>DeFi</h4></td><td>Enable smart contracts for lending, borrowing, and trading of digital assets.</td><td><a href="/pages/sBaii4nWOa1N4xn9FMSn">/pages/sBaii4nWOa1N4xn9FMSn</a></td></tr><tr><td><h4>Art</h4></td><td>Facilitate the artistic creation and trading of digital art as NFTs.</td><td><a href="/pages/LXjbvv6GHeNpmyk6zON3">/pages/LXjbvv6GHeNpmyk6zON3</a></td></tr><tr><td><h4>Payments</h4></td><td>Enable fast, Bitcoin-settled transactions using assets like sBTC and STX, with developer tooling support and easy wallet integrations.</td><td><a href="/pages/pS4Vk6tzNWtiESrpmirR">/pages/pS4Vk6tzNWtiESrpmirR</a></td></tr><tr><td><h4>Gaming</h4></td><td>Support on-chain economies, verifiable in-game assets as NFTs, and player rewards programs.</td><td><a href="/pages/f8uEngpQ1emKuIeTCvnh">/pages/f8uEngpQ1emKuIeTCvnh</a></td></tr><tr><td><h4>AI</h4></td><td>AI agents can hold sBTC, sign transactions, manage digital assets, and automate workflows while being bound by Clarity-level constraints</td><td><a href="/pages/nrViiQlz3UNQGD0Lt7U1">/pages/nrViiQlz3UNQGD0Lt7U1</a></td></tr></tbody></table>


# Payments

Use cases of payments on Stacks

<div data-with-frame="true"><figure><img src="/files/BZn44W5F7dYExv76CfLv" alt=""><figcaption></figcaption></figure></div>

Enable fast, Bitcoin-settled transactions using assets like sBTC and STX, with developer tooling support and easy wallet integrations. Stacks brings the liquidity, speed, and logic of modern payments to Bitcoin — fast digital transfers, smarter payment rules, and the UX digital payments deserve.

Here are the payment use cases developers are building with today:

### sBTC Pay

sBTC Pay provides a payment gateway with APIs and webhooks for developers to instantly integrate a simple sBTC payment system in their app. A complete ***"Stripe for sBTC"*** payment gateway that enables businesses to easily accept Bitcoin payments via sBTC on Stacks blockchain.

**Implementation highlight:**\
sBTC Pay comes with a few integration methods developers can start using right away. The React component from its `@sbtc-gateway/react` library provides UI components for readily usable sBTC payments.

{% code title="@sbtc-gateway/react" %}

```typescript
import { SBTCProvider, PaymentButton } from '@sbtc-gateway/react';

function App() {
  return (
    <SBTCProvider apiKey="sk_test_...">
      <PaymentButton
        amount={100000}
        description="Product purchase"
        onSuccess={(paymentIntent) => console.log('Success!', paymentIntent)}
      />
    </SBTCProvider>
  );
}
```

{% endcode %}

<details>

<summary>Check out more from sBTC Pay</summary>

* [Official website](https://sbtcpay.org/)
* [Demo video](https://x.com/kai_builder/status/1962151430535700891)
* [Winner of the Stacks Builder Competition](https://x.com/kai_builder/status/1967806436387459388)
* [Github repo](https://github.com/STX-CITY/sbtc-pay)

</details>

***

### Bolt Wallet

Bolt wallet not only enables sBTC as transaction fees, but also boasts lightning bolt speed for payments on Stacks while guaranteeing transaction confirmation. This is made possible by Stacks' sponsor transaction feature and optimistic confirmations.

**Implementation highlight:**\
The code snippet below demonstrates how to transfer sBTC between Stacks wallets while paying the fee in sBTC instead of STX using Bolt Protocol's sponsorship feature.

{% code title="<https://github.com/ronoel/bolt-protocol/blob/main/cookbook/transfer-stacks-to-stacks.md>" expandable="true" %}

```typescript
import { STACKS_TESTNET } from "@stacks/network";
import { bytesToHex } from "@stacks/common";
import {
    Cl,
    FungiblePostCondition,
    makeContractCall,
    PostConditionMode,
    SignedContractCallOptions,
} from "@stacks/transactions";

async function transferStacksToStacks() {
    // Amount and fee in satoshis
    const amount = 100000000; // 1 sBTC
    const fee = 10;          // 10 satoshis minimum fee

    // Post condition to ensure exact amount+fee is spent
    const ftPostCondition: FungiblePostCondition = {
        type: 'ft-postcondition',
        address: "<sender-wallet-address>",    // Replace with actual sender address
        condition: 'eq',
        amount: amount + fee,
        asset: 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token::sbtc-token'
    };

    // Transaction options
    const txOptions: SignedContractCallOptions = {
        sponsored: true,  // Enable sponsorship
        senderKey: "<sender-key>",  // Replace with sender's private key
        network: STACKS_TESTNET,
        contractAddress: "SP3QZNX3CGT6V7PE1PBK17FCRK1TP1AT02ZHQCMVJ",
        contractName: "boltproto-sbtc-v1",
        functionName: "transfer-stacks-to-stacks",
        functionArgs: [
            Cl.uint(amount),
            Cl.principal("<recipient-address>"),  // Replace with recipient address
            Cl.none(),  // No memo
            Cl.uint(fee)
        ],
        postConditionMode: PostConditionMode.Deny,
        postConditions: [ftPostCondition],
    };

    // Create and serialize the transaction
    const transaction = await makeContractCall(txOptions);
    const serializedTx = bytesToHex(transaction.serializeBytes());

    // Submit to Bolt Protocol API
    const response = await fetch('https://boltproto.org/api/v1/transaction/sbtc-token', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ serializedTx })
    });

    if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log('Transaction submitted:', data.txid);
    return data;
}
```

{% endcode %}

<details>

<summary>Check out more from Bolt wallet</summary>

* [Official website for Bolt](https://boltproto.org/)
* [Hiro Dev N' Tell with Ronoel.btc showcasing Bolt wallet in action](https://youtu.be/iuNQ88VoRiU?si=xR7hf5N0VJQlz1rm)
* [Bolt Protocol](https://x.com/boltprotobtc)
* [Github repo](https://github.com/ronoel/bolt-protocol)

</details>


# Art

Use cases of art on Stacks

<div data-with-frame="true"><figure><img src="/files/gYwK65yNolAmASrgpWwq" alt=""><figcaption></figcaption></figure></div>

Unlock expressive, Bitcoin-secured digital art with NFT assets — all backed by fast, low-cost execution on Stacks. The Stacks ecosystem brings programmability, provenance, and creative tooling to Bitcoin, giving artists and collectors the speed, flexibility, and cultural richness they’ve always wanted *without leaving Bitcoin*. Stacks expands what Bitcoin culture can be: native digital ownership, programmable collectibles, onchain storytelling, and communities that form directly around Bitcoin-secured art.

Here are the creative use cases artists are exploring today:

### **Megapont Ape Club**

Megapont Ape Club is a pixel-art NFT collection built on Stacks. The “universe” behind Megapont is a fictional, stylized world — a retro-inspired pixel-art universe where mutated species evolved, with chimpanzees (apes) playing a central role. Beyond just apes, Megapont supports other NFT lines (e.g. Robot Factory, other “species / world” NFTs) and cross-chain / cross-platform assets.

**Implementation highlight:**\
The below code snippet is taken from the Megapont Ape's NFT contracts. This snippet shows two **internal minting functions** used. They are not public entrypoints—only callable from inside the contract. One handles *mintpass*-based presale minting, the other handles *public sale* minting.

* **Presale minting** has stricter access rules (mintpasses, whitelists, limits).
* **Public sale minting** is open to anyone once activated.
* The actual NFT lives in a separate contract (`.megapont-ape-club-nft`), keeping logic modular.

{% code title=".megapont-ape-club-mint" fullWidth="false" expandable="true" %}

```clarity
;; ...

;; Internal - Mint NFT using Mintpass mechanism
(define-private (mintpass-mint (new-owner principal))
  (let ((presale-balance (get-presale-balance new-owner)))
    (asserts! (> presale-balance u0) ERR-NO-MINTPASS-REMAINING)
    (map-set presale-count
              new-owner
              (- presale-balance u1))
  (contract-call? .megapont-ape-club-nft mint new-owner)))

;; Internal - Mint public sale NFT
(define-private (public-mint (new-owner principal))
  (begin
    (asserts! (var-get sale-active) ERR-SALE-NOT-ACTIVE)
    (contract-call? .megapont-ape-club-nft mint new-owner)))
    
;; ...
```

{% endcode %}

<details>

<summary>Check out more from Megapont</summary>

* \[[Official](https://www.megapont.com/)] Official website of Megapont
* \[[Gamma](https://stacks.gamma.io/collections/megapont-ape-club)] NFT listing page on the Gamma marketplace
* \[[Hiro YT](https://youtu.be/mz1irJUpq0I?t=843)] Muneeb joining the Megapont Ape community
* \[[Hiro YT](https://youtu.be/xwbXNgSvMkk?si=jeHwWQ4oLlj9_ucr)] A Beginner's Overview of the Megapont Ape NFT Clarity Smart Contract
* \[[contract](https://explorer.hiro.so/txid/SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft?chain=mainnet)] .megapont-ape-club-nft
* \[[contract](https://explorer.hiro.so/txid/SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-mint?chain=mainnet\&tab=overview)] .megapont-ape-club-mint

</details>

***

### Satoshibles

Satoshibles is an early, pixel-art NFT collection that originally launched on Ethereum in 2021 and later bridged to Stacks, becoming one of the first established NFT communities to move onto the Bitcoin ecosystem.

The project consists of 5000 algorithmically generated crypto collectible NFTs that have been hand illustrated. Each one unique, and each representing a fun, retro interpretation of “Satoshi-like” personas—quirky, expressive, and distinctly Bitcoin-themed.

**Implementation highlights:**\
This code snippet below enables a flexible, secure commission system by letting each NFT listing specify a commission contract, enforcing its use during purchase, and delegating fee payout logic to that external contract via the commission trait. By accepting a contract implementing `commission-trait`, it creates a *plug-and-play commission system* where:

* marketplaces decide their fee logic,
* creators can define custom royalty structures,
* different listings can use different commission rules.

The marketplace contract enforces that the same commission contract passed at listing must also be used at purchase time.

{% code title="SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.satoshibles" expandable="true" %}

```clarity
;; ...

(use-trait commission-trait .commission-trait.commission)

;; ...

(define-public (list-in-ustx (id uint) (price uint) (comm <commission-trait>))
  (let ((listing  {price: price, commission: (contract-of comm)}))
    (asserts! (is-sender-owner id) ERR-NOT-AUTHORIZED)
    (map-set market id listing)
    (print (merge listing {a: "list-in-ustx", id: id}))
    (ok true)))

(define-public (unlist-in-ustx (id uint))
  (begin
    (asserts! (is-sender-owner id) ERR-NOT-AUTHORIZED)
    (map-delete market id)
    (print {action: "unlist-in-ustx", id: id})
    (ok true)))

(define-public (buy-in-ustx (id uint) (comm <commission-trait>))
  (let ((owner (unwrap! (nft-get-owner? Satoshibles id) ERR-NOT-FOUND))
      (listing (unwrap! (map-get? market id) ERR-LISTING))
      (price (get price listing)))
    (asserts! (is-eq (contract-of comm) (get commission listing)) ERR-WRONG-COMMISSION)
    (try! (stx-transfer? price tx-sender owner))
    (try! (contract-call? comm pay id price))
    (try! (trnsfr id owner tx-sender))
    (map-delete market id)
    (print {action: "buy-in-ustx", id: id})
    (ok true)))
    
;; ...
```

{% endcode %}

<details>

<summary>Check out more from Satoshibles</summary>

* \[[Official](https://satoshibles.com/)] Official website of Satoshibles
* \[[contract](https://explorer.hiro.so/txid/SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.satoshibles?tab=overview)] SP6P4EJF0VG8V0RB3TQQKJBHDQKEF6NVRD1KZE3C.satoshibles
* \[[Gamma](https://gamma.io/stacks/collections/satoshibles/items)] Satoshibles' listing page on Gamma marketplace
* \[[YT](https://www.youtube.com/watch?v=gZw4EvV6qig)] BRIDGE from ETH to Stacks | Satoshibles

</details>


# DeFi

Use cases of DeFi on Stacks

<div data-with-frame="true"><figure><img src="/files/CKq9d9zEAwuPvUlJV9xA" alt=""><figcaption></figcaption></figure></div>

Stacks enables users to put their BTC to work in trust-minimized ways: borrowing against it, providing liquidity, earning yield, or participating in programmable financial products that settle on Bitcoin. This ecosystem gives builders the foundation to extend Bitcoin from a passive store of value into an active financial layer.

Here are some powerful demonstrations of unlocking DeFi for Bitcoin:

### Hermetica

Hermetica is a DeFi protocol built on Stacks whose mission is to bring fully Bitcoin-native stablecoins and yield products to the Bitcoin ecosystem. Their flagship asset is USDh — a Bitcoin-backed, yield-bearing synthetic dollar.

**Implementation highlight:**\
The code snippet below highlights the **migration lock**, **manager assignment**, and **token deprecation logic** all in one tight block. It captures the “power unlock” of the contract without pulling in the entire file:

* Safely upgrade USDh by freezing old token operations once migration starts.
* Assigns a migration manager to burn and migrate balances securely.
* Ensures consistent supply and a trust-minimized transition to the new token.

{% code title="SPN5AKG35QZSK2M8GAMR4AFX45659RJHDW353HSG.usdh-token-v1" expandable="true" %}

```clarity
;; Prevents all token activity once migration has begun
(define-read-only (is-not-migrated)
  (ok (asserts! (is-eq u0 (var-get migration-start-height)) ERR_DEPRECATED_TOKEN))
)

;; Begins the migration process and hands control to a migration manager contract
(define-public (start-migration (manager <token-migration-trait>))
  (begin
    (try! (is-not-migrated))
    (try! (contract-call? .hq-v1 check-is-owner contract-caller))
    (var-set migration-start-height burn-block-height)
    (var-set migration-manager (some (contract-of manager)))
    (contract-call? manager start-migration burn-block-height (ft-get-supply usdh))
  )
)

;; Allows the designated migration manager to burn a user’s balance and extract it for migration
(define-public (migrate-balance (who principal))
  (let ((balance (ft-get-balance usdh who)))
    (asserts! (is-eq (var-get migration-manager) (some contract-caller)) ERR_NOT_MIGRATION_MANAGER)
    (asserts! (> balance u0) (ok u0))
    (try! (ft-burn? usdh balance who))
    (ok balance)
  )
)

```

{% endcode %}

<details>

<summary>Check out more from Hermetica</summary>

* \[[Official](https://hermetica.fi/)] Official website of Hermetica
* \[[Stacks YT](https://youtu.be/Xb54LJrLicY?si=3wMTBwOskphdsn4S)] Earn up to 25% with Your BTC as Collateral with Jakob Schillinger
* \[[Hiro YT](https://www.youtube.com/watch?v=R6f4jR8S45M)] Lessons From Building Bitcoin DeFi
* \[[Hiro Blog](https://www.hiro.so/blog/how-hermetica-uses-chainhook-to-track-bitcoin-deposits)] How Hermetica Uses Chainhook to Track Bitcoin Deposits
* \[[contract](https://explorer.stacks.co/token/SPN5AKG35QZSK2M8GAMR4AFX45659RJHDW353HSG.usdh-token-v1?chain=mainnet)] SPN5AKG35QZSK2M8GAMR4AFX45659RJHDW353HSG.usdh-token-v1

</details>

***

### StackingDAO

StackingDAO is the hub for liquid stacking on Stacks. One of their liquid stacking services **stSTXbtc**, is a liquid stacking token (LST) backed 1-to-1 with STX, and holders receive sBTC rewards daily that can be claimed at any moment.

**Implementation highlight:**\
This function **initiates a withdrawal of stSTXbtc**, locks the underlying STX for withdrawal, burns the derivative token, and mints an NFT that represents the user’s withdrawal claim. It effectively transforms a liquid derivative token into a time-locked withdrawal right.

* Enforces protocol-level safety checks
* Determines the unlock Bitcoin (burn) height
* Links the withdrawal to an NFT “claim ticket”
* Coordinates state changes across multiple protocol contracts

{% code title="SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-btc-v2" fullWidth="true" expandable="true" %}

```clarity
;; --snip--

(define-public (init-withdraw 
  (reserve <reserve-trait>) 
  (direct-helpers <direct-helpers-trait>)
  (ststxbtc-amount uint)
)
  (let (
    (sender tx-sender)
    (unlock-burn-height (unwrap-panic (contract-call? .stacking-dao-core-v4 get-withdraw-unlock-burn-height)))

    (nft-id (unwrap-panic (contract-call? .ststxbtc-withdraw-nft get-last-token-id)))
  )
    (try! (contract-call? .dao check-is-enabled))
    (try! (contract-call? .dao check-is-protocol (contract-of reserve)))
    (try! (contract-call? .dao check-is-protocol (contract-of direct-helpers)))
    (asserts! (not (get-shutdown-init-withdraw)) (err ERR_SHUTDOWN))

    (try! (contract-call? .data-core-v2 set-ststxbtc-withdrawals-by-nft nft-id ststxbtc-amount unlock-burn-height))
    
    (try! (contract-call? direct-helpers subtract-direct-stacking tx-sender ststxbtc-amount))

    ;; Burn stSTXbtc tokens
    (try! (as-contract (contract-call? reserve lock-stx-for-withdrawal ststxbtc-amount)))
    (try! (contract-call? .ststxbtc-token-v2 burn-for-protocol ststxbtc-amount sender))
    (try! (as-contract (contract-call? .ststxbtc-withdraw-nft mint-for-protocol sender)))

    (print { action: "init-withdraw", data: { stacker: tx-sender, nft-id: nft-id, ststxbtc-amount: ststxbtc-amount, unlock-burn-height: unlock-burn-height, block-height: block-height } })
    (ok nft-id)
  )
)
```

{% endcode %}

<details>

<summary>Check out more from StackingDAO</summary>

* \[[Hiro YT](https://youtu.be/1hWYeqS5r-k?si=GRWag60DUmm08TG_)] Going Under the Hood of stSTXbtc with Philip De Smedt from StackingDAO
* \[[Hiro YT](https://youtu.be/ujpatSY9DhM?si=cr823veqbmcfYr7y)] A Simple Breakdown of the StackingDAO Clarity Contracts on Stacks

</details>


# Gaming

Use cases of gaming on Stacks

<div data-with-frame="true"><figure><img src="/files/vp1qVq8nEG3ElLvAzcGR" alt=""><figcaption></figcaption></figure></div>

Gaming is one of the most powerful entry points for bringing millions of new users into the Bitcoin ecosystem, and Stacks unlocks this opportunity with onchain logic secured by Bitcoin itself. By enabling fast, low-cost transactions, expressive smart contracts, and asset ownership through NFTs and fungible tokens, Stacks gives game developers the tools to build richer in-game economies, verifiable digital ownership, and player-driven marketplaces—all anchored to Bitcoin’s security. This combination lets games move beyond simple collectibles and into fully programmable, decentralized worlds where players truly own their assets and developers can design deeper incentives, interoperable items, and sustainable onchain economies.

Here are some powerful examples of how Stacks is unlocking on-chain gaming for Bitcoin:

### Skullcoin

Skullcoin is a Web3 gaming project building a new genre called Find2Earn — treasure hunt games powered by Encrypted NFTs and real on-chain rewards. An Encrypted NFT is a new type of digital asset with two layers of information: a public layer visible to everyone, and a private encrypted layer that can only be revealed by the owner of NFT.

**Implementation highlight:**\
Here's a high-level breakdown of Skullcoin's Encrypted NFTs:

* **What happens on-chain**: standard SIP-009 NFTs + commitments (hashes / indexes / events) that define what’s “locked” and who has the right to unlock it;
* **What happens off-chain**: the actual encrypted payload (image / text / coords) lives in storage and is only served after the on-chain proof/conditions are satisfied.

{% code title="skullcoin-competitive-seed-phase2.clar" %}

```clarity
;; --snip--

(define-private (is-sender-owner (id uint))
  (let ((owner (unwrap! (nft-get-owner? skullcoin_competitive_seed_p2 id) false)))
    (or (is-eq tx-sender owner) (is-eq contract-caller owner))))
    
;; --snip--
```

{% endcode %}

<details>

<summary>Check out more from Skullcoin</summary>

* \[[Official](https://skullco.in/)] Official website of Skullcoin
* \[[Whitepaper](https://docs.skullco.in/)] Skullcoin whitepaper/docs
* \[[contracts](https://github.com/proofofgame/find_to_earn)] Github repo for Skullcoin's Find2Earn contracts

</details>

***

### Cryptonauts

Cryptonauts is a multiplayer GameFi Experience built on Unreal Engine 5 and powered by **Stacks**, a Bitcoin-anchored smart contract layer. Cryptonauts integrates Stacks wallet authentication, NFT verification, and on-chain asset logic directly into Unreal Engine, enabling features such as player skin ownership validation, Codex Component loadouts (NFT-based abilities), and signed game session data for Web3 interoperability.

**Implementation highlight:**\
Cryptonauts leverages BNS for player identification.

* **Human-readable identities for players** — instead of using cryptographic addresses, BNS lets players show names like `cryptodude.btc`. This makes in-game identities more memorable, personality-driven, and social.
* **Persistent identity + on-chain history** — BNS allows binding off-chain state to names and linking with on-chain state. That means a player’s actions, assets, and progress can be tied to a stable identity — even if they change wallets.

{% code title="<https://api.bnsv2.com/names/address/SP3WAR3N1XRR139DXCGPR1ATPK2VN63PGRXTD537N/valid>" expandable="true" %}

```json
{
  "total": 2,
  "current_burn_block": 921664,
  "limit": 50,
  "offset": 0,
  "names": [
    {
      "full_name": "cryptodude.btc",
      "name_string": "cryptodude",
      "namespace_string": "btc",
      "owner": "SP3WAR3N1XRR139DXCGPR1ATPK2VN63PGRXTD537N",
      "registered_at": "28369",
      "renewal_height": "1125897",
      "stx_burn": "2000000",
      "revoked": false
    }
  ]
}
```

{% endcode %}

<details>

<summary>Check out more from Cryptonauts</summary>

* \[[docs](https://cryptonauts.gitbook.io/cryptonauts-docs)] Cryptonauts docs

</details>

***

### Additional Resources

* \[[Hiro Blog](https://www.hiro.so/blog/its-time-to-stake-your-claim-on-the-future-of-web3-gaming)] It’s Time to Stake Your Claim on the Future of Web3 Gaming
* \[[Hiro Blog](https://www.hiro.so/blog/what-are-gaming-nfts-and-how-can-they-drive-bitcoin-adoption)] What Are Gaming NFTs and How Can They Drive Bitcoin Adoption?


# AI

Use cases of AI on Stacks

<div data-with-frame="true"><figure><img src="/files/qDyfj2mvH6zo9BRE7Txk" alt=""><figcaption></figcaption></figure></div>

AI on **Stacks** enables verifiable, Bitcoin-secured AI applications. Developers can build decentralized AI marketplaces, create AI agents that safely manage sBTC under smart-contract rules, and generate verifiable inference receipts for trust and compliance. By combining Bitcoin security with Clarity and sBTC, Stacks provides a powerful foundation for trusted, permissionless, AI-powered apps.

Here are some powerful examples of how **Stacks is unlocking on-chain AI experiences secured by Bitcoin:**

### **x402-Stacks**

x402 enables **automatic HTTP-level payments** for APIs, AI agents, and digital services using STX or sBTC tokens on Stacks. Pay only for what you use, right when you use it. No subscriptions, no API keys, no intermediaries.

**Implementation highlight:**\
The `x402-Stacks` library is a TypeScript library for implementing the x402 payment protocol on Stacks blockchain. This system supports multiple ways to handle paid API access: clients can pay automatically using an axios interceptor, or they can sign requests while a facilitator service reliably settles the payment on their behalf. Developers can also protect any Express.js endpoint with plug-and-play middleware. Pricing is fully flexible, supporting fixed, tiered, or dynamic fee models.

{% code title="x402-stacks" expandable="true" %}

```typescript
import axios from 'axios';
import { withPaymentInterceptor, privateKeyToAccount } from 'x402-stacks';

// Create account from private key
const account = privateKeyToAccount(process.env.PRIVATE_KEY!, 'testnet');

// Wrap axios with automatic payment handling
const api = withPaymentInterceptor(
  axios.create({ baseURL: 'https://api.example.com' }),
  account
);

// Use normally - 402 payments are handled automatically!
const response = await api.get('/api/premium-data');
console.log(response.data);
```

{% endcode %}

<details>

<summary>Check out more from x402-Stacks</summary>

* \[[npm package](https://www.npmjs.com/package/x402-stacks)] x402-Stacks
* \[[Github](https://github.com/tony1908/x402Stacks)] Open-source repo for x402-Stacks
* \[[Twitter](https://x.com/toony1908/status/1996417973842858238)] Demo video of using x402-Stacks SDK

</details>

***

### AIBTC

The AI + BTC coordination network. AIBTC provides AI powered agents with Bitcoin and Stacks tooling.

**Implementation highlight:**\
The `aibtcdev-backend` bridges AI capabilities with Stacks blockchain technology to create intelligent DAO management experiences. The system provides real-time communication with AI agents that can autonomously interact with DAOs, create and evaluate proposals, execute trades, and manage blockchain accounts.

{% code title="WebSocket Chat usage example" %}

```typescript
const ws = new WebSocket('ws://localhost:8000/chat/ws?token=your_token');
ws.send(JSON.stringify({
  type: 'message',
  thread_id: 'thread-uuid',
  content: 'Hello, AI agent!'
}));
```

{% endcode %}

<details>

<summary>Check out more from AIBTC</summary>

* \[[Official](https://aibtc.com/)] Official website of AIBTC
* \[[Github](https://github.com/aibtcdev)] Open-source repo for backend, frontend, and agent tooling support

</details>


# Latest Updates

Check out the latest Stacks developer updates

### More Linting, Less Friction

*March 12th, 2026*

[**\[Clarinet 3.15.0\]**](https://github.com/stx-labs/clarinet/releases/tag/v3.15.0) This release brings some solid quality-of-life improvements to Clarinet. On the analysis side, there's now static code analysis via CodeLens, and two new linter rules covering `at-block` and `case_binding`. Diagnostics now run with and without the `#[env(simnet)]` annotation during both `clarinet check` and the LSP. Devnet gets some love too — Docker containers are now grouped, logging is improved in `--no-dashboard` mode, and the orchestrator has been refactored for better reliability. Under the hood, Chainhooks v1 has been removed, dependencies have been updated, and a fix lands for correctly traversing Clarity 4's `as-contract?`.

<details>

<summary>Details</summary>

`at-block` **Lint Warning**

A SIP is currently up for vote that would remove the `at-block` function starting in Epoch 3.4. If it passes, any deployed contract calling `at-block` will start throwing runtime errors after Epoch 3.4 activates, and new contracts using it will be rejected at deployment entirely. To get ahead of this, Clarinet now flags any use of `at-block` in your code with a lint warning. If you have contracts using `at-block`, now is the time to audit and refactor. Vote and learn more [here](https://ballot.gg/67a34537-0375-4046-a4b7-432e8dfd4eb3/1MP9LjMBZRKXWq3tRio6nGwFyUoboozEQx).

**Static Cost Analysis via CodeLens**

You can now see the static max cost of your Clarity functions directly in your editor, displayed inline just above each function definition. No more manually invoking a function and digging through terminal output to get a cost estimate — the analysis is just there, passively, as you write.

<div data-with-frame="true"><figure><img src="/files/ulf5JnW7ttDZrGE2HAbi" alt=""><figcaption></figcaption></figure></div>

**Improved `devnet start --no-dashboard` Logging**

Running devnet without the dashboard used to be pretty useless in practice — it would print container status updates, stop once the Bitcoin node was ready, and then go quiet, giving you no visibility into what was actually happening as the chain progressed. That's been fixed. The logs now surface the full chain of events as devnet runs, making it actually usable for local development workflows and, importantly, for AI agents running devnet headlessly in automated pipelines.

{% code title="example" expandable="true" %}

```
Mar 05 17:51:49.870 DEBG Bitcoin block #145 received
Mar 05 17:51:49.870 INFO bitcoin-node - mining blocks (chain_tip = #145)
Mar 05 17:51:51.187 WARN Stacks reorg received
Mar 05 17:51:51.187 INFO stacks-node - mining blocks (chain_tip = #38)
Mar 05 17:51:51.187 INFO Stacks block #38 mined including 2 transactions
Mar 05 17:51:51.187 INFO Local Devnet network ready
Mar 05 17:51:57.252 DEBG Bitcoin block #146 received
Mar 05 17:51:57.252 INFO bitcoin-node - mining blocks (chain_tip = #146)
Mar 05 17:51:58.554 INFO   ok deploy ST000000000000000000002AMW42H.sip-031 [(ok true)]
Mar 05 17:51:58.554 INFO stacks-node - mining blocks (chain_tip = #39)
Mar 05 17:51:58.554 INFO Stacks block #39 mined including 3 transactions
Mar 05 17:52:01.459 DEBG Bitcoin block #147 received
Mar 05 17:52:01.459 INFO bitcoin-node - mining blocks (chain_tip = #147)
Mar 05 17:52:02.807 INFO stacks-node - mining blocks (chain_tip = #40)
Mar 05 17:52:02.807 INFO Stacks block #40 mined including 2 transactions
Mar 05 17:52:06.748 DEBG Bitcoin block #148 received
Mar 05 17:52:06.748 INFO bitcoin-node - mining blocks (chain_tip = #148)
Mar 05 17:52:08.070 INFO   ok deploy ST000000000000000000002AMW42H.costs-4 [(ok true)]
```

{% endcode %}

**`case_binding` Linter Rule**

Clarity convention is `kebab-case`. The new `case_binding` lint rule enforces this on `let` bindings and function argument names, so things like `camelCaseVar` or `snake_case_arg` will now generate a diagnostic. If you have a specific binding you want to opt out of the check, you can suppress it with a `#[allow(case_binding)]` comment on the line above.

**Simnet-Only Code Annotations**

Clarinet now supports a `#[env(simnet)]` annotation that lets you mark functions or expressions as simnet-only. Annotated code gets stripped out automatically when deploying to other networks, so test helpers like faucets never accidentally make it to mainnet. To keep things safe, `clarinet check` and the LSP now run two validation passes: one with the simnet code included and one without, catching any cases where production code accidentally depends on a simnet-only function.

</details>

***

### Clarity Plugin for Claude Code

*March 11th, 2026*

A [Clarity plugin](https://github.com/stx-labs/clarity-claude-plugin) for Claude Code is now available via the Stacks Labs Claude plugin marketplace. Install it with two commands and Claude Code will be aware of the Clarity CLI and have access to the Clarity LSP — meaning the agent can actually use the CLI as part of its workflow. More detailed skills around the JS SDK, devnet, deployments, and more are on the roadmap.

***

### Stacks Mesh API for exchanges and institutions

*March 10th, 2026*

[**\[API\]**](/reference/api/stacks-mesh-api) Previously, the Hiro Stacks Blockchain API included an embedded Rosetta implementation, but this was removed due to inefficiency. The standalone Mesh API implementation replaces that prior integration. Mesh (formerly branded as Rosetta) is an open standard originally developed by Coinbase to provide a unified interface for reading data from blockchains. It defines a common set of endpoints that blockchain nodes implement, **allowing exchanges and other institutions** to write a single parser that works across multiple chains.

***

### Chainstate shrinkage, Signer global state, and more security fixes

*March 9th, 2026*

[**\[Stacks Core 3.3.0.0.6\]**](https://github.com/stacks-network/stacks-core/releases/tag/3.3.0.0.6) This release contains two major infra upgrades: chainstate shrinkage (>20% reduction in daily growth) and the Signer state machine activation (better block production under load). This release also contains several bugfixes and improvements to the stacks-node and stacks-signer binaries, ensuring more consistent block production. Please upgrade if you are a node operator and signer.

***

### sBTC APIs, BNSv2, and new Stacks.js Reference section

*March 7th, 2026*

The API section now includes the sBTC bridge's [Emily APIs](/reference/api/sbtc-bridge), allowing you to track peg-in and peg-out statuses directly within the Stacks docs. We've also updated the [BNS section](/learn/network-fundamentals/bitcoin-name-system) to reflect the canonical BNSv2 protocol, ensuring you have accurate informational context for the latest naming system. Finally, the [Stacks.js reference](/reference/stacks.js/stacks-wallet) pages have been completely overhauled with an exhaustive list of function and type definitions, making it easier than ever to find exactly what you need.

***

### Enhanced Linting, JSON Output, and Performance Improvements

*March 3rd, 2026*

[**\[Clarinet v3.14.0\]**](https://github.com/stx-labs/clarinet/releases/tag/v3.14.1) This Clarinet release adds powerful new linting capabilities including improved noop detection, an `unnecessary_as_max_len` lint rule, and JSON output formatting via `clarinet check --output=<format>`. The update also includes important bug fixes for linter false positives and devnet timing issues, plus a 15% performance improvement in the clarinet-format tool.

***

### Fetch Deposit and Withdrawal Status for USDCx Bridging

*March 2nd, 2026*

**\[USDCx]** Deposit and withdrawal status endpoints for USDCx give applications a reliable way to track the lifecycle of cross-chain transfers between Stacks and other networks. Instead of manually monitoring multiple transactions and bridge events, developers can query a single endpoint to see whether a deposit or withdrawal is pending, verified, failed, or completed.

* Fetch withdrawal status for a USDCx burn event:\
  <https://api.usdc-on-stacks.com/testnet/withdrawals/0x5dfcc46c8e284132b702bb976b5b7d1f170d9c49f3b963fa0127ea348a228912/1>

Navigate to the USDCx API section [here](/reference/api/usdcx-bridge).

***

### Query PoX Activity on Bitcoin with new API endpoints

*February 26th, 2026*

\[**Stacks API**] The new PoX-related Bitcoin transactions endpoints are now easily discoverable and indexable for applications interacting with Stacks. These endpoints expose Bitcoin-layer activity that participates in Stacks’ Proof of Transfer (PoX) so apps don’t need to manually scan and decode raw Bitcoin blocks.

* Get all Bitcoin PoX transactions in a Bitcoin block:\
  <https://api.hiro.so/extended/v2/burn-blocks/938020/pox-transactions>
* Get all Bitcoin PoX transactions for a Bitcoin address:\
  <https://api.hiro.so/extended/v2/addresses/bc1qs5env6vx638xfrpx3jvrtvslke6gf5wdgjpye9kw9462289nyyqsvw3vyw/pox-transactions>

***

### Improved Deployment Plan Format

*February 14th, 2026*

\[[**Clarinet**](https://github.com/stx-labs/clarinet/releases/tag/v3.14.0)] The latest release of Clarinet (v3.14.0) comes with many small improvements. You'll also notice that the structure of the Deployment plans has changed slightly. The old format is still supported and Clarinet will automatically migrate to the new one. This is to help us bring more improvement to deployment plans in the future. You have nothing to do, but don't be surprised by this change.

{% hint style="warning" %}
**Reminder**: we are still seeing a lot of downloads on the deprecated NPM package `@hirosystems/clarinet-sdk`, only the new `@stacks/clarinet-sdk` is maintained.
{% endhint %}

***

### Deprecation notices for Hiro's Chainhooks v1 & L1 APIs

*February 6th, 2026*

\[**Hiro**] **Chainhooks V2 is now available.** This is a huge upgrade with more capability, better performance, and much greater reliability. But it also means that Hiro is **deprecating their hosted Chainhooks v1 on March 9th**, so if you’re using Chainhooks via the Hiro Platform, now is the time to upgrade. Self hosted Chainhook instances aren’t affected by this.

**L1 Bitcoin APIs shutting down March 9th.** Hiro is also deprecating their Ordinals, BRC-20, Runes, and Bitcoin Indexer APIs. They've partnered with Xverse to provide a smooth migration path for these use cases, and have put together a detailed migration guide to help you transition.

<details>

<summary>Details</summary>

* Chainhooks v2 announcement [blog post](https://www.hiro.so/blog/chainhooks-v2-is-now-generally-available)
* Hiro's L1 metaprotocol APIs deprecation [blog post](https://www.hiro.so/blog/upcoming-deprecation-of-ordinals-runes-and-brc-20-apis)

</details>

***

### Enhanced Block Production and New Block Simulation Capabilities

*February 4th, 2026*

[**\[Stacks Core 3.3.0.0.5\]**](https://github.com/stacks-network/stacks-core/releases/tag/3.3.0.0.5) This Stacks Core release (3.3.0.0.2) introduces a new block simulation endpoint and improves block validation while fixing critical bugs to ensure more stable block production. Key updates include enhanced burn-view calculations, streamlined validation tools, and compatibility with stacks-signer 3.3.0.0.5.0.

***

### Start Cookin' with the Cookbook

*January 30, 2026*

The [Cookbook](https://docs.stacks.co/cookbook/) contains detailed coding snippets known as recipes. Recipes are focused and reusable. They are designed to be referenced, copied, and adapted.

This section provides focused, reusable Clarity and Stacks.js code snippets that solve common problems or demonstrate specific patterns—designed to be referenced, copied, and adapted rather than read end-to-end.

***

### New 'Path To Production' Guide

*January 26, 2026*

Are you a new developer looking for security resources and best practices for when you're ready for testing or deploying? This page provides an outline of checklist items that you can use to further battle-test your contracts. Head to the [**Path To Production**](/get-started/path-to-production) guide to see what steps you can take to harden your project before mainnet production.

***

### Catch Dead Code Early with Clarity Linting

*January 14, 2026*

The latest Clarinet [v3.13.0](https://github.com/stx-labs/clarinet/releases/tag/v3.13.0) release includes a built-in Clarity linter to `clarinet check`, enabling dead code analysis and no-op detection, with configurable lint levels and inline overrides. The initial release focuses on identifying unused code and expressions that have no effect on execution. Lint behavior can be customized globally or per rule via `Clarinet.toml`.

<details>

<summary>Details</summary>

Today, Clarinet introduces a built-in **Clarity linter** as part of `clarinet check`, designed to help developers catch common mistakes, eliminate dead code, and improve overall contract quality earlier in the development cycle.

This first release focuses on **dead code analysis**, surfacing declarations and expressions that have no effect on contract execution and are often sources of bugs, confusion, or unnecessary complexity.

#### Dead Code Analysis (Available Today)

The initial lint set includes **seven configurable lints**, each targeting a specific class of unused code:

| Identifier          | Description                                                                    |
| ------------------- | ------------------------------------------------------------------------------ |
| `unused_const`      | Detects unused `define-constant` declarations                                  |
| `unused_data_var`   | Detects `define-data-var` values that are never written to                     |
| `unused_map`        | Detects `define-map` declarations that are never accessed                      |
| `unused_private_fn` | Detects private functions that are never called                                |
| `unused_token`      | Detects fungible and non-fungible tokens that are never minted                 |
| `unused_trait`      | Detects traits imported via `use-trait` that are never used as parameter types |
| `unused_binding`    | Detects unused function arguments and `let` bindings                           |

In addition, Clarinet includes the **`noop`** lint (contributed by GitHub user [0xalpharush](https://github.com/0xalpharush)), which flags expressions that have no effect, such as: `(is-eq 1)`

#### Suppressing Lints

Some unused code is intentional—for example, private functions used only in tests or bindings whose evaluation has side effects.

To handle these cases, Clarinet supports:

#### Identifier-based suppression

Appending a trailing `_` to an identifier might generate other kinds of warnings but the linter will allow them to be unused, following a convention similar to Rust. (Note: *prefixing* identifiers with `_` is not yet supported.)

#### Line-level suppression

Individual lints can also be disabled on a per-line basis using Clarity annotations:

```clarity
;; #[allow(lint_name)]
```

#### Configuration

All non-style/non-cosmetic lints are enabled by default at `warning` level. Style lints may be enabled by default at `notice` eventually.

**Configure individual lints**

```toml
[repl.analysis.lints]
noop = true # Defaults to "warning"
unused_const = "warning"
unused_data_var = "error"
unused_map = false
```

**Configure lint groups**

```toml
[repl.analysis.lint_groups]
all = true       # Sets default level to "warning" for all lints
style = "notice" # Cosmetic lints generate notices only
unused = "error" # Enforces removal of unused code
```

#### What’s Next

This release lays the foundation for a broader linting system in Clarinet. Upcoming work includes:

* **Style lints** for consistent and idiomatic Clarity code
* **Performance lints** to surface inefficient patterns
* **Safety lints** to help identify potentially dangerous constructs

If you have ideas for additional lints, feedback can be shared via the [Clarinet GitHub issue](https://github.com/stx-labs/clarinet/issues/2028) or in the community Discord.

Navigate to the Clarinet section on [this](/clarinet/validation-and-analysis).

</details>

***

### Completion of dimension-specific tenure extension

*January 12, 2026*

\[[**Stacks Core 3.3.0.0.4**](https://github.com/stacks-network/stacks-core/releases/tag/3.3.0.0.4)] With dimension-specific tenure extensions, Stacks can extend block limits per dimension (likeruntimeandread\_countbudgets) instead of stopping early. This ensures DeFi protocols can process critical flows during high-volatility periods. Hear Alex Huth talk about this during the latest DevRel office hours [here](https://x.com/StacksDevs/status/2017601390345130421).

***

### Multiple language support for Learn

*January 9, 2026*

The [Learn](https://docs.stacks.co/learn/) section now supports Chinese and Spanish, helping more developers access clear explanations of how Stacks works. You can switch languages using the selector in the top-right corner of the Learn pages.

***

### Bridging USDCx developer guide

*January 8, 2026*

Developers can now programmatically integrate the USDCx bridging flow into their app. Deposits are initiated on Ethereum and automatically minted on Stacks, while withdrawals are initiated on Stacks and settled on Ethereum. Check out the guide [here](/more-guides/bridging-usdcx) and start enabling stablecoin liquidity across the Stacks DeFi ecosystem.

***

### Multiple network URLs supported in RPC-API playground

*December 29, 2025*

The API playground in the [RPC-API reference](/reference/api/stacks-node-rpc) now supports testnet and mainnet. Use the interactive API playground to test API calls on mainnet, testnet, devnet, or for your own locally running Stacks node.

***

### Stacks Blockchain API v8.13.6 is live

*December 22, 2025*

\[**Hiro**] This is a required upgrade for all API users (incl. partners & exchanges): adds support for smart contracts deployed with empty source code.

It's an easy upgrade: no DB migrations, and fully compatible with the current chainstate.

See more in Hiro's release notes [here](https://github.com/hirosystems/stacks-blockchain-api/releases/tag/v8.13.6).

***

### USDCx now live on mainnet

*December 18, 2025*

New docs section dedicated to the launch of USDCx is now live [here](/learn/bridging/usdcx). Learn about its interoperable architecture with Circle's xReserve and discover the Clarity contracts behind the new USDCx token.

***

### Stacks Miners — Please Update ASAP!

*December 12, 2025*

This release activates the new read-count tenure extensions from SIP-034, a highly anticipated upgrade for builders across the ecosystem.

It also includes several important bug fixes, making this an update you don’t want to delay.

<details>

<summary>Details</summary>

For the latest release: <https://github.com/stacks-network/stacks-core/releases/tag/3.3.0.0.2>

#### Details on what was updated

**Added**

* Fixed an issue where `event.committed` was always equal to `true` in the block replay RPC endpoint
* Added `result_hex` and `post_condition_aborted` to the block replay RPC endpoint
* Added `--epoch <epoch_number>` flag to `clarity-cli` commands to specify the epoch context for evaluation.
* Support read-count tenure extends
* Added `read_count_idle_timeout_secs` config option to set the amount of seconds of idle time must pass before a read-count tenure extend is allowed (defaults to 20 seconds)
* Send a read-count tenure extend timestamp in the block responses
* Approve a block with a read-count tenure extend when the appropriate amount of idle time has passed

**Fixed**

* Correctly produce the receipt for the `costs-4` contract, which was deployed on epoch 3.3 activation. Users who consume node events and want to fill in the missing receipt (e.g. the Hiro API) will need to revert their chainstate to before the 3.3 activation and then resume sync to receive the previously missing event.

</details>

***

### Upgrade to Dual Stacking contracts

*December 10, 2025*

Dual Stacking contracts will be **upgraded on Dec 15**. This upgrade enables more flexible reward parameters and allows users to view their sBTC holdings and corresponding rewards within the Dual Stacking app.

<details>

<summary>Details</summary>

#### tl;dr

* If you enrolled in Dual Stacking you'll be moved over automatically with no action needed.
* If you did not enroll in the web app but were receiving Dual Stacking rewards through a participating app, you need to enroll on the web app.

To check your enrollment status go to [app.stacks.co](https://app.stacks.co/).

The contract will upgrade from `.dual-stacking-v1` to `.dual-stacking-v2_0_2` .

</details>

***

### Deploy in Clarinet using encrypted mnemonics

*December 9, 2025*

`clarinet 3.11.0` contains support for encrypted mnemonics. This feature gives users the option to encrypt the mnemonic seed phrase in their deployment files, so if a user's machine is compromised by a filesystem reading vulnerability, the seed phrase is not leaked to the attacker.

<details>

<summary>Details</summary>

To use this feature, a user must first run `clarinet deployments encrypt`, which will prompt the user for the seed phrase and a password, then print the encrypted mnemonic to the console. The user can then put the resulting ciphertext into their deployment config file using the key `encrypted_mnemonic`. The next time the user runs `clarinet deployments apply`, they will be prompted for the password, and the mnemonic will be decrypted for use in that session.

For example, if your `settings/Mainnet.toml` file looks like this:

{% code title="settings/Mainnet.toml" %}

```toml
[network]
name = "mainnet"
stacks_node_rpc_address = "https://api.hiro.so"
deployment_fee_rate = 10

[accounts.deployer]
mnemonic = "twice kind fence tip hidden tilt action fragile skin nothing glory cousin green tomorrow spring wrist shed math olympic multiply hip blue scout claw"
```

{% endcode %}

You would then run:

{% code title="terminal" %}

```
user@host package % clarinet deployments encrypt
Enter mnemonic to encrypt:
twice kind fence tip hidden tilt action fragile skin nothing glory cousin green tomorrow spring wrist shed math olympic multiply hip blue scout claw
Enter password: 

encrypted_mnemonic = "<encrypted_mnemonic>"
```

{% endcode %}

You would then replace the `mnemonic` field in your settings file with the `encrypted_mnemonic` output above:

{% code title="settings/Mainnet.toml" %}

```toml
[accounts.deployer]
encrypted_mnemonic = "47hYHSp4gtoBabz4X8cByJtRbvD3tBemS1zZJTkxYh2LJ7cVAHY6z74Td8bF5Dcsdpv45gDELPwfBP8Mfk64Q8TsBJNU9sf5hWMrTKPtr5h9abSdmxu4m2BewbUCi4o8znn42nAd7yphcb345YCrYLJFqFC7k9LqXvxgbQxUiFpWeyTVJPkGFa3aiQ8G5uhrv7pLCer4kRmXsmXbBvEqwEQLG7eM3TUMzUP79mHqJ1HGe2XWn"
```

{% endcode %}

Then the next time you deploy your package, you will be prompted for the password:

{% code title="terminal" %}

```
user@host package % clarinet deployments apply --mainnet

Enter password to decrypt mnemonic for account deployer: 
```

{% endcode %}

</details>

***

### New Tutorials section

*December 7, 2025*

The new [Tutorials](https://docs.stacks.co/tutorials/) section is now live on the Stacks docs!

First up: the beloved [Bitcoin Primer](/tutorials/bitcoin-primer/introduction) by Kenny Rogers.

We’re building a collection of the best full, end-to-end tutorials in the Stacks ecosystem. If you want to contribute a complete end-to-end tutorial related to developing on Stacks, let us know!

***

### Clarity 4 is now LIVE!

*November 18, 2025*

SIP-033 and SIP-034 have officially activated at Bitcoin block 923222 – bringing Clarity 4 live on Stacks, the smart contract layer secured by Bitcoin.

This upgrade introduces Version 4 of the Clarity smart contract language, marking a major step forward for the Stacks ecosystem. For users, it delivers safer, smarter contracts with enhanced built-in protections.

For builders, it unlocks five powerful new functions that make developing secure, flexible, and Bitcoin-native DeFi applications easier than ever.

<details>

<summary>Details</summary>

### What Clarity 4 Means for Bitcoin Builders

#### 1. On-chain Contract Verification

Developers can now fetch the hash of another contract’s code body.

[`contract-hash?`](https://docs.stacks.co/reference/clarity/functions#contract-hash)

This makes it possible for one contract to verify that another follows a specific template before interacting with it – a major step toward safer, more trustless bridges and marketplaces that can support a wider range of assets.

#### 2. Allowing Contracts to Set Post-Conditions

New functions allow contracts to set post-conditions that protect their assets.

[`restrict-assets?`](https://docs.stacks.co/reference/clarity/functions#restrict-assets)

This means a contract can safely call external contracts (such as traits) and automatically roll back any changes if the executed code moves assets beyond what’s allowed.

#### 3. Convert Simple Values into ASCII Strings

Clarity 4 adds a function to convert simple values like booleans or principals into ASCII strings.

[`to-ascii?`](https://docs.stacks.co/reference/clarity/functions#to-ascii)

This makes it easier to generate readable, string-based messages – a useful tool for developers building cross-chain features and integrations.

#### 4. Get the Timestamp of the Current Block

A new keyword lets developers retrieve the timestamp of the current block.

[`stacks-block-time`](https://docs.stacks.co/reference/clarity/keywords#stacks-block-time)

This addition enables time-based logic in smart contracts – an essential capability for building features like yield schedules, lockups, or expiration conditions in DeFi applications.

#### 5. Native Passkey Integration

Clarity 4 introduces a new function enabling on-chain verification of secp256r1 signatures.

[`secp256r1-verify`](https://docs.stacks.co/reference/clarity/functions#secp256r1-verify)

This lays the groundwork for passkey-based authentication, opening the door to features like hardware-secured wallets and biometric transaction signing.

#### 6. Dimension-specific Tenure Extensions

The SIP-033 vote also included technical rider SIP-034, which introduces dimension-specific tenure extensions. Signers can approve resets to one budget dimension (e.g., read-count) without resetting the others, allowing high-throughput workloads even when the cost model is pessimistic.

### Why This Matters for Bitcoin

Clarity 4 strengthens Stacks' position as Bitcoin's liquidity layer by giving developers the tools to build more sophisticated Bitcoin DeFi applications – all secured by Bitcoin through Stacks' Proof of Transfer mechanism.

Whether you're building Bitcoin lending protocols, yield products with sBTC, or the next generation of BTCFi applications, Clarity 4 delivers the security and functionality Bitcoin capital markets demand.

Check out [the full SIP-033](https://github.com/stacksgov/sips/pull/218) & [SIP-034](https://github.com/314159265359879/sips/blob/9b45bf07b6d284c40ea3454b4b1bfcaeb0438683/sips/sip-034/sip-034.md) specifications.

***

#### Additional Resources

* \[[Hiro Youtube](https://youtu.be/oJgacfc7YVk?si=b72bNicdS8NjUpml)] A Dev N' Tell with Brice on new Clarity 4 features

</details>

***

### Clarinet was migrated to Stacks Labs

*November 5, 2025*

You may have noticed that the Clarinet repository now belongs to the stx-labs organization.

With the **3.9.0** release, a few other things have changed:

* The NPM packages are now published under the `@stacks` organization.
* The Clarity VSCode extension is now published under the Stacks Labs organization.

<details>

<summary>Details</summary>

### tl;dr

Checklist:\
✅ Update NPM packages:

* `"@stacks/clarinet-sdk": "^3.10.0"`
* `"vitest-environment-clarinet": "3.0.2"`\
  ✅ Replace all imports of `@hiroystems/clarinet-sdk` to `@stacks/clarinet-sdk`\
  ✅ Optionally, update Vitest to v4 and **update vitest config**

***

### How to migrate?

#### VSCode

In VSCode (or similar variants such as Cursor), you'll have to uninstall the Hiro Systems "Clarity" extension in favor of the new "Clarity - Stacks Labs" extension published by Stacks Labs. The name of the extension will eventually revert to "Clarity" at some point, once the Hiro one is deprecated. You can also see it in the [online marketplace](https://marketplace.visualstudio.com/items?itemName=StacksLabs.clarity-stacks) - feel free to leave a 5 ⭐ review if you enjoy Clarinet!

#### NPM

New Clarinet projects created with 3.9.0 will automatically use the `@stacks/` NPM package.

However, older projects require a few manual updates to be migrated.

#### `package.json`

In your package.json, replace `@hirosystems/clarinet-sdk` with the `@stacks` one, and upgrade `vitest-environement-clarinet` to version 3.0.1. Your dependencies should look like that.

Optionally, you can upgrade to Vitest\@4, more on that below

```
  "dependencies": {
    "@stacks/clarinet-sdk": "^3.10.0",
    "@stacks/transactions": "^7.3.0",
    "@types/node": "24.10.0",
    "chokidar-cli": "3.0.0",
    "vitest": "^4.0.7",
    "vitest-environment-clarinet": "3.0.2"
  }
```

#### `tsconfig.json`

In the tsconfig.json, you need to update the `"includes"` config like so, so that is using `@stacks/clarinet-sdk`

```
  "include": ["node_modules/@stacks/clarinet-sdk/vitest-helpers/src", "tests"]
```

#### `vitest.config.ts` (or `.js`)

Your Vitest config has to import `@stacks/clarinet-sdk/vitest`.

Double check that you import `defineConfig` from `"vitest/config"` and not `"vite"`.

```
import { defineConfig } from "vitest/config";
import {
  vitestSetupFilePath,
  getClarinetVitestsArgv,
} from "@stacks/clarinet-sdk/vitest";
```

If you upgraded to Vitest v4, a few other changes are needed in `defineConfig`:

```
...

export default defineConfig({
  test: {
    // use vitest-environment-clarinet
    environment: "clarinet",
    pool: "forks",
    // clarinet handles test isolation by resetting the simnet between tests
    isolate: false,
    maxWorkers: 1,
    setupFiles: [
      vitestSetupFilePath,
      // custom setup files can be added here
    ],
    environmentOptions: {
      clarinet: {
        ...getClarinetVitestsArgv(),
        // add or override options
      },
    },
  },
});
```

#### Docker image

The Clarinet Docker image has been moved from Docker Hub to GitHub Container Registry (ghcr). It can be used like so:

```
jobs:
  sanity-checks:
    runs-on: ubuntu-latest
    container: ghcr.io/stx-labs/clarinet:latest
    steps:
      - uses: actions/checkout@v4
      - name: Check Clarity contracts check
        run: clarinet check --use-on-disk-deployment-plan
      - name: Check Clarity contracts format
        run: clarinet fmt --check
```

#### Double check

Search for all occurrences of `@hirosystems/clarinet-sdk` in your project; they'll likely need to be updated to `@stacks/clarinet-sdk`.

{% hint style="success" %}
If you're using third-party tools like Rendezvous or Clarigen, they now both support `@stacks/clarinet-sdk`.
{% endhint %}

***

### See it in action

See how the clarity-starter project was updated in this PR:\
[stx-labs/clarity-starter#17](https://github.com/stx-labs/clarity-starter/pull/17)

### Conclusion

We understand that these types of breaking changes can be frustrating. Although it's not ideal, we need it to move forward.

If you experience any issues with the migrations, reach out to us in the `#clarinet` channel on Discord or reply to this discussion.

</details>


# Overview

Clarinet is everything you need to write, test, and deploy Clarity smart contracts on Stacks.

<div data-with-frame="true"><figure><img src="/files/AtCX1jML5yo1Cgidhmfg" alt=""><figcaption></figcaption></figure></div>

{% hint style="success" %}
For the latest releases and versions of Clarinet, check out the open-source repo [here](https://github.com/stx-labs/clarinet).
{% endhint %}

Clarinet is a development framework and Clarity runtime packaged as a command line tool, designed to facilitate smart contract understanding, development, testing and deployment. It contains a suite of tools for building, testing, and deploying Clarity smart contracts for the Stacks blockchain.

Clarinet is the fastest way to build, test, and deploy smart contracts on the Stacks blockchain. It gives you a local devnet, REPL, testing framework, and debugging tools to ship high-quality Clarity code with confidence.

<div data-with-frame="true"><figure><img src="/files/CUiOqZumyn4tsJ23hU9n" alt=""><figcaption></figcaption></figure></div>

## Key features

* [**Leverage a powerful CLI**](/reference/clarinet/cli-reference) - Create new projects, manage your smart contracts and their dependencies using clarinet requirements, and interact with your code through the built-in REPL.
* [**Write unit tests with the SDK**](/clarinet/testing-with-clarinet-sdk) - Use the Clarinet SDK to write unit tests in a familiar JS environment and validate contract behavior.
* [**Run a private blockchain environment**](/clarinet/local-blockchain-development) - Spin up a local devnet with nodes, miners, and APIs so you can test and integrate your code.
* [**VSCode extension**](/clarinet/integrations/clarity-vscode-extension) - Linter, step by step debugger, helps writing smart contracts (autocompletion, documentation etc).

## Installation

{% tabs %}
{% tab title="Homebrew" %}

```bash
brew install clarinet
```

{% endtab %}

{% tab title="Winget" %}

```bash
winget install clarinet
```

{% endtab %}

{% tab title="Source" %}

```bash
sudo apt install build-essential pkg-config libssl-dev
git clone https://github.com/stx-labs/clarinet
cd clarinet
cargo clarinet-install
```

{% endtab %}

{% tab title="Binary" %}

```bash
wget -nv https://github.com/stx-labs/clarinet/releases/latest/download/clarinet-linux-x64-glibc.tar.gz -O clarinet-linux-x64.tar.gz
tar -xf clarinet-linux-x64.tar.gz
chmod +x ./clarinet
mv ./clarinet /usr/local/bin
```

{% endtab %}
{% endtabs %}

## Networks

Clarinet supports different network types to cater to various development and testing needs.

| Network   | Description                                                                 | Use case                                                           |
| --------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `simnet`  | Optimized for fast feedback loops, introspection, and portability.          | Ideal for initial development and unit-testing.                    |
| `devnet`  | Local Stacks and Bitcoin nodes running on Docker for faster feedback loops. | Use for integration tests or local frontend development.           |
| `testnet` | A pre-production network that offers a realistic environment for testing.   | Ideal for final testing before deploying to Mainnet.               |
| `mainnet` | The production network where real transactions occur.                       | Use when you're ready to deploy your smart contract to production. |

For a deeper understanding of when to use these networks, check out the dedicated blog post by Hiro [here](https://www.hiro.so/blog/devnet-vs-testnet-vs-mainnet-what-do-they-mean-for-web3-developers).

***

### Additional Resources

* \[[Hiro Blog](https://www.hiro.so/blog/clarinet-roadmap-looking-to-the-future)] The Humble Beginning of Clarinet
* \[[LabSTX](https://www.labstx.online/)]: Browser-based alternative to installing and running Clarinet locally

***

{% hint style="info" %}
Help: Need help building with Clarinet?

Reach out to us on the **#clarinet** channel on [Discord](https://stacks.chat/) under the Developer Tools section.
{% endhint %}


# Quickstart

In this guide, you'll build a simple counter smart contract and interact with it in a local environment.

## What you'll learn

* Create a Clarity smart contract project
* Write Clarity code with maps and public functions
* Test and validate your contracts using Clarinet's console

## Prerequisites

* Clarinet installed on your machine. Follow the [installation guide](/clarinet/overview#installation) if needed.
* A code editor like VS Code for editing Clarity files.

{% stepper %}
{% step %}

#### Create your project

Let's start by creating a new Clarinet project. The `clarinet new` command sets up everything you need for smart contract development, including a testing framework, deployment configurations, and a local development environment:

```bash
clarinet new counter
```

Clarinet creates a complete project structure for you. Each folder serves a specific purpose in your development workflow:

```
- counter/
  - contracts/
  - settings/
    - Devnet.toml
    - Mainnet.toml
    - Testnet.toml
  - tests/
    - Clarinet.toml
    - package.json
    - vitest.config.js
```

{% endstep %}

{% step %}

#### Generate your contract

Now that we have our project structure, let's create a smart contract. Navigate into your project directory and use Clarinet's contract generator:

```bash
$ cd counter
$ clarinet contract new counter
Created file contracts/counter.clar
Created file tests/counter.test.ts
Updated Clarinet.toml with contract counter
```

Clarinet automatically creates both your contract file and a corresponding test file. This follows the best practice of writing tests alongside your contract code:

| File                     | Purpose                     |
| ------------------------ | --------------------------- |
| `contracts/counter.clar` | Your smart contract code    |
| `tests/counter.test.ts`  | Test file for your contract |

{% hint style="info" %}
Notice that Clarinet also updated your `Clarinet.toml` file. This configuration file tracks all contracts in your project and their deployment settings.
{% endhint %}
{% endstep %}

{% step %}

#### Write your contract code

Open `contracts/counter.clar` and replace its contents with our counter implementation. This contract will maintain a separate count for each user who interacts with it:

{% code title="contracts/counter.clar" %}

```lisp
;; Define a map to store counts for each user
(define-map counters principal uint)

;; Increment the count for the caller
(define-public (count-up)
  (ok (map-set counters tx-sender (+ (get-count tx-sender) u1)))
)

;; Get the current count for a user
(define-read-only (get-count (who principal))
  (default-to u0 (map-get? counters who))
)
```

{% endcode %}

Let's understand what each part does:

* `define-map` creates a persistent storage map that associates each user (principal) with their count
* `tx-sender` is a built-in variable that contains the address of whoever calls the function
* `define-public` declares functions that can modify contract state
* `define-read-only` declares functions that only read data without modifying it
  {% endstep %}

{% step %}

#### Validate your contract

Before we can test our contract, let's make sure it's syntactically correct and type-safe. Clarinet's check command analyzes your contract without deploying it:

```bash
clarinet check
```

If you see errors instead, here are the most common issues and how to fix them:

| Error                 | Fix                                                                           |
| --------------------- | ----------------------------------------------------------------------------- |
| `Unknown keyword`     | Check spelling of Clarity functions                                           |
| `Type mismatch`       | Ensure you're using correct types (uint, principal, etc.)                     |
| `Unresolved contract` | Verify contract name in `Clarinet.toml` matches the contract name in the file |
| {% endstep %}         |                                                                               |

{% step %}

#### Test in the console

Now for the exciting part—let's interact with our contract! Clarinet provides an interactive console where you can call functions and see results immediately. Start the console with:

```bash
clarinet console
```

Once the console loads, you can call your contract functions directly. Here are a few examples you can try:

```lisp
$ (contract-call? .counter count-up)
(ok true)
$ (contract-call? .counter get-count tx-sender)
u1
$ (contract-call? .counter count-up)
(ok true)
$ (contract-call? .counter get-count tx-sender)
u2
```

{% endstep %}
{% endstepper %}


# Project Structure

Understand the complete structure and configuration of a Clarinet project.

A Clarinet project follows a carefully designed structure that separates contracts, tests, and configuration. Understanding this structure helps you organize code effectively and configure tools for an efficient development workflow.

## Core project layout

Every Clarinet project contains these essential directories and files:

```
- my-project/
  - .vscode/
  - contracts/
    - main.clar
    - trait.clar
  - deployments/
  - settings/
    - Devnet.toml
    - Mainnet.toml
    - Testnet.toml
  - tests/
    - main.test.ts
  - .gitignore
  - Clarinet.toml
  - package.json
  - tsconfig.json
  - vitest.config.js
```

Each component serves a specific purpose in your development workflow. The sections below explain how they work together to create a complete development environment.

## The project manifest

### Clarinet.toml

The **Clarinet.toml** file is the heart of your project. It defines project metadata and tracks all contracts:

```toml
[project]
name = "counter"
description = "A counter smart contract"

[contracts.traits]
path = "contracts/traits.clar"
clarity_version = 4
epoch = "latest"

[contracts.counter]
path = "contracts/counter.clar"
clarity_version = 4
epoch = "latest"
```

The manifest handles several critical functions:

* **Contract registration**: Every contract must be listed here
* **Stacks epoch and Clarity version**: Specifies Clarity version and epoch for each contract
* **Boot sequence**: Lists contracts to deploy on `clarinet devnet start`

### Epoch configuration

You can specify the epoch in two ways:

```toml
# Use a specific epoch version
epoch = 3.1
```

```toml
# Use the latest available epoch (default)
epoch = "latest"
```

Using `"latest"` ensures your contracts always use the newest Clarity features and optimizations available in your version of Clarinet.

## Testing infrastructure

### Package configuration

The **package.json** defines your testing environment and dependencies:

```json
{
  "name": "counter-tests",
  "version": "1.0.0",
  "description": "Run unit tests on this project.",
  "type": "module",
  "private": true,
  "scripts": {
    "test": "vitest run",
    "test:report": "vitest run -- --coverage --costs",
    "test:watch": "chokidar \"tests/**/*.ts\" \"contracts/**/*.clar\" -c \"npm run test:report\""
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@stacks/clarinet-sdk": "^3.9.1",
    "@stacks/transactions": "^7.2.0",
    "@types/node": "^24.4.0",
    "chokidar-cli": "^3.0.0",
    "vitest": "^4.0.7",
    "vitest-environment-clarinet": "^3.0.0"
  }
}
```

| Package                       | Purpose                                                 |
| ----------------------------- | ------------------------------------------------------- |
| `@stacks/clarinet-sdk`        | WebAssembly-compiled Clarinet for Node.js               |
| `@stacks/transactions`        | Clarity value manipulation in TypeScript                |
| `vitest`                      | Modern testing framework with native TypeScript support |
| `vitest-environment-clarinet` | Simnet bootstrapping for tests                          |

### Vitest configuration

The **`vitest.config.ts`** (or `.js`) configures the testing framework. Make sure to import `defineConfig` from `vitest/config` (and not for `vite`). This configuration will work with Vitest v4 and higher.

{% code expandable="true" %}

```typescript
import { defineConfig } from "vitest/config";
import {
  vitestSetupFilePath,
  getClarinetVitestsArgv,
} from "@stacks/clarinet-sdk/vitest";

/*
  In this file, Vitest is configured so that it works seamlessly with Clarinet and the Simnet.
  The `vitest-environment-clarinet` will initialise the clarinet-sdk
  and make the `simnet` object available globally in the test files.
  `vitestSetupFilePath` points to a file in the `@stacks/clarinet-sdk` package that does two things:
    - run `before` hooks to initialize the simnet and `after` hooks to collect costs and coverage reports.
    - load custom vitest matchers to work with Clarity values (such as `expect(...).toBeUint()`)
  The `getClarinetVitestsArgv()` will parse options passed to the command `vitest run --`
    - vitest run -- --manifest ./Clarinet.toml  # pass a custom path
    - vitest run -- --coverage --costs          # collect coverage and cost reports
*/

export default defineConfig({
  test: {
    // use vitest-environment-clarinet
    environment: "clarinet",
    pool: "forks",
    // clarinet handles test isolation by resetting the simnet between tests
    isolate: false,
    maxWorkers: 1,
    setupFiles: [
      vitestSetupFilePath,
      // custom setup files can be added here
    ],
    environmentOptions: {
      clarinet: {
        ...getClarinetVitestsArgv(),
        // add or override options
      },
    },
  },
});
```

{% endcode %}

This configuration enables:

* **Clarinet environment**: Automatic `simnet` setup for each test
* **Single fork mode**: Efficient test execution with proper isolation
* **Coverage tracking**: Generate reports in multiple formats
* **Custom setup**: Add project-specific test utilities

<details>

<summary>For Vitest v3 and earlier, use the configuration below.</summary>

```typescript
import { defineConfig } from "vitest/config";
import {
  vitestSetupFilePath,
  getClarinetVitestsArgv,
} from "@stacks/clarinet-sdk/vitest";

/*
  In this file, Vitest is configured so that it works seamlessly with Clarinet and the Simnet.
  The `vitest-environment-clarinet` will initialise the clarinet-sdk
  and make the `simnet` object available globally in the test files.
  `vitestSetupFilePath` points to a file in the `@hirosystems/clarinet-sdk` package that does two things:
    - run `before` hooks to initialize the simnet and `after` hooks to collect costs and coverage reports.
    - load custom vitest matchers to work with Clarity values (such as `expect(...).toBeUint()`)
  The `getClarinetVitestsArgv()` will parse options passed to the command `vitest run --`
    - vitest run -- --manifest ./Clarinet.toml  # pass a custom path
    - vitest run -- --coverage --costs          # collect coverage and cost reports
*/

export default defineConfig({
  test: {
    // use vitest-environment-clarinet
    environment: "clarinet",
    pool: "forks",
    poolOptions: {
      forks: { singleFork: true },
    },
    setupFiles: [
      vitestSetupFilePath,
      // custom setup files can be added here
    ],
    environmentOptions: {
      clarinet: {
        ...getClarinetVitestsArgv(),
        // add or override options
      },
    },
  },
});
```

</details>

### TypeScript configuration

The **tsconfig.json** provides TypeScript support:

{% code expandable="true" %}

```json
{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ESNext"],
    "skipLibCheck": true,

    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,

    "strict": true,
    "noImplicitAny": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": [
    "node_modules/@stacks/clarinet-sdk/vitest-helpers/src",
    "tests"
  ]
}
```

{% endcode %}

Properly setting the `include` property ensures TypeScript picks up the helpers defined in the Clarinet SDK package along with your tests.

## Network configurations

### Environment settings

Each network has its own configuration file in the **settings** directory:

```toml
[network]
name = "devnet"
deployment_fee_rate = 10

[accounts.deployer]
mnemonic = "twice kind fence tip hidden..."
balance = 100_000_000_000_000

[accounts.wallet_1]
mnemonic = "sell invite acquire kitten..."
balance = 10_000_000_000_000
```

These settings control:

* **Network ports**: API, RPC, and explorer endpoints
* **Account configuration**: Test wallets with STX balances
* **Chain parameters**: Network-specific blockchain settings

{% hint style="warning" %}
Never commit mainnet private keys or mnemonics. Use environment variables for production credentials.
{% endhint %}

## Common issues

<details>

<summary>Imports failing in tests</summary>

If you're encountering import errors in your tests, update your TypeScript configuration to use Vite's bundler resolution:

```json
{
  "compilerOptions": {
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true
  }
}
```

This configuration ensures TypeScript understands Vite's module resolution strategy and allows importing `.ts` files directly.

</details>


# Project Development

Clarinet streamlines the entire lifecycle of Clarity smart contract development. From project initialization to contract management and code formatting, you'll have the tools needed for professional workflows.

## Creating a new project

The `clarinet new` command creates a complete project structure with all necessary configuration files:

```bash
$ clarinet new my-defi-app
```

| Option                | Description                     | Example                                   |
| --------------------- | ------------------------------- | ----------------------------------------- |
| `--disable-telemetry` | Opt out of telemetry collection | `clarinet new my-app --disable-telemetry` |

For a deeper look at what Clarinet generates, see the [project structure](/clarinet/project-structure) guide.

## Managing contracts

### Creating new contracts

The `clarinet contract new` command generates both a contract file and a matching test file:

```bash
$ clarinet contract new token
Created file contracts/token.clar
Created file tests/token.test.ts
Updated Clarinet.toml
```

The generated contract includes a minimal template:

```clarity
;; token
;; <add a description here>

;; constants
;;

;; data vars
;;

;; data maps
;;

;; public functions
;;

;; read only functions
;;

;; private functions
;;
```

### Removing contracts

Clean up unused contracts with the `rm` command:

```bash
$ clarinet contract rm old-token
Removed file contracts/old-token.clar
Removed file tests/old-token.test.ts
Updated Clarinet.toml
```

## Checking project contract syntax

Validate your entire project setup:

```bash
$ clarinet check
✔ 3 contracts checked
```

Check specific contracts:

```bash
$ clarinet check contracts/token.clar
✔ contracts/token.clar Syntax of contract successfully checked
```

## Code formatting

Clarinet includes a formatter to maintain consistent style across your project.

Format all contracts in your project:

```bash
$ clarinet format --in-place
Formatted 5 contracts
```

### Formatting options

Customize formatting to match your team's style guide:

| Option              | Description                                            | Example                                 |
| ------------------- | ------------------------------------------------------ | --------------------------------------- |
| `--dry-run`         | Preview changes without modifying files                | `clarinet format --dry-run`             |
| `--in-place`        | Replace file contents (required for actual formatting) | `clarinet format --in-place`            |
| `--max-line-length` | Set maximum line length                                | `clarinet format --max-line-length 100` |
| `--indent`          | Set indentation size                                   | `clarinet format --indent 2`            |
| `--tabs`            | Use tabs instead of spaces                             | `clarinet format --tabs`                |

### Format single files

```bash
$ clarinet format contracts/messy-contract.clar --in-place
```

Format specific contracts with glob patterns:

```bash
$ clarinet format contracts/token*.clar --in-place
```

## Project configuration

### Working with requirements

Add mainnet contracts as dependencies:

```bash
$ clarinet requirements add SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait
Added requirement SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait
Updated Clarinet.toml
```

Clarinet adds the dependency to `Clarinet.toml`:

```toml
[project]
requirements = [
  { contract_id = "SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait" }
]
```

You can now implement traits from mainnet contracts:

```clarity
(impl-trait 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait)

(define-non-fungible-token my-nft uint)
;; ... implement required functions
```

##


# Contract Interaction

Clarinet provides powerful tools for interacting with your contracts during development. The console gives you an interactive REPL where you can call functions, inspect state, and debug issues in real time. This interactive REPL environment in the console is also referred to as the simnet.

<details>

<summary>What is a simnet?</summary>

* Simnet is a lightweight environment optimized for fast feedback loops, introspection and portability.
* Simnet focuses on letting you quickly iterate on your code and test the code of the contract itself through unit testing. It’s a good preliminary debugging step before introducing the additional variables that come with a fully-fledged blockchain environment.
* Simnet enables you to create a bunch of reports about contract analysis, execution costs, and more and is a useful tool for unit testing your smart contracts.
* In simnet, the blockchain environment is simulated and can be run anywhere (in the terminal with clarinet console, web browsers, GitHub actions, etc).

</details>

## Starting the console

Use `clarinet console` to launch an interactive session with your contracts deployed to a local simulated blockchain REPL. This is also referred to as simnet.

```bash
clarinet console
```

Sample startup output:

```
clarity-repl v3.3.0
Enter "::help" for usage hints.
Connected to a transient in-memory database.
```

The console supports several useful flags for different development scenarios:

| Option                                  | Description                                           |
| --------------------------------------- | ----------------------------------------------------- |
| `--enable-remote-data`                  | Connect to mainnet or testnet to query real contracts |
| `--deployment-plan-path <path>`         | Use a specific deployment plan                        |
| `--manifest-path <path>`                | Use an alternate `Clarinet.toml` location             |
| `--remote-data-api-url <url>`           | Specify a custom Stacks API endpoint                  |
| `--remote-data-initial-height <height>` | Set the starting block height for remote data         |

## Working with remote data

One of the most powerful features is the ability to interact with real mainnet or testnet contracts from your local console. This lets you test against actual deployed contracts:

```bash
clarinet console --enable-remote-data
```

Example contract calls:

```clarity
(contract-call? 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token get-decimals)
;; (ok u8)

(contract-call? 'SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-token get-name)
;; (ok "Arkadiko Token")
```

These capabilities help you:

* Test integrations with existing protocols
* Verify contract behavior against live chain state
* Develop contracts that depend on mainnet deployments

> **Warning: Remote data requirements**
>
> Before using remote data, add the target contract to `Clarinet.toml` with `clarinet requirements add SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token`.

### Using the Hiro API key

Avoid rate limits by setting the `HIRO_API_KEY` environment variable before launching the console. Clarinet forwards this key in the `x-api-key` header for all requests:

```bash
export HIRO_API_KEY=your_api_key_here
clarinet console --enable-remote-data
```

You can request a free API key from the Hiro Platform.

### Working with contracts

List all available contracts in the session:

```clarity
::get_contracts
;; +---------------------------------------------------------+----------------------+
;; | Contract identifier                                    | Public functions    |
;; |---------------------------------------------------------+----------------------|
;; | ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.counter      | (count-up)          |
;; |                                                         | (get-count (who ...))|
;; +---------------------------------------------------------+----------------------+

(contract-call? .counter count-up)
;; (ok true)

(contract-call? .counter get-count tx-sender)
;; u1
```

### Working with different principals

Switch between the provided test wallets to validate multi-user flows:

```clarity
::get_assets_maps
;; +-------------------------------------------+-----------------+
;; | Address                                   | uSTX            |
;; |-------------------------------------------+-----------------|
;; | ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM | 100000000000000 |
;; | ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 | 100000000000000 |
;; ...

::set_tx_sender ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5
;; tx-sender switched to ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5
```

### Working with block heights

Advance the chain to test time-dependent logic:

```clarity
::get_block_height
;; Current block height: 4

::advance_chain_tip 100
;; new burn height: 3
;; new stacks height: 104

::get_block_height
;; Current block height: 104
```

> **Tip: Console reference**
>
> For a complete list of console commands, see the [CLI reference](https://github.com/stacks-network/docs/blob/master/docs/reference/clarinet/cli-reference.md).

## Common issues

<details>

<summary>Contract not found errors</summary>

If you see `use of unresolved contract` errors, the contract may not be deployed or the name might be incorrect:

```clarity
(contract-call? .missing-contract get-value)
;; error: use of unresolved contract
```

Solutions:

* Check for typos in the contract identifier
* Confirm the contract is deployed in the current session with `::get_contracts`
* Use the correct prefix (`.` for local contracts)

</details>

<details>

<summary>Remote data connection issues</summary>

When you enable remote data, rate limits or connectivity problems can occur:

```clarity
(contract-call? 'SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-token get-name)
;; error: API rate limit exceeded
```

**Solutions:**

1. Set your Hiro API key: `export HIRO_API_KEY=your_key_here`
2. Use a custom API endpoint: `--remote-data-api-url https://your-node.com`
3. Wait for rate limit to reset (usually 1 minute)

</details>

##




---

[Next Page](/llms-full.txt/1)

