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
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
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). Theu1tou3codes come from Clarity'sget-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?