Release 4.0.1: Required upgrade before July 29

6 views
Skip to first unread message

Brice Dobry

unread,
Jul 21, 2026, 3:16:05 PMJul 21
to announce
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hello,

Stacks core developers have released Stacks Core version 4.0.1, available here:
https://github.com/stacks-network/stacks-core/releases/tag/4.0.1.

This release includes the activation logic for the Epoch 4.0 hard-fork, which
will activate on mainnet at Bitcoin block 960230 (approximately July 30 2026, AM
UTC). It is compatible with prior chainstates, but after the hard-fork
activation height, nodes running 4.0.1 and 3.4.x will diverge. Node operators
**must** upgrade before the activation height.

This release contains several bugfixes and improvements to the stacks-node and
stacks-signer binaries, ensuring more consistent block production.

* This release is compatible with existing chainstate directories from 3.x.
* This release is compatible with sBTC signer version 1.3.3.

Docker images have been published to GitHub Container Registry:

* stacks-core:
  https://github.com/stacks-network/stacks-core/pkgs/container/stacks-core

    docker pull ghcr.io/stacks-network/stacks-core:4.0.1

* stacks-signer:
  https://github.com/stacks-network/stacks-core/pkgs/container/stacks-signer

    docker pull ghcr.io/stacks-network/stacks-signer:4.0.1

This release includes the following changes:
https://github.com/stacks-network/stacks-core/blob/4.0.1/CHANGELOG.md

### Added

* Clarity 6: Add variadic `concat` built-in
* Adds two new Clarity 6 native functions: `verify-merkle-proof`, which checks a
  Bitcoin-style merkle inclusion proof against a known root using
  double-SHA-256, and `get-bitcoin-tx-output?`, which parses a serialized
  Bitcoin transaction (with or without SegWit witness data) and returns the
  output at a given index along with the canonical, witness-stripped txid in
  internal byte order
* Adds the ability to pause claiming of rewards in pox-5. This is an
  irreversible action, which can only be taken by the "pause admin", which is
  set initially at 4.0 activation.
* Added ed25519-verify to Clarity 6
* Adds a new epoch, epoch 4.0, which deploys pox-5, and a new Clarity version,
  Clarity 6, along with related boilerplate code.
* Complete L1 bitcoin staking integration tests, including both normal exit
  after the timelock expires, and early exit.
* pox-5: support seamless rollovers between bond and STX-only staking positions.
  A staker may now `register-for-bond` for the bond that starts immediately
  after their current bond ends or at the same cycle at which their STX-only
  staking unlocks. They can also `stake` STX-only while their existing
  bond/stake is ending. In these cases, the STX lock is carried forward (amount
  may go up or down) with no release. sBTC for the bond is also rolled forward
  via net transfer (or refunded on bond → stake). These rollovers are restricted
  to the bond L1 unlock window (last half cycle).
* Added `print` events for all interesting actions on the pox-5 contract and
  also improved the return values for some.
* The `/v2/pox` RPC response now includes `pox_5_sbtc_contract` and
  `pox_5_sbtc_registry_contract`, the sBTC token and registry contract
  identifiers that this node's PoX-5 references. On mainnet these are the
  canonical sBTC contracts; on non-mainnet they reflect the node's
  configuration.
* Add support to the pox-locking library for PoX-5.
* Added a private function, `transfer-from-reserve` to pox-5 to allow a
  consensus transfer of sBTC from the reserve.
* Added per-block `problematic_txs` markers to the Nakamoto block header (Epoch
  4.0+), letting miners flag transactions to skip during replay. The field is
  gated on a new header version, so pre-4.0 block serialization and hashes are
  unchanged, and the header version is now validated against the block's epoch.
  Until the policies are set, signers will reject any transactions in this list.
* Added secp256k1-decompress? to Clarity 6
* Added transaction-level `Staking` and `Pox` post-conditions, and matching
  in-contract `with-staking` / `with-pox` allowances. `Staking` constrains how
  much STX a principal may stake (lock for PoX) during a transaction. `Pox`
  gates the state-altering PoX-5 operations that act on a principal's existing
  position: `unstake`, `unstake-sbtc`, `update-bond-registration`, and
  `announce-l1-early-exit`, and is presence-based (block / allow / require).
  Both are only valid in Stacks epoch 4.0 and later, and in `Deny`/`Originator`
  post-condition mode an uncovered stake or PoX action fails the transaction. In
  Clarity 6 the `with-stacking` allowance was renamed to `with-staking` (the old
  `with-stacking` spelling remains valid in Clarity 4 and 5).
* Updated the print event inside `register-for-bond` to include the transaction
  info for L1 lockups.

### Changed

* Added `.cost-voting` disablement gate beginning from epoch 4.0
* Updated coinbase intervals for Epoch 4.0
* Recalibrated all Clarity 6 (Epoch 4.0) runtime cost functions in `costs_5.rs`
  using Callgrind instruction-count measurements from `clarity-cost-bench`.
  Arithmetic, tuple, sequence, hash, crypto, and store operations now have
  bench-derived linear formulas instead of forwarding to the Clarity 4 values,
  with a calibration baseline of 1 cost unit = 80,000 CPU instructions (a clean
  round value chosen to place the base overhead of any Clarity call at ≈38
  units).
* Doubled the Clarity read budget (`read_length` and `read_count`) for Stacks
  Epoch 4.0 blocks, via a new `BLOCK_LIMIT_MAINNET_40` cost limit. All other
  block limit dimensions (write and runtime) remain unchanged from Epoch 2.1
  onward.
* Add additional Clarity value sanitization pass to function invocations in
  Epoch 4.0
* Contract analysis now charges the runtime cost of `AnalysisUseTraitEntry` when
  a trait is resolved from the contract under analysis. This closes a metering
  asymmetry between the two lookup paths and applies starting with Epoch 4.0.
* Allow pox-5 L1 BTC lockups to use timelock unlock heights greater than or
  equal to the bond's minimum L1 unlock height.
* Restructure the pox-5 L1 BTC lockup witness script: the early-exit branch now
  requires revealing the 32-byte `sha256(to-consensus-buff? staker)` preimage
  alongside the early-unlock signature.
* Updated the `stacks-signer generate-staking-signature` command to generate
  PoX-5 signer grant signatures.
* Reduced the per-cycle `readCount` cost of pox-5 `stake` (and the other staking
  entry points that fold over lock cycles) by de-duplicating redundant map reads
  in `settle-rewards` and skipping `settle-staker-rewards` when the staker holds
  no shares in that cycle. A max-length (96-cycle) `stake` now costs ~2,336
  readCount instead of ~3,104 (~15.6% vs ~20.7% of the tenure-block budget),
  raising worst-case throughput from ~4 to ~6 such transactions per block.
* pox-5: `announce-l1-early-exit` is now callable by the staker themselves, not
  the bond's early-unlock admin. The `early-unlock-admin` field is removed from
  `protocol-bonds` and from the `setup-bond` parameter list, since no on-chain
  code path consumes it anymore. Re-announcing for the same bond returns the new
  `ERR_L1_EARLY_EXIT_ALREADY_ANNOUNCED`. The new read-only
  `has-announced-l1-early-exit` exposes per-staker announcement state for
  off-chain consumers and gates the re-entry assert on-chain.
* Reject `unstake-sbtc` and `announce-l1-early-exit` calls during a prepare
  phase.
* The node and `stacks-signer` now share a single version (`stacks_node_version`
  in `versions.toml`) and ship in one combined GitHub release: one set of binary
  archives (containing both binaries) plus the `stacks-core` and `stacks-signer`
  docker images, all tagged with the same version. The separate
  `stacks_signer_version`, the `signer-x.x.x` release tags, and the independent
  `release/signer-x.x.x` release path have been removed.
* Use new variadic `concat` in the pox-5 contract.

### Fixed

* Updates to pox-5 to prevent a scenario where a bond participant could switch
  signers, but that switch would cause the new signer to immediately start
  getting rewards, even though their signing power isn't updated yet.
* Fixed an issue related to signer managers not being able to withdraw their
  accumulated fees.
* Consensus now rejects blocks that contain transactions with non-normalized
  "high S" secp256k1 signatures. This is a requirement of SIP 005, but was never
  correctly implemented. This change applies starting with Epoch 4.0.
* Prevent counting duplicate lockups in pox-5 `register-for-bond`.
* In `signer-manager.clar`, the function `check-pox-addr` wasn't used. Now, it
  is used to check when a staker has passed a `pox-addr` as part of their
  calldata.
* Fixed an issue related to how current and future cycle rewards state is
  managed after unstaking.
* Fixed an error where there could be an arithmetic underflow if a staker
  claimed rewards before the signer claimed their own first. Instead, we now
  explicitly return an error.
* Remove the faulty `reward-cycle-to-unlock-height` from pox-5.
* Return rejected sBTC withdrawal amounts to stakers and let admins sweep
  orphaned fee-refund dust in the pox-5 reference signer-manager. The admin
  sweep now subtracts outstanding withdrawal liability so it can never sweep
  funds owed to stakers, and accepted withdrawals are retired via the
  permissionless `settle-accepted-withdrawal` to release their liability.
* Handle reward cycle with no STX-only stakers (all excess rewards go to the
  reserve).
* In Epoch 4.0 (PoX-5), the Clarity asset map now sums concurrent stacking
  entries for the same principal within a transaction (both within a frame and
  when merging frames) instead of rejecting the block. The pre-Epoch-4.0
  soft-fork behavior (rejecting PoX assetmap overwrites) is unchanged.
* Fixed PoX-5 L1 lockup CLTV height serialization so large unlock heights cannot
  truncate to lower Bitcoin script numbers.
* Re-check the signer key grant at every pox-5 new-stake entry point
  (`register-for-bond`, `update-bond-registration`, `stake`, `stake-update`), so
  revoking a grant with `revoke-signer-grant` now disables an already-registered
  signer manager from accepting any new stake. Previously revocation only
  blocked future `register-signer` calls, leaving a deprecated or buggy manager
  free to keep accumulating delegated STX and re-enter the signer set; its
  existing obligations still settle and wind down as the backing bonds/stakes
  expire.
* Fixed PoX-5 L1 lockup script construction to reject Bitcoin
  `CHECKLOCKTIMEVERIFY` values that would be interpreted as Unix timestamps
  instead of block heights.
* Allow only the signer to call `grant-signer-key`. Without this check someone
  could grief the signer, by watching for their call to `register-self` in the
  mempool, grabbing the `signer-key`, and then frontrunning a call to
  `grant-signer-key`, causing the signer's call to fail with
  `ERR_SIGNER_KEY_GRANT_USED`.
* Require that `revoke-signer-grant` is called directly only, not indirectly
  through any contract.
* Starting in Epoch 4.0, signer signatures on a Nakamoto block must be strictly
  ordered by the signer's index in the reward set. Previously a bug only
  compared each signature against the first signer's index, so only a partial
  ordering was enforced. The pre-Epoch-4.0 behavior is preserved for blocks
  validated before the activation so that historical blocks and un-upgraded
  peers validate identically.
* Gate the pox-5 callback functions in the sample signer-manager contract so
  that they can only be called directly by pox-5.
* Updates the max-fee settable by the signer to be 99.99%, to prevent accounting
  issues.
* Fix an off-by-one in the Clarity `map` built-in over unequal-length sequences.
  The fix is consensus-breaking and epoch-gated, activating in Epoch 4.0.
* Do not allow functions that modify the staker/signer set during the prepare
  phase.
* The miner-spend estimators (`get_miner_spend` CLI helper and `MinerStats`) now
  model block-commit outputs using the PoX-5 waterfall single-output scheme when
  active, matching the relayer.
* Surface cost-tracking errors raised during Clarity trait-compliance
  type-checking instead of masking them as `IncompatibleTrait`. The fix is
  consensus-breaking and epoch-gated, activating in Epoch 4.0.
* Fix tuple `merge` producing an oversized value: starting in Epoch 4.0, a
  `merge` whose combined size exceeds the maximum value size is rejected cleanly
  with `ValueTooLarge` at the merge site (in both static analysis and at
  runtime), instead of aborting the block. Behavior in earlier epochs is
  unchanged.
* Fix `uint-to-buff-le` in pox-5 contract to handle values >255 correctly.
* Fix the minimum threshold reported by /v2/pox when pox-5 is the active
  contract.
* Tightens the Clarity 6 `verify-merkle-proof` builtin so that it rejects
  CVE-2012-2459-style "inflated `tx-count`" forgeries that relocate the last
  real leaf of an odd-sized tree into the duplicated-padding region (e.g.
  presenting the same real Bitcoin tx as `(tx-index 3, tx-count 4)` against the
  merkle root of a 3-tx block).
* Replaced `time` dependency in logging code with `chrono` to allow it to work
  properly in Wasm builds.

### Removed

* Removed the `allow-contract-caller`, `disallow-contract-caller`, and
  `check-caller-allowed` functions and the `allowance-contract-callers` map from
  `pox-5`. Stacking methods may now be invoked through any contract-caller;
  stackers protect themselves with the in-contract `with-stacking` / `with-pox`
  allowances or transaction-level `Staking` / `Pox` post-conditions instead.

- ---

Stacks Core:

Git commit hash: 62e03cc5551bfc574223c2b78ce04ceca30cec37

SHA512 checksums (CHECKSUMS.txt):
4a06ac9a7f98888f2004d42bc89f66978ad5724ee4eabcfd86cf3a718cfcd552c21dc92299620ebbc709d759eddfbe1b444472d035d004ac8fbc0ba57680cf8f
linux-glibc-arm64.zip
7d66ce337cf3bc4b218b10fa4a66b063e90fe04d15d41c84feff72f829ac417a6b430fc07d3b8e1039952a57280c7f9e74b7630dee64c0608c7d0beba7051194
linux-glibc-x64.zip
3fd7046d3711d97664128cefe9b42a00fde29c0269e0e48a24e6a8211a8f57b57b0b20b1af720b19cf9367b7b302ba71cd74e7b0ec1c53ccc720bc26fb70d63f
linux-musl-arm64.zip
b42efa05cd22d5c243f037ace27b302c4b7e3cb3eeee79821dcefc95dd3eb6214ef4f964fd0e99047196ad6ad8a2c746ac322b699430ed6958415924b90eb04e
linux-musl-x64.zip
5276896143c25bd99907a6e7d122ec869c55da4e02d004872fd5739e435ad98874328b86eb26cb4a051a81db67b36bcd38a26c84c172ee6161331c1007f400bb
macos-arm64.zip
95ad220213f7f278fe49f5917471be828f5b8ecb25daadfc9473cda86bf01e67c4712396e90838ecd58fb35114518c5e99e4d63123cb1562a7ef7d20fca2b5c1
windows-x64.zip

Best,

Brice Dobry Staff Engineer, Stacks Labs
-----BEGIN PGP SIGNATURE-----

iQFlBAEBCABPFiEEVTrGj54NWyQJkqD84zO/PN0rBYYFAmpfxV0bFIAAAAAABAAO
bWFudTIsMi41KzEuMTIsMCwzFRxicmljZUBzdGFja3NsYWJzLmNvbQAKCRDjM788
3SsFhtb2B/9TU/3YtqyZH9sx5F1/q/MHkGaT+NA0vMj40xnEj9a6ek8oxRhfMBf9
SuR/BhOLKbRMtWt3m1cd/LM5lFADXzvCduSfSd3G7t9HAkOhFGlXlJui5LNHUSK+
QlidfrB+NXH0e+3hVOK6Trl/VDGhliA5jTpOUNoZrlYfB/Vab5QjzhurTWbjHUIA
s5f2bItVMgzOhHL8C1U37Jg84VPCj2Gb4D4twlOc1D21Pzv5+8nq8yBQsqqKfu3f
uOwpyTbkzv50rdL8VaCuCwmeLFvUvRB4pqEnMiegycpi3pTEqNucZbIXaVuaxZsx
nqwGBYHz9VxB7VssIVQ+iuS4uUFc/I0Z
=OB0b
-----END PGP SIGNATURE-----
Reply all
Reply to author
Forward
0 new messages