Skip to main content

Contracts Overview

The on-chain protocol (packages/contracts) is immutable — no admin, no proxy, no upgrade path. A change means a new deployment. State authority lives entirely in the Orchestrator and tokens live in the Vault.

The pieces

Contract / libraryRolePage
OrchestratorThe entry points (deposit, transact), all validation, and settlement. Holds the commitment tree + nullifier set in an ERC-7201 slot.Orchestrator
VaultPure custodian: holds every token, never calls untrusted code, skims the protocol fee on deposit.Vault
CommitmentTreeLib / LeanIMTThe sequence of depth-16 binary Lean IMTs, root history, and the spent-nullifier set.Commitment Tree
AppAccountEIP-7702 per-app execution account for the public route.App Account
PqPubkeyRegistryWrite-once registry mapping a BJJ transmission key to an ML-KEM-768 public key.PQ Registry
FinalizeHonkVerifierBarretenberg-generated UltraHonk verifier, wrapped by IFinalizeVerifier.Finalize

Trust and immutability

  • No admin. There is no owner, no pause, no upgrade. The only privileged relationships are the onlyOrchestrator modifier on the Vault/AppAccount and the onlySelf modifier guarding executeAction.
  • Vault migration invalidates pre-signed actions. The AppAccount action digest binds address(VAULT), so a (hypothetical) new deployment with a new Vault cannot replay old signatures.

EncodedAsset packing

Assets are identified by two 256-bit fields used everywhere (calldata, circuit, commitments):

encodedAssetAddress:
bits 0–159 : token contract address
bits 160–161 : AssetType (0 = ERC20, 1 = ERC721, 2 = ERC1155)
bits 250–252 : upper 3 bits of a token id
encodedAssetId : the lower 253 bits of the token id

The circuit binds (encodedAssetAddress, encodedAssetId) across all four notes of an Action, and the contract asserts a bundle is asset-uniform — together these stop a spend from silently changing assets. The Vault today is ERC-20 only (_token reverts unless the type field is 0); the encoding reserves room for NFTs.