Clarity 5: Fixing known issues in Clarity
By Brice Dobry
- Idea
- Draft
- Accepted
- CAB vote
- Recommended
- Activation
- Ratified
Abstract
This version of Clarity is being proposed solely to address and resolve documented issues with existing functionality, specifically those that require a hard-fork to change. The implementation for this SIP should only resolve problems in the current Clarity implementation or make beneficial changes to under-specified aspects of the Clarity language and virtual machine (VM).
Consideration Advisory Board votes
Introduction
This SIP intends to solve the known issues in the implementation of the Clarity VM, without making any changes to the intended behavior of the Clarity language.
Specification
Resolve the discrepancy in secp256r1-verify described in SIP-035
In Clarity 5 and above, secp256r1-verify will no longer double-hash its input.
See SIP-035 for details.
Runtime error when passing an empty buffer to from-consensus-buff?
Beginning in Clarity 5, computing the cost of passing an empty buffer to
from-consensus-buff? will no longer trigger a runtime error. Instead, the cost
will be charged appropriately, and the expression will return none, as
originally intended. See issue
#6683.
Bug inside at-block expressions
From issue #6123:
Epoch 3 introduced a bug which causes
burn-block-heightto always return the current burn block height, even if inside of anat-blockexpression. This should be fixed to behave as expected in the next hard-fork.
In addition to burn-block-height, it was also determined that this same error
effects stx-account and stx-get-balance. These two functions can return an
incorrect value inside of an at-block since the incorrect burn block height is
used to determine the locked status of the STX.
In Clarity 5 and above, burn-block-height will return the correct value when
used inside of an at-block expression.
Increased stack depth
Currently, the Clarity VM limits the call stack of a transaction execution to a depth of 64 and several user applications have been hitting this limit recently. This value was not specified in any previous SIPs, but was chosen to constrain memory usage by the VM. Upon further testing, it has been determined that this value can safely be increased to 128 without imposing unreasonable requirements on Stacks node runners. Effective in epoch 3.4, the stack depth will be set to 128.
Rejectable transactions
Several kinds of errors have been avoided in the Clarity VM via a soft-fork mechanism, causing transactions that trigger these problematic situations to be rejected, not allowed to be included in a block. This strategy is useful for quickly patching issues without requiring a hard-fork. However, once the soft-fork is in place, the next time a hard-fork is executed, these errors can all be transitioned to errors that can be included in a block. This is much better for the network, since not including a transaction in a block has several downsides:
- Miners cannot charge a fee for processing the transaction
- Users may be confused as to why their transaction is not being included, causing that transaction and all later transactions (with higher nonces) to stall
- These unmineable transactions remain in the mempool, unprocessed, until they age out
With the upgrade to epoch 3.4, all known reachable "rejectable" errors will become includable errors.
Allow trait use in same contract
Currently, a trait defined in a contract cannot be used at the top-level of that
contract. For example, the code below will result in a NoSuchContract error.
(define-trait trait-1 (
(foo
()
(response int int)
)
))
(define-private (bar (F <trait-1>))
(unwrap-panic (contract-call? F foo))
)
(bar .c-foo)
This behavior is a bit surprising. Beginning in Clarity 5, this usage will be supported. See issue 6831.
Allow contract-call? to constant
Effective in Clarity 2, the type-checker does not complain about using a
constant as the target of a contract-call?, for example:
(define-constant MY_CONTRACT .contract-a)
(define-public (call-foo)
(contract-call? MY_CONTRACT foo)
)
Despite passing type-checking, this contract would fail during runtime, with an
error, RuntimeCheckErrorKind::ContractCallExpectName. This again is surprising
behavior. Beginning in epoch 3.4, this usage will be supported.
Copyright
This SIP is made available under the terms of the BSD-2-Clause license, available at https://opensource.org/licenses/BSD-2-Clause. This SIP’s copyright is held by the Stacks Open Internet Foundation.
Related Work
This SIP is focused on fixing consensus issues discovered in previous implementations of Clarity, or improving behavior which is unspecified in prior SIPs. The existing SIPs defining Clarity are:
Backwards Compatibility
Clarity 5 will be implemented with these changes while maintaining backwards compatibility for previous versions of Clarity. Existing contracts will continue to execute with the existing behavior, but new contracts will default to Clarity 5.
Activation
In order for this SIP to activate, the following criteria must be met:
- At least 80 million stacked STX must vote, with at least 80% of all stacked STX committed by voting must be in favor of the proposal (vote "yes").
- At least 80% of all liquid STX committed by voting must be in favor of the proposal (vote "yes").
All STX holders vote by sending Stacks dust to the corresponding Stacks address from the account where their Stacks are held (stacked or liquid). To simplify things, users can create their votes by visiting the ballot.gg platform. Voting power is determined by a snapshot of the amount of STX (stacked and unstacked) at the block height at which the voting started (preventing the same STX from being transferred between accounts and used to effectively double vote). The voting addresses are also shared below.
Solo stackers only can also vote by sending a bitcoin dust transaction (6000 sats) to the corresponding bitcoin address.
| Vote | Bitcoin | Stacks | ASCII Encoding | Msg |
|---|---|---|---|---|
| yes | 11111111111mdWK2VXcrA1eceSntcp | SP00000000001WPAWSDEDMQ0B9K76XTZ79N | 000000000000000000007965732d7369702d3339 | yes-sip-39 |
| no | 111111111111ACW5wa4RwyepZ84byy | SP000000000006WVSDEDMQ0B9K76JZVAKY | 00000000000000000000006e6f2d7369702d3339 | no-sip-39 |
If the SIP is approved, epoch 3.4 will activate at Bitcoin block height 943000, targeting March 30, 2026.
Note (2026-03-24)
Due to an issue identified in the late stages of testing before the release, the activation height has been postponed to Bitcoin block height 943,333, targeting 20:00 UTC on April 2, 2026 to ensure that all network participants have sufficient time to upgrade their stacks-node software.
Activation Status
At the end of Bitcoin block height 941,639, the following vote was recorded: A total of 97,497,945 STX participated, with 97,497,945 STX (100%) voting 'Yes' and 0 STX (0%) voting 'No'.
A breakdown of the onchain vote is as follows:
-
For STX locked in stacking, a total of 86,325,407 STX participated.
- Of this, 86,325,407 STX (100%) voted 'Yes'.
- While 0 STX (0%) voted 'No'.
-
For unlocked STX, a total of 11,172,535 STX participated.
- Of this, 11,172,535 STX (100%) voted 'Yes'.
- While 0 STX (0%) voted 'No'.
Total of 67 addresses participated, a breakdown is as follows:
- Via Ballot.gg website: 32 addresses
- STX Dust Transactions: 25 addresses
- Bitcoin Address Votes: 10 addresses
The open-source Ballot.gg repository, which includes the tally process and the audit script used to process and verify the results, can be found here: https://github.com/BlockSurvey/ballot/tree/main?tab=readme-ov-file#poll-results-auditor
Note (2026-03-24)
Due to an issue identified in the late stages of testing before the release, the activation height has been postponed to Bitcoin block height 943,333, targeting 20:00 UTC on April 2, 2026 to ensure that all network participants have sufficient time to upgrade their stacks-node software.
Activation Status
At the end of Bitcoin block height 941,639, the following vote was recorded: A total of 97,497,945 STX participated, with 97,497,945 STX (100%) voting 'Yes' and 0 STX (0%) voting 'No'.
A breakdown of the onchain vote is as follows:
-
For STX locked in stacking, a total of 86,325,407 STX participated.
- Of this, 86,325,407 STX (100%) voted 'Yes'.
- While 0 STX (0%) voted 'No'.
-
For unlocked STX, a total of 11,172,535 STX participated.
- Of this, 11,172,535 STX (100%) voted 'Yes'.
- While 0 STX (0%) voted 'No'.
Total of 67 addresses participated, a breakdown is as follows:
- Via Ballot.gg website: 32 addresses
- STX Dust Transactions: 25 addresses
- Bitcoin Address Votes: 10 addresses
The open-source Ballot.gg repository, which includes the tally process and the audit script used to process and verify the results, can be found here: https://github.com/BlockSurvey/ballot/tree/main?tab=readme-ov-file#poll-results-auditor
Reference Implementation
At the time of this writing, the following public implementations are available so far:
zadao.ai