Skip to content

force deploys to latest Clarity; reserved-name defines for legacy trait implementations - #7404

Draft
francesco-stacks wants to merge 4 commits into
stacks-network:pox-wf-integrationfrom
francesco-stacks:clarity6-force-latest
Draft

force deploys to latest Clarity; reserved-name defines for legacy trait implementations#7404
francesco-stacks wants to merge 4 commits into
stacks-network:pox-wf-integrationfrom
francesco-stacks:clarity6-force-latest

Conversation

@francesco-stacks

@francesco-stacks francesco-stacks commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Description

NOTE: Not intended to be shipped with Clarity 6 / Epoch 4.0 itself. (but it would have been nice :P ) Changing which Clarity versions are deployable is a consensus-rules change that will likely require its own SIP. The PR is for early feedback and review.

From Epoch 4.0, new contract deploys are forced to the latest Clarity version. Two changes make thi safe and enforce it:

1. Deploy version enforcement (consensus rule)

process_transaction_precheck now rejects a versioned smart-contract deploy that pins a Clarity version older than the epoch default, from Epoch 4.0 on (pinning a newer version was already rejected). Unversioned deploys resolve to the epoch default as before, which at Epoch 4.0 is Clarity 6. Already-deployed contracts keep running at their pinned version. The check runs in the shared precheck path, so it applies identically to mempool admission and block validation: a block containing such a deploy is invalid.

2. Clarity 6: reserved-name defines for legacy trait implementations

Each Clarity version reserves names that used to be free (slice? since Clarity 2, stacks-block-height since Clarity 3, current-contract since Clarity 4, …). Traits deployed before those reservations may declare methods under such names - without this change, those traits would be unimplementable at the latest version, and force-latest would break interoperability with older contracts that define such methods.

From Clarity 6, a public or read-only function may be defined under such a name, but only to implement a matching method of an implemented (impl-trait) trait deployed while the name was still free. Everything else is unchanged:

  • A bare reference inside the contract still resolves to the native; the function is reachable only by literal-name lookup (contract-call?, static or dynamic, and trait dispatch).
  • Private functions are excluded (only reachable by bare name, which the native always wins).
  • define-trait now rejects currently-reserved method names, so no new trait can ever make a reserved name implementable - only traits that predate the reservation can.

Validation mechanics (consensus-sensitive details)

The check runs after contract initialization (validate_shadowable_reserved_definitions), so define/impl-trait ordering doesn't matter, and it is a no-op unless the contract actually defines a reserved name. When it runs, implemented traits are consulted in sorted order (deterministic across nodes), each trait-defining contract load is priced like any contract load (LoadContract cost + memory, mirroring inner_execute_contract), and loading stops as soon as every name is matched. Analysis is intentionally unchanged: like reserved names generally, this is enforced at initialization only, and trait compliance (signature match) is still enforced by the existing analysis pass.

Applicable issues

Additional info (benefits, drawbacks, caveats)

Checklist

  • Test coverage for new or modified code paths
  • For new Clarity features or consensus changes, add property tests (see docs/property-testing.md)
  • Changelog fragment(s) or "no changelog" label added (see changelog.d/README.md)
  • Required documentation changes (e.g., rpc/openapi.yaml for RPC endpoints, event-dispatcher.md for new events)
  • New clarity functions have corresponding PR in clarity-benchmarking repo

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR proposes a consensus-rule change for Epoch 4.0 that forces new smart-contract deploys to use the epoch-default (latest) Clarity version, while adding Clarity 6 VM support for defining certain previously-reserved native names only when required to implement legacy trait methods (keeping older traits interoperable under “force-latest”).

Changes:

  • Enforce (in process_transaction_precheck) that from Epoch 4.0, version-pinned contract deploys cannot pin a Clarity version older than the epoch default.
  • Add Clarity 6 initialization-time validation that allows public/read-only function defines under “shadowable reserved” names only when they match methods from legacy (pre-reservation) implemented traits; and prevent new traits from declaring currently-reserved method names.
  • Add/adjust extensive unit tests across chainstate + VM analysis/runtime suites, plus changelog fragments for both behaviors.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
File Description
stackslib/src/chainstate/tests/runtime_analysis_tests.rs Updates runtime error variant coverage mapping to include the new Clarity 6 reserved-name behavior test.
stackslib/src/chainstate/tests/consensus.rs Updates Epoch 4.0 deployable Clarity version list to only include the latest version.
stackslib/src/chainstate/tests/consensus_unit_tests.rs Adds consensus-level tests for Epoch 4.0 deploy version enforcement and Clarity 6 legacy-trait reserved-name interop.
stackslib/src/chainstate/stacks/db/transactions.rs Factors deploy Clarity version validation into a helper and enforces “force-latest” from Epoch 4.0; adds precheck tests.
clarity/src/vm/tests/variables.rs Makes initialization/runtime expectation checking stricter and clarifies test contract naming.
clarity/src/vm/tests/contracts.rs Adds an extensive Clarity 6 test suite covering shadowable reserved names, trait matching, determinism, and edge cases.
clarity/src/vm/mod.rs Introduces is_shadowable_reserved and initialization-time validate_shadowable_reserved_definitions with deterministic trait-loading and costing.
clarity/src/vm/functions/define.rs Allows Clarity 6 public/read-only defines for shadowable reserved names (deferred validation), and rejects reserved method names in define-trait from Clarity 6.
clarity/src/vm/contexts.rs Adds is_name_defined_by_contract and refactors is_name_used to support the reserved-name shadowing rule cleanly.
clarity/src/vm/analysis/tests/mod.rs Adds analysis tests ensuring bare references keep resolving to natives even when shadowed functions exist.
changelog.d/epoch-4-force-latest-clarity.changed Changelog entry for Epoch 4.0 deploy version enforcement.
changelog.d/clarity6-reserved-name-trait-impls.added Changelog entry for Clarity 6 reserved-name defines for legacy trait implementations + new trait restrictions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@hstove-stacks hstove-stacks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM, but you'll have to update snapshots

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants