Pillar Ownership Transfer via HTLC

Project Name: Pillar Ownership Transfer via HTLC

Description: There is no way to transfer a Pillar today. PillarInfo.StakeAddress is written once at registration and never changes, and the only exit is Revoke, which destroys the name permanently. As a result:

  • Operators who want to liquidate must destroy the asset instead of passing it on. The name and delegation base are lost.
  • The network loses Pillars it would otherwise keep, and each re-registration costs 150,000 + 10,000 × N QSR.
  • Off-chain handovers mean sharing keys, which transfers control but not ownership and leaves the buyer with no recourse.

This project specifies and implements the smallest consensus change that makes a Pillar tradeable trustlessly:

Change Caller Effect
LockOwnership(name, buyer, duration, hashType, hashLock) (new) Current owner An irrevocable, time-limited commitment: the named buyer may take this Pillar by revealing the preimage before this height
TakeOwnership(name, preimage) (new) Named buyer Reveals the preimage and takes ownership
Revoke (modified) Current owner Fails while a lock is live, so a seller can’t revoke out from under a buyer

The Pillar contract never handles value. Payment happens on the other leg of an atomic swap: on Bitcoin, or on NoM through the existing embedded.htlc contract, which already accepts any ZTS.

Why it matters for Zenon: it keeps Pillars, and their delegators, in the network when operators change, and it replaces key-sharing handovers with a trustless one.

URL: The ZIP will be published at https://zenon.zip on submission. The on-chain project will link to this forum thread.

Team:

  • sol: specification, adversarial review, implementation, testing. Also built Ferry, which already runs both legs of BTC⇄Zenon HTLC swaps.

Phases

Phase 1: ZIP submitted and accepted

High-level overview of main tasks:

  • :white_check_mark: Draft specification (Standards Track, Consensus, BSD-3-Clause) written against go-zenon at 590f43c, with every cited symbol re-checked against the source:
    • ValidateSendBlock and ReceiveBlock rules for each method
    • The state-record encoding, measured at 288 / 320 bytes and round-trip byte-identical
    • Constants and their one-way upgrade classes, errors, RPC, and spork gating
  • :white_check_mark: Four design iterations, each with a written adversarial review: an escrowed bid/ask market, ask-only v1 and v2, and the HTLC-only primitive specified here. Every rejected alternative is recorded in the ZIP’s Rationale with the reason.
  • :white_check_mark: Consensus hazards found and closed in the draft:
    • The spork diff must mutate the Pillar contract in place, or it discards the Accelerator spork’s CollectReward plasma override and halts nodes syncing from genesis.
    • The ABI re-pack must be the identity, or blocks fail on mainnet with ErrABHashInvalid while CI passes.
    • Lock checks must fail closed on storage errors.
  • :white_check_mark: The swap protocols specified normatively (BTC for a Pillar, ZNN for a Pillar), including the required leg ordering: the owner generates the secret and locks first, with the longer timelock. Reversed, a failed take publishes the preimage and one party loses everything.
  • Submit the ZIP under the ZIP-0001 process as a NIP-34 proposal against the canonical repository
  • Answer public review from core developers and revise

Completion of Phase 1 will be measured by:

  • The ZIP accepted by the ZIP maintainers into the canonical repository

Phase 2: Implementation

High-level overview of main tasks:

  • go-zenon: LockOwnership, TakeOwnership, the Revoke guard, the pillarOwnershipLock state record, constants, errors and RPC, all gated behind PillarOwnershipSpork with a placeholder id, so the release does nothing on its own
  • Tests: full per-method coverage plus the ZIP’s three required test classes:
    • a re-pack identity test at harness level
    • a plasma test across all 32 spork variants
    • a reward-attribution test
  • Devnet: pre-activation through genesis, the full suite, and end-to-end swap smoke tests on both legs (BTC for a Pillar, and ZNN for a Pillar through embedded.htlc)
  • znn_sdk_dart bindings and the swap helper, which owns secret generation, refuses the reversed ordering, and refuses to fund when the timelock margin is thin. The ZIP requires both before activation.
  • znn_cli_dart lock and take commands, showing heights as approximate times, with the take-time warnings (revoke phase, RewardWithdrawAddress, give-percentages)

Completion of Phase 2 will be measured by:

  • Pull requests opened against zenon-network/go-zenon, znn_sdk_dart and znn_cli_dart, with CI green
  • Both swap flows settled end to end on a devnet with the spork pre-activated
  • The swap helper refusing the reversed ordering and a thin margin, both demonstrated in tests

Funding

Total Requested Funding = 5,000 ZNN and 50,000 QSR
Project Duration = 2 month

How did you calculate your budget?

  • Phase 1 covers specification work already done: four design iterations and four written adversarial reviews against the go-zenon source, plus the submission and review cycle still to come.
  • Phase 2 is a consensus change with a spork diff, a new state record, a modified method, three required test classes, devnet integration, and SDK and CLI tooling. It is comparable in scope to Combined SDK and znn-cli updates (5,000 ZNN + 50,000 QSR, about 200 h), plus the consensus work.

Project and Payment Milestones:

Phase 1
Funding Request: 40% (2,000 ZNN and 20,000 QSR)
Duration: 1 month

Phase 2
Funding Request: 60% (3,000 ZNN and 30,000 QSR)
Duration: 1 month


Other Information

Risks, Assumptions, Known Issues, Dependencies:

  • Activation depends on a mechanism this project doesn’t control. Like every consensus change, this one goes live through a spork, and sporks are currently frozen. The community spork key’s window closed on 2026-04-16, and the genesis key’s whereabouts are unknown. The network’s upgrade path is being worked out through the draft governance ZIP.
    • Phase 2 is defined so it can be delivered and verified without activation: merged code behind a placeholder spork, tested on devnet, with SDK and CLI tooling ready.
    • Mainnet activation happens whenever a working mechanism exists (a new spork key, the governance contract, or a coordinated hard fork).
    • If Pillars would rather wait for that path before funding implementation, Phase 2 can be held while Phase 1 proceeds. Say so in this thread.
  • Acceptance risk. The ZIP maintainers may ask for changes, or decline. Phase 1 is paid only on acceptance.
  • Stated, not mitigated, in the ZIP:
    • Rewards go to the seller until the buyer calls UpdatePillar. The seller’s RewardWithdrawAddress keeps collecting, and both simple fixes misattribute rewards in opposite directions. Clients must show it to the buyer at take time.
    • Undecided Accelerator-Z votes transfer with the Pillar.
    • A mis-posted lock freezes a Pillar for up to 48 hours.
    • A reused hashlock is the one mistake that loses the asset, which is why the SDK owns secret generation.
  • Open items the ZIP lists for before activation: run the four-transaction same-chain flow end to end (covered by Phase 2), and check the non-Dart SDKs.

Have you previously submitted a proposal (either in Accelerator-Z or Incubator)?

Follow-up work (not requested here):

  • Syrius and Syrius-extension lock and take screens
  • Indexer and explorer support (nom-indexer, zenon.tools, zenonhub)
  • A BTC-for-Pillar flow in Ferry
  • The ZIP’s future work: an on-chain provenance record and a standing-offer layer, which would need a second spork

On-chain filing. One project with two phases, whose sum equals the project total exactly (the chain maximum per project):

Project name Project funds Phases
Pillar Ownership via HTLC 5,000 ZNN / 50,000 QSR Phase 1: 2,000 / 20,000
Phase 2: 3,000 / 30,000