Self-hosted service
stacks-sbtc/sbtc avatar
stacks-sbtc/sbtc

sbtc: the Bitcoin-backed layer on Stacks and its signer infrastructure

sBTC is a 1:1 Bitcoin-backed asset, enabling users to put their BTC to work in DeFi, dApps, and other applications.

579 stars56 forksRustGPL-3.0

At a glance

What is it?
sbtc is a 1:1 Bitcoin-backed asset that lets BTC holders use their bitcoin in DeFi and dApps on Stacks, and the repository is the implementation of that system rather than a library: a Rust workspace holding the signer, the protocol client, the emily API and a web frontend, with a local development network that runs three Nakamoto signers. It is GPL-3.0 licensed, and its design decisions are tracked in public GitHub issues rather than in private documents.
Who is it for?
Adopt sBTC if you are building on the Stacks Bitcoin-backed asset and need the signer, the protocol client and the emily API rather than a paper design, and if your team is prepared to run three signers locally.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What sBTC is, and what this repository contains

sBTC is described as a 1:1 Bitcoin-backed asset, enabling users to put their BTC to work in DeFi, dApps and other applications, and the homepage is the Stacks documentation page for it.

That gives the purpose, but the repository is not a library you add to a project. It is the implementation of the system, and the directory listing shows the scope: a signer/ directory, a wsts/ directory, an emily/ directory for the API, a blocklist-client/ and a blocklist-openapi-gen/ pair, a contracts/ directory, a web/ frontend, a devenv/ directory, a docker/ directory, protobufs/, a supply-chain/ directory, and emily_cron/ and emily_sidecar/ for the scheduled and sidecar parts of the API.

The naming is worth decoding because it explains the architecture. Emily is the API service, and its name recurs through emily_cron, emily_sidecar and the emily-client crates. The signer is the component that holds keys and produces signatures. wsts is a separate distributed threshold signing library, and having it as a workspace member rather than an external dependency tells you the signing scheme is part of what this repository owns.

The primary language is Rust, the licence is GPL-3.0, the default branch is main, and the recent releases are v1.4.1 from 2026-10-16, v1.4.0 from 2026-10-14 and v1.3.6 from 2026-10-08. The last push was on 2026-10-16 and the project is not archived.

The licence matters more here than it would for a utility crate. This is protocol code for a system that holds Bitcoin, and GPL-3.0 is a deliberate choice for infrastructure that others may want to run and audit.

Decisions in public issues, and why the README points there

The Design Docs section is unusual and worth reading closely.

The README states that all decisions are made and tracked via GitHub issues where they and their rationale can be verified publicly, and that due to sBTC's critical nature extensive research and planning has been done to ensure all funds remain secure on launch. The links that follow are filtered issue queries rather than documents: research issues with a research label, design issues with a design label, and a link to additional documents in a shared drive.

The reasoning is sound. For a system where a bug can cost users their Bitcoin, a design document that states a decision without its alternatives is much less useful than an issue thread where the rejected options are visible. The cost is that the reasoning is not conveniently packaged, and a reader who wants to know why the signer set size is what it is has to go and read threads.

The releases section is similarly thin, pointing to RELEASE.md for the release process, which is a reasonable convention for a project with tagged releases and a changelog.

One thing to notice is the set of links at the top: a landing page at sbtc.tech, the Stacks documentation for the concept, and an sBTC address constructor hosted from the project. An address constructor is the kind of tool a project publishes when users are expected to derive Bitcoin addresses from a Stacks principal, and its presence is a sign of where the intended users are.

The contributing section opens by asking you to review the code of conduct before going any further, which is a small thing that says the project expects external contributors and has put governance in place for them.

The toolchain, and the seven dependencies a contributor has to install

The Tools to Install section lists what a developer needs on their machine, and the list is long enough to be a real barrier to a first contribution.

Cargo builds the Rust packages. Cargo-lambda compiles the package for AWS Lambda, installed with cargo install cargo-lambda --locked --version 1.9.2, which tells you that a piece of this system runs as a serverless function. pnpm manages node packages. Make is the development task runner, described as natively present on nearly every system. Docker is used for running integration tests. protoc compiles protobuf files. And uv manages python packages, which points at the emily_cron and emily_sidecar components.

There is a warning above the list that this repository is under development and that the section may become outdated, with an invitation to open an issue if something is missing.

Three optional tools are for maintainers of the dependency graph rather than for contributors to the code. Cargo Nextest runs the unit and integration tests. Cargo Vet vets Rust dependencies, which is a supply chain check. And Cargo Machete detects unused dependencies, which is a dependency hygiene check. The README points at the exact workflow versions used in CI for each, which is a small courtesy that saves an afternoon of version mismatch.

The developer shell is the escape hatch for all of this. If you have nix and flakes installed, one command gives you a shell with all dependencies in place:

bash
nix develop

And the README provides a command that checks the versions the resources need:

bash
echo "\n--- sBTC tool versions ---" \
    && cargo --version \
    && cargo lambda --version \
    && echo "pnpm $(pnpm --version)" \
    && make --version | head -n 1 \
    && uv --version

The example output shows what a working machine looks like, and the versions in it are recent enough to be worth reading twice: cargo 1.98.1, cargo-lambda 1.9.2, pnpm 9.1.0, GNU Make 3.81 and uv 0.8.13. Note the package.json in the repository pins pnpm at 10.33.0, so the sample output is from a machine that predates that pin.

Building, testing and the local network

The build instructions are short and they delegate to the Makefile, with the reason given: the Makefile commands will build the dependencies in the right order.

The targets are make install for node dependencies, make build to build packages, make lint to lint packages, make clean to clean the workspace, make test to run non-integration tests, and make integration-test for the integration tests, with the requirement to run make integration-env-up before and make integration-env-down afterwards.

The Makefile itself shows how the pieces fit. The install target splits into install-py, which sets up virtual environments for emily_cron and emily_sidecar with uv, and install-pnpm, which installs node packages with a frozen lockfile. The build target depends on two code generation steps, blocklist-client-codegen and emily-client-codegen, plus contracts, and then runs a cargo build with --locked and --bins --lib, excluding the two openapi generation crates. The test target runs cargo nextest with the testing feature, then the Python unittest discovery in both emily directories, then pnpm --recursive test. Cargo flags are consistently --locked, and the Makefile exports a DATABASE_URL pointing at a local Postgres for the signer.

The local development network is the part that gives the project its shape. A Docker Compose file under docker/ starts a Stacks node, the Stacks API, a Bitcoin node on devnet, three Nakamoto signers, a Stacks explorer, and a Mempool.space Bitcoin explorer. Two make targets drive it, make devenv-up to start the network and make devenv-down to stop it and remove the containers and networks.

The service list is worth reading because it shows the full system: Stacks node at localhost:20443, Stacks API at localhost:3999, Bitcoin node at devnet:devnet@localhost:18443, the three signers at localhost:30000 through 30002, the Stacks explorer at localhost:3020 and the Mempool.space Bitcoin explorer at localhost:8083.

Three signers is the detail that matters. A threshold scheme with three signers tolerates one failing, and running three locally is how you develop against the real protocol rather than a mock. Rebuilding the containers from your branch uses the compose file directly:

bash
# Build signers + emily (~2m, if `sbtc-build` was already built)
docker compose -f docker/docker-compose.yml --profile default --profile bitcoin-mempool --profile sbtc-signer build
# Build bridge-website (~2m)
docker compose -f docker/docker-compose.yml build --no-cache sbtc-bridge-website

```

There is a platform note attached, that you may need to disable buildkit by prefixing the commands with DOCKER_BUILDKIT=0 if you get a pull access denied when building the containers on MacOS.

How to evaluate it, and where the risk actually sits

This is a protocol implementation for a Bitcoin-backed asset, so the evaluation has to be about custody and consensus rather than about code quality.

The first question is where the keys live and who can move them. The repository has three Nakamoto signers in the local network and a signer/ directory, and a threshold scheme means no single party can move funds alone. Whether that is sufficient depends on the protocol specification, which is in the Stacks documentation and the public design issues rather than in this repository. A team evaluating sBTC for custody reasons should read those, not the Rust code.

The second question is what happens when the signers disagree or go offline. The local devnet is designed so you can answer that empirically, because three signers means you can stop one and watch what the others do, and the README's readiness instructions are specific about it: wait for Nakamoto on the stacks explorer, usually around block number 30, then watch the deployer account for the contract deployment and the first rotate key transaction, and once you see that transaction everything is ready.

That last detail, the rotate key transaction, is a good sign for a threshold scheme. It means key rotation is an observable on-chain event, which is the property you want in a system where a signer key can be rotated without a governance vote.

The third question is the one the repository is unusually honest about. The README says the tool list may become outdated and asks for issues where something is missing, and the design decisions live in issue threads that will be slow to read. For a project at this stage of maturity, that is the right trade and also a real cost.

On the engineering side the signals are good and conventional. Cargo dependencies are pinned with --locked, there is a supply-chain/ directory, cargo-vet and cargo-machete run in CI, the lockfile is frozen for pnpm, the Rust toolchain is pinned with rust-toolchain.toml, there is a nextest.toml, and the workspace uses resolver 3 with generated sources kept in a .generated-sources/ directory rather than committed by hand. The dependency on stacks-core is pinned to a specific revision, which means a Stacks upgrade is a deliberate act rather than something that happens when a transitive dependency moves.

Editorial conclusion

Adopt sBTC if you are building on the Stacks Bitcoin-backed asset and need the signer, the protocol client and the emily API rather than a paper design, and if your team is prepared to run three signers locally. Do not treat it as a library to import, since this is the protocol implementation, and do not base a custody decision on the code alone, because the specification, the key management model and the key rotation rules live in the Stacks documentation and in public design issues rather than in this repository. Before you commit, read the design issues, bring up the devnet with make devenv-up and watch for the first rotate key transaction, and check the pinned stacks-core revision against the Stacks release you intend to run.

Frequently asked questions

What is sBTC?

It is a 1:1 Bitcoin-backed asset that enables users to put their BTC to work in DeFi, dApps and other applications on Stacks. The homepage is the Stacks documentation page for the concept, and the code lives in this repository.

How are design decisions made in the sBTC project?

All decisions are made and tracked via GitHub issues where they and their rationale can be verified publicly, with separate issue labels for research and design. The README explains that this is because of sBTC's critical nature and the extensive research and planning done to keep funds secure on launch.

What tools do I need to build sBTC from source?

Cargo, cargo-lambda installed with cargo install cargo-lambda --locked --version 1.9.2, pnpm, Make, Docker for integration tests, protoc, and uv for the Python packages. Optionally Cargo Nextest, cargo-vet and cargo-machete, and with nix and flakes installed a single nix develop command gives a shell with all dependencies.

What does the local sBTC development network run?

A Docker Compose network with a Stacks node at localhost:20443, the Stacks API at localhost:3999, a Bitcoin node on devnet, three Nakamoto signers at localhost:30000 through 30002, a Stacks explorer at localhost:3020 and a Mempool.space Bitcoin explorer at localhost:8083. It is started with make devenv-up and stopped with make devenv-down.

What licence is sBTC released under and how is the code structured?

The repository is licensed under GPL-3.0. The Cargo workspace holds the signer, the wsts threshold signing library, the emily API, the blocklist client and its openapi generator, and the contract crates, with generated sources kept in a .generated-sources/ directory and the Stacks core dependency pinned to a specific revision.

Official sources

  1. License: GPL-3.0
  2. Project website
  3. README
  4. Releases
  5. stacks-sbtc/sbtc on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stacks-sbtc-sbtc.svg)](https://hysenlabs.com/projects/stacks-sbtc-sbtc)

Was this useful?