For the complete documentation index, see llms.txt. This page is also available as Markdown.

Opening a Bond Position

How to open a protocol bond: the allowlist, the two Bitcoin legs, the registration deadline, and what the contract checks.

A protocol bond pairs locked STX with a Bitcoin leg for 12 reward cycles, about six months. You open one with a single register-for-bond call on Stacks. The Bitcoin leg is either native BTC under a timelock you fund on Bitcoin first, or sBTC the contract takes from you in the same call.

For STX-only staking, see Stake to an Existing Signer-Manager. For how bonds work, see Bitcoin Staking.

Before you start

  • An allowlist entry for the bond. Every registration needs one, on either leg. Getting on the allowlist is an off-chain conversation with the Stacks Endowment, and the list is fixed when the bond is set up, roughly seven days before it starts. To bond sBTC without an entry of your own, join a bond pool.

  • A signer-manager that is registered and holds a live signer-key grant. Your rewards route through it.

  • Enough STX. Each bond sets a minimum amount of STX per BTC. Your locked plus unlocked balance must cover the amount you commit.

  • No overlapping position. A principal holds one position at a time, and a bond cannot overlap an STX-only stake or another bond.

Pick your Bitcoin leg

Native BTC
sBTC

What is locked

BTC in a timelocked output on Bitcoin that you control

sBTC transferred to the contract

Steps

Fund on Bitcoin, wait for confirmation, then register

One Stacks transaction

Ending it early

announce-l1-early-exit, then a co-signed Bitcoin spend

unstake-sbtc, in part or in full

Pool option

No

Yes

A registration uses one leg or the other, never both, and the leg is fixed for the term.

Timing

  • Register before the bond starts. After the start height the contract rejects the call with ERR_BOND_ALREADY_STARTED (u43). There is no grace period.

  • Not in the prepare phase. The last 100 Bitcoin blocks before every cycle boundary, including the one before the bond starts, reject registration with ERR_STAKE_IN_PREPARE_PHASE (u47). The last block you can register in is 101 blocks before the bond's start height.

  • Native BTC confirms first. Registration proves a confirmed Bitcoin output, so fund the lock address early enough to confirm and still register in time.

Moving into a new bond from an ending bond or stake uses the same call. See Rolling into a new position.

Native BTC, step by step

1

Confirm your allowlist entry

Read your cap for the bond. A missing entry means you are not allowlisted.

2

Derive the lock address

The address is deterministic: it comes from your Stacks address, the bond's unlock height, your staker-unlock-bytes, and the bond's early-unlock-bytes. Anyone can rederive it to check the lock.

3

Fund it and wait for confirmation

Send the BTC from a wallet that can pay to a P2WSH output. You can lock across up to 10 outputs in one registration, and the total must stay within your cap.

4

Register on Stacks

Call register-for-bond with the STX amount, your signer-manager, and a proof for each output: the block header, the raw transaction, and its Merkle path.

5

Confirm the position

A transaction ID confirms submission, not success. Read the membership back before treating the bond as open.

sBTC, in one transaction

Call register-for-bond with the sBTC amount instead of lockup proofs. The contract transfers the sBTC from you. Attach post-conditions for the STX lock and the sBTC transfer: under the default deny mode, the transaction aborts without them.

What the contract checks

register-for-bond checks, in order:

  • On the native BTC leg, the bond exists (u7), then each lockup output in turn: a complete 80-byte header (u39), a transaction that decodes and has the output you named (u1, u2 or u3), unlock height in range (u52), script (u42), amount (u45), no duplicate outpoint (u46), a header matching the Bitcoin block at that height (u40), and Merkle proof (u41). The u1 to u3 codes come from Clarity's get-bitcoin-tx-output?, not from pox-5.

  • The bond exists (u7) and you are on its allowlist (u11).

  • Not in the prepare phase (u47).

  • Your STX amount meets the bond's minimum for your sats (u8).

  • The bond has not started (u43).

  • No overlapping STX-only stake (u19).

  • Your sats are within your cap (u10), and your balance covers the STX (u8).

  • Your signer-manager accepts the stake. This is a call into the manager contract, which can reject it with its own error.

  • The signer-manager is registered (u23) with a live grant (u17).

  • No overlapping bond membership (u9), and, when rolling from an ending bond, the rollover window is open (u48).

What you are committing to

  • 12 reward cycles. Your STX stays locked until the bond ends, whichever leg you chose.

  • The full amount up front. You cannot add BTC or sBTC to a membership after registration.

  • Ending early changes the Bitcoin leg only. See Ending or Changing a Bond Position.

Building a registration

For wallet, custodian, and app developers. The examples use @stacks/bitcoin-staking 7.6.0. The canonical lock script is the contract's construct-lockup-script in pox-5.clar.

Step 1: check the allowlist and derive the lock address

Step 2: build the proof once the output confirms

Step 3: preflight and build the registration

The preflight does not run the signer-manager's own acceptance check, and it verifies only part of each lockup proof: the unlock height, the duplicate-outpoint check and the header. The Merkle proof, script, amount and transaction parse are verified on-chain only.

The sBTC variant

Pass lockup: { kind: 'sbtc', sbtcSats } and add a post-condition for the sBTC transfer. The contract moves only the difference between the sBTC it already holds for you and the new total, so bound it from above:

Step 4: confirm the membership

fetchBondMembership returns undefined until the registration lands, and again once the bond's term has ended.

Was this helpful?