API Reference

Ownable API

This module provides the full Ownable module API.

For an overview of the module, read the Ownable guide.

import "./node_modules/@openzeppelin/compact-contracts/access/Ownable";

Ledger

_owner: Either<Bytes<32>, ContractAddress>

ledger

#

Either a Bytes<32> account identifier or ContractAddress representing the owner.

Witnesses

wit_OwnableSK() → Bytes<32>

witness

#

Returns the caller's secret key used in deriving the account identifier.

The same key produces the same account identifier across all contracts. Users who desire cross-contract unlinkability should use different keys per contract.

Circuits

initialize(initialOwner: Either<Bytes<32>, ContractAddress>) → []

circuit

#

Initializes the contract by setting the initialOwner. This must be called in the contract's constructor.

Requirements:

  • Contract is not already initialized.
  • initialOwner is not a ContractAddress.
  • initialOwner is not the zero address.
k=10, rows=626

owner() → Either<Bytes<32>, ContractAddress>

circuit

#

Returns the current contract owner.

Requirements:

  • Contract is initialized.
k=7, rows=76

transferOwnership(newOwner: Either<Bytes<32>, ContractAddress>) → []

circuit

#

Transfers ownership of the contract to newOwner.

Ownership transfers to contract addresses are currently disallowed until contract-to-contract interactions are supported in Compact. This restriction prevents permanently disabling access to a circuit.

Requirements:

  • Contract is initialized.
  • The caller is the current contract owner.
  • newOwner is not a ContractAddress.
  • newOwner is not the zero address.
k=13, rows=2959

_unsafeTransferOwnership(newOwner: Either<Bytes<32>, ContractAddress>) → []

circuit

#

Unsafe variant of transferOwnership.

Ownership transfers to contract addresses are considered unsafe because contract-to-contract calls are not currently supported. Ownership privileges sent to a contract address may become uncallable. Once contract-to-contract calls are supported, this circuit may be deprecated.

Requirements:

  • Contract is initialized.
  • The caller is the current contract owner.
  • newOwner is not the zero address.
k=13, rows=2956

renounceOwnership() → []

circuit

#

Leaves the contract without an owner. It will not be possible to call assertOnlyOwner circuits anymore. Can only be called by the current owner.

Requirements:

  • Contract is initialized.
  • The caller is the current contract owner.
k=13, rows=2364

assertOnlyOwner() → []

circuit

#

Throws if called by any account other than the owner. Use this to restrict access of specific circuits to the owner. The caller's identity is derived from the wit_OwnableSK witness as persistentHash(secretKey).

Requirements:

  • Contract is initialized.
  • The caller is the current contract owner.
k=13, rows=2360

_transferOwnership(newOwner: Either<Bytes<32>, ContractAddress>) → []

circuit

#

Transfers ownership of the contract to a newOwner without enforcing permission checks on the caller.

Ownership transfers to contract addresses are currently disallowed until contract-to-contract interactions are supported in Compact. This restriction prevents circuits from being inadvertently locked in contracts.

Requirements:

  • Contract is initialized.
  • newOwner is not a ContractAddress.
k=10, rows=600

_unsafeUncheckedTransferOwnership(newOwner: Either<Bytes<32>, ContractAddress>) → []

circuit

#

Unsafe variant of _transferOwnership.

Ownership transfers to contract addresses are considered unsafe because contract-to-contract calls are not currently supported. Ownership privileges sent to a contract address may become uncallable. Once contract-to-contract calls are supported, this circuit may be deprecated.

Requirements:

  • Contract is initialized.
k=10, rows=597

_computeAccountId() → Bytes<32>

internal

#

Computes the caller's account identifier from the wit_OwnableSK witness.

ID Derivation: accountId = persistentHash(secretKey)

The result is a 32-byte commitment that uniquely identifies the caller.

computeAccountId(secretKey: Bytes<32>) → Bytes<32>

pure

#

Computes an account identifier without on-chain state, allowing a user to derive their identity commitment before submitting it in an ownership transfer. This is the off-chain counterpart to the internal _computeAccountId and produces an identical result given the same inputs.

ID Derivation: accountId = persistentHash(secretKey)

The secretKey parameter is a sensitive secret. Mishandling it can permanently compromise the security of this system. Never log or persist the key in plaintext. Use cryptographically secure randomness to generate keys. Treat key loss as identity loss. A lost key cannot be recovered.


import "./node_modules/@openzeppelin/compact-contracts/access/ZOwnablePK";

Ledger

_ownerCommitment: Bytes<32>

ledger

#

Stores the current hashed commitment representing the owner. This commitment is derived from the public identifier (e.g., SHA256(pk, nonce)), the instanceSalt, the transfer counter, and a domain separator.

A commitment of default<Bytes<32>> (i.e. zero) indicates the contract is unowned.

_counter: Counter

ledger

#

Internal transfer counter used to prevent commitment reuse.

Increments by 1 on every successful ownership transfer. Combined with id and instanceSalt to compute unique owner commitments over time.

_instanceSalt: Bytes<32>

sealed ledger

#

A per-instance value provided at initialization used to namespace commitments for this contract instance.

This salt prevents commitment collisions across contracts that might otherwise use the same owner identifiers or domain parameters. It is immutable after initialization.

Witnesses

wit_secretNonce(): Bytes<32>

witness

#

A private per-user nonce used in deriving the shielded owner identifier.

Combined with the user's public key as SHA256(pk, nonce) to produce an obfuscated, unlinkable identity commitment. Users are encouraged to rotate this value on ownership changes.

Circuits

initialize(ownerId: Bytes<32>, instanceSalt: Bytes<32>): []

circuit

#

Initializes the contract by setting the initial owner via ownerId and storing the instanceSalt that acts as a privacy additive for preventing duplicate commitments among other contracts implementing ZOwnablePK.

The ownerId must be calculated prior to contract deployment using the SHA256 hashing algorithm. Using any other algorithm will result in a permanent loss of contract access. See _computeOwnerId.

Requirements:

  • Contract is not initialized.
  • ownerId is not zero.
k=14, rows=14933

owner(): Bytes<32>

circuit

#

Returns the current commitment representing the contract owner. The full commitment is: SHA256(SHA256(pk, nonce), instanceSalt, counter, domain).

Requirements:

  • Contract is initialized.
k=10, rows=57

transferOwnership(newOwnerId: Bytes<32>): []

circuit

#

Transfers ownership to newOwnerId. newOwnerId must be precalculated and given to the current owner off chain.

Requirements:

  • Contract is initialized.
  • Caller is the current owner.
  • newOwnerId is not an empty array.
k=16, rows=39240

renounceOwnership(): []

circuit

#

Leaves the contract without an owner. It will not be possible to call assertOnlyOwner circuits anymore. Can only be called by the current owner.

Requirements:

  • Contract is initialized.
  • Caller is the current owner.
k=15, rows=24442

assertOnlyOwner(): []

circuit

#

Throws if called by any account whose id hash SHA256(pk, nonce) does not match the stored owner commitment. Use this to only allow the owner to call specific circuits.

Requirements:

  • Contract is initialized.
  • Caller's id (SHA256(pk, nonce)) when used in _computeOwnerCommitment equals the stored _ownerCommitment.
k=15, rows=24437

_computeOwnerCommitment(id: Bytes<32>, counter: Uint<64>): Bytes<32>

circuit

#

Computes the owner commitment from the given id and counter.

The commitment derivation follows: commitment = SHA256(id, instanceSalt, counter, "ZOwnablePK:shield:")

Where:

  • id: The unique identifier SHA256(pk, nonce).
  • instanceSalt: Per-deployment salt to prevent collisions.
  • counter: Incremented with each transfer for uniqueness. Cast to Field then Bytes<32> for hashing.
  • Domain separator: "ZOwnablePK:shield:" padded to 32 bytes.

Requirements:

  • Contract is initialized.
k=14, rows=14853

_computeOwnerId(pk: Either<ZswapCoinPublicKey, ContractAddress>, nonce: Bytes<32>): Bytes<32>

pure

#

Computes the unique identifier (id) of the owner from their public key and a secret nonce.

The ID derivation follows: id = SHA256(pk, nonce)

Currently only supports ZswapCoinPublicKey. Contract address owners are not yet supported.

Requirements:

  • pk is not a ContractAddress.

_transferOwnership(newOwnerId: Bytes<32>): []

circuit

#

Transfers ownership to owner id newOwnerId without enforcing permission checks on the caller.

This is an internal function that increments the counter and updates the owner commitment.

Requirements:

  • Contract is initialized.
k=14, rows=14823

_isTargetZero(target: Either<Bytes<32>, ContractAddress>) → Boolean

internal

#

Returns true if target's active branch (as indicated by is_left) holds the zero value.