stacking
Stacking is implemented as a smart contract using Clarity. You can always find the Stacking contract identifier using the Stacks Blockchain API v2/pox endpoint.
Currently, stacking uses the pox-4 contract. The deployed pox-4 contract and included comments can be viewed in the explorer.
In this walkthrough, we'll cover the entire stacking contract from start to finish, including descriptions of the various functions and errors, and when you might use/encounter them.
Rather than walking through the contract line by line, which you can do by simply reading the contract code and the comments, we'll instead explore it from the perspective of conducting stacking operations, including solo stacking, delegating, and running a pool.
At the bottom you will find a list of some errors you may run into and their explanations.
There are a few utilities that make interacting with this contract easier including Leather Earn as an UI and the @stacks/stacking package for a JS library.
Hiro has a detailed guide available for stacking using this library as well as a Nakamoto guide specifically for the additions made to work with pox-4.
Prerequisites
If you are not familiar with stacking as a concept, it will be useful to familiarize yourself with that first before diving into the contract.
Solo Stacking
Solo stacking is the simplest option, and begins by calling the stack-stx function.
stack-stx
This function locks up the given amount of STX for the given lock period (number of reward cycles) for the tx-sender.
Here's the full code for that function, then we'll dive into how it works below that.
First let's cover the needed parameters.
amount-ustxis the amount of STX you would like to lock, denoted in micro-STX, or uSTX (1 STX = 1,000,000 uSTX).pox-addris a tuple that encodes the Bitcoin address to be used for the PoX rewards, details below.start-burn-htis the Bitcoin block height you would like to begin stacking. You will receive rewards in the reward cycle followingstart-burn-ht. Importantly,start-burn-htmay not be further into the future than the current reward cycle, and in most cases should be set to the current burn block height.lock-periodsets the number of reward cycles you would like you lock your STX for, this can be between 1 and 12.signer-sigis a unique generated signature that proves ownership of this signer. Further details for its role and how to generate it can be found in the How to Stack document.signer-keyis the public key of your signer, more details in the How to Run a Signer document.max-amountsets the maximum amount allowed to be stacked during the provided stacking period.auth-idis a unique string to prevent re-use of this stacking transaction.
It's important to make sure that these fields match what you pass in to the signer signature generation. If they don't, you will likely get error 35 (ERR_INVALID_SIGNATURE_PUBKEY) when trying to submit this transaction as the signer signature will not be valid.
Supported Reward Address Types
The stack-stx function performs several checks including:
The
start-burn-htresults in the next reward cycleThe function is being called by the
tx-senderor an allowed contract callerThe
tx-senderis not currently stacking or delegatingThe
tx-senderhas enough fundsThe given
signer-keyis valid, proving ownershipStacking can be performed (amount meets minimum threshold, lock period and bitcoin address are valid)
Next the function registers the provided PoX address for the next reward cycle, assigns its specific reward slot, and adds it to the stacking-state map, which keeps track of all current stackers per reward cycle.
Finally it returns the lock-up information so the node can carry out the lock. This step is what actually locks the STX and prevents the stacker from using them on-chain.
From here, the locked STX tokens will be unlocked automatically at the end of the lock period. The stacker can also call stack-increase or stack-extend to increase the amount locked or extend the time.
Delegated Stacking
Delegated stacking is essentially a multi-step process where delegators give pool operators permission to lock STX on their behalf. The typical flow:
There are also alternative actions like revoking delegation (see contract functions).
delegate-stx
This function is called by the individual stacker delegating their STX to a pool operator. An individual stacker choosing to delegate does not need to run their own signer.
This function does not actually lock the STX, but just allows the pool operator to issue the lock.
Parameters:
amount-ustx: amount delegating (uSTX)delegate-to: Stacks address of the pool operatoruntil-burn-ht: optional expiry burn height for the delegationpox-addr: optional Bitcoin address where this delegator wants rewards sent (if supplied, pool operator must send rewards to this address)
Checks: caller allowed, pox-addr version valid if provided, delegator not already delegating. Updates delegation-state. No STX are locked yet — the pool operator must call delegate-stack-stx.
delegate-stack-stx
Called by the pool operator to partially stack a delegator's STX.
This function validates the delegation record, ensures the delegator has the funds and is not already stacking, runs lightweight stacking checks, registers the partial stacked amount, and updates stacking-state. The STX remain partially stacked until the operator commits.
stack-aggregation-commit-indexed / inner-stack-aggregation-commit
The stack-aggregation-commit-indexed function wraps the private inner-stack-aggregation-commit. The private function commits partially stacked amounts into the reward set so each pox-addr obtains a reward-slot index.
Key points:
Validates caller and signer signature.
Validates stacking conditions.
Adds the aggregated pox-addr to the reward cycle and returns its reward-set index.
Deletes the partial-stacked entry and logs it.
How Stacking Reward Distribution Works
All of the above stacking functions take a pox-addr field that corresponds to a Bitcoin address where BTC rewards will be sent. It's important to understand how these addresses are used and how reward distribution is handled.
How Bitcoin rewards are distributed is primarily up to the discretion of the pool operator. Since PoX reward distributions are handled using Bitcoin transactions, there is currently not an effective way to automate their distribution to individual delegated stackers.
Role of pox-addr by function:
stack-stx: Bitcoin address for the solo stacker to receive rewards.
delegate-stx: Optional. If omitted, the pool operator decides where to send this delegator's rewards. If provided, the pool operator must send rewards to that address. Note: if provided, the delegator must have enough STX to meet the minimum stacking amount (each unique
pox-addrconsumes a reward slot).delegate-stack-stx and stack-aggregation-commit-indexed:
pox-addris where the pool operator will receive BTC rewards for that aggregated stake. Pool operators typically use wrapper contracts or off-chain accounting to distribute BTC to delegators.
Errors
You may encounter several errors when trying to perform stacking operations. Below are some of the more common errors with explanations and how to resolve them.
Was this helpful?
