# Project Zeno

**URL:** <http://forum.zenon.org/t/project-zeno/2384>\
**Category:** Development\
**Created:** [November 1, 2026, 12:42pm UTC](http://forum.zenon.org/t/project-zeno/2384 "2026-11-01T12:42:04Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![digitalSloth](http://forum.zenon.org/user_avatar/forum.zenon.org/digitalsloth/32/3621_2.png) [@digitalSloth](http://forum.zenon.org/u/digitalSloth)\
**Post date:** [November 1, 2026, 12:42pm UTC](http://forum.zenon.org/t/project-zeno/2384/1 "2026-11-01T12:42:04Z")

</div>

## What is Zeno

Zeno brings smart contracts to Zenon without putting a virtual machine on L1. Contracts run off-chain on pillar-operated executors, and the results settle back to L1 through a new embedded contract called Settlement.

Everything is open source in the [Zeno-L2 GitHub organisation](https://github.com/Zeno-L2).

The whole design follows one rule: **Consensus orders. Executors compute. Settlement anchors.**

- **Consensus orders.** Every L2 input (a deploy, a call, a deposit) is an ordinary account-block sent to Settlement. Zenon’s momentum chain fixes its order, so there is no sequencer to run or trust, and inclusion cannot be censored by the executor.
- **Executors compute.** An executor reads the confirmed inputs from L1, runs them through a deterministic runtime, and produces a new state root, receipts, events and an outbox of withdrawals.
- **Settlement anchors.** The executor submits each batch’s commitment to Settlement. Settlement holds deposited funds in escrow, records the commitment in Zenon’s state, and releases withdrawals back to L1 accounts.

```auto
            deposits & calls ordered inputs
  +--------+ ---------------> +-------------+ ---------------> +-------------------+
  | User | | Settlement | | Executor (pillar) |
  | | <--------------- | (Zenon L1) | <--------------- | |
  +--------+ withdrawals +-------------+ batch + roots +-------------------+

```

Inputs flow right through Settlement to the executor; batch commitments and withdrawals flow back through Settlement.

Three properties come from this split:

1. **L1 stays light.** Nodes never re-run contract code. Registering an L2 result is just a state write in an embedded contract, enabled by a spork, with no momentum format change.
2. **Data availability is inherited.** Inputs live on L1, so anyone can replay a domain from L1 data alone and check the executor’s roots.
3. **Runtime-agnostic by design.** Settlement anchors _execution domains_, not a specific VM. Phase 1 ships one WASM domain; an EVM, Move or Bitcoin-verifier domain plugs in beside it without changing the base chain.

The L1 and L2 share one Merkle tree library (`common/trie`: a full-depth sparse Merkle tree over SHA3-256). One proof format and one verifier serve reads of Zenon state and reads of contract state.

Executors are pillars. Developers pay ZNN fees for deploying bytecode and buying storage; 30% is burned and 70% goes to the pillar whose batch carried the input. Contract calls stay free for users.

## Where we are: the end of Phase 1

Phase 1 is the full off-chain execution loop working end to end on a devnet, ready for testnet. It is testnet only by design: correctness rests on one registered executor, so it never activates on mainnet.

What works today:

- **Write** contracts in Rust with `cargo zeno`, and test them locally against `zeno-exec` before deploying.
- **Deploy** a WASM contract in chunks, pay its bytecode fee, and buy storage quota for it.
- **Call** it through Settlement (`CallL2`), including payable calls that move ZNN or ZTS tokens into L2.
- **Upgrade** an owner-upgradeable contract in place, or transfer its ownership.
- **Batch and settle:** the executor reads inputs from L1, executes them, and submits batch commitments that Settlement checks and records.
- **Withdraw** back to L1: contracts emit withdrawals, the executor relays them with Merkle proofs, and Settlement pays them out after the withdrawal delay.
- **Read and verify** L2 state through the gateway, with every value checked against the batch root Settlement holds.
- **Use it from a browser:** the Zeno console deploys, calls and manages contracts, signing through the web wallet.
- **Run it all locally:** one command brings up the whole system on your machine, ready to use.

**The Phase 1 trust model.** One administrator-registered pillar runs the executor. Settlement enforces aggregate solvency on-chain for each domain and asset: an executor can never pay out more than was deposited. Per-account correctness depends on that executor until Phase 2 adds validity proofs.

## The work so far, repo by repo

Phase 1 spans seven repositories: two Go repos for the chain and the executor, four client repos that let developers and users reach it, and a devnet that runs it all locally.

| Repo | Role | What we built |
| --- | --- | --- |
| [go-zenon](https://github.com/digitalSloth/go-zenon/tree/feature/settlement) | The Zenon node | The Merkle state root in every momentum header, the Settlement embedded contract, its RPC API and a devnet build |
| [zeno-executor](https://github.com/Zeno-L2/zeno-executor) | The off-chain executor | The deterministic WASM runtime, the batch pipeline, submission, withdrawals, the gateway read API and the `zeno-exec` contract runner |
| [znn-typescript-sdk](https://github.com/digitalSloth/znn-typescript-sdk/tree/feature/settlement) | Client for everything go-zenon implements | State-root proofs, an SMT verifier, and Settlement builders, readers and withdrawal helpers |
| [zeno-client-ts](https://github.com/Zeno-L2/zeno-client-ts) | Client for everything the executor defines | The L2 codec, the gateway client with proof verification, and contract interface encoding |
| [zeno-contract-sdk-rs](https://github.com/Zeno-L2/zeno-contract-sdk-rs) | Rust SDK for writing WASM contracts | The contract runtime, the `#[contract]` macros, the `cargo zeno` tool, and the counter and reference vault examples |
| [zeno-console](https://github.com/Zeno-L2/zeno-console) | The web app | One app to explore domains, batches and contracts, and to deploy, call, manage and withdraw |
| [zeno-devnet](https://github.com/Zeno-L2/zeno-devnet) | The local network | One command that runs the node, executor, gateway and console together, and end-to-end flows that test them |

### go-zenon

- **Merkle state root.** Each momentum now commits to a root over all of Zenon’s state, signed by the producing pillar. Anyone can prove “key K has value V at height H” against a header, with no trust in the node serving the proof. It powers light clients and state sync, and it is how the executor and bridges read Settlement storage. It activates with `StateRootSpork`.
- **Settlement contract.** A spork-gated embedded contract (`OffchainExecutionSpork`) built across twelve tickets: domain registry, admin and pause controls with time-locked changes, pillar executor registration and per-epoch fee settlement, deposits and escrow with an on-chain conservation check, chunked deployment, batch acceptance, withdrawal registration and release, and the `CallL2`, `UpgradeContract`, `TransferContractOwnership` and `BuyStorage` inputs.
- **Settlement RPC** (`embedded.settlement`) and a **devnet** build tag and Docker image for local testing.

### zeno-executor

The executor is a standalone Go binary that runs beside a node.

- **Generic runtime and plugin seam.** A public `domain` interface any runtime implements. Each domain runs in its own isolated worker process under a supervisor, with its own uid and memory and CPU limits where the host allows it. The submission key never reaches a worker.
- **WASM runtime.** A deterministic WebAssembly 1.0 interpreter with gas metering, a three-import host ABI, and handlers for all six input kinds. Revert data from `env.abort` is carried into the receipt.
- **State and encoding.** The L2 sparse Merkle tree on the shared `common/trie` core, and a canonical binary encoding for every consensus-visible structure.
- **Batch pipeline.** A ledger follower that reproduces L1’s canonical input order, a batch builder that computes every commitment root, crash-safe persistence with reorg rollback, and fail-closed halts on any inconsistency.
- **Submission and withdrawals.** Batches go to Settlement from the pillar’s executor address; withdrawals are proven, relayed and released automatically.
- **Gateway.** A separate read process with a JSON-RPC API: batches, receipts, events, state with proofs, deploy history, and `zeno_simulate` to dry-run a call before sending it. It serves pending and L1-verified state.
- **`zeno-exec`.** A local validator and session runner that executes contracts with the real WASM runtime, no node needed. The Rust SDK’s test harness runs on it.
- **Conformance suites** for the SMT, execution and serialization, so a second implementation can prove byte equality.

### znn-typescript-sdk

Everything go-zenon implements, available to TypeScript apps:

- Merkle state-root proofs and an SMT verifier.
- The Settlement ABI, constants and block builders for every input.
- A Settlement storage reader, the `embedded.settlement` RPC, a deploy planner, and withdrawal helpers.
- Fixtures dumped from go-zenon, so every encoding is checked for byte equality with the Go code.

### zeno-client-ts

A framework-free TypeScript package for everything the executor, gateway and runtimes define:

- The L2 codec, derivations (chain id, caller, contract id, storage keys), decoders for receipts, events and outbox messages, and input encoding.
- A gateway client that verifies every proof and batch root it receives, and labels each value as verified or pending.
- Contract interface files, the `zeno-selector-v1` encoder, and `prepareDeploy` and `prepareCall` helpers.

Neither SDK holds keys. Both build unsigned blocks or read data; signing stays with the wallet.

### zeno-contract-sdk-rs

A Rust SDK for writing Zeno WASM contracts, built to be easy for developers and coding agents alike:

- **`zeno-contract`:** a `no_std` runtime with the codec, typed storage (`Item` and `Map`) and the effects encoder.
- **`#[contract]` macros:** declare storage, methods, events and error codes in one module; the build generates the dispatch and the contract’s interface file, which the console and `zeno-client` read.
- **`cargo zeno`:** `new` scaffolds a contract, `build` produces reproducible, validated artifacts, `test` runs contract tests against `zeno-exec`, and `explain` prints the cause and fix of any error code.
- **Examples:** a counter (upgradeable to v2) and the reference vault, production-quality custody code to build DEXes, escrows and bridge pools on. The vault is also the testnet demo for deposits and withdrawals.
- **Docs for people and agents:** a step-by-step guide whose snippets are compiled and run by the test suite, API and error references, `AGENTS.md` and `llms.txt`.

### zeno-console

One Vue app for reading the network and acting on it, signing through the user’s wallet:

- **Explore:** a network dashboard, and every domain’s batches, inputs, events, outbox and contracts, with search by id or address.
- **Build:** a deploy and upgrade flow that resumes after a reload, contract call and manage tabs, a playground for trying contracts, and a send tracker from publish to finalized receipt.
- **Manage:** a withdrawals page that checks the proof before every relay, and an admin area for time-locked parameter changes.
- **Decoded by default:** calls and events decode through the contract’s interface file, matched by its code hash. Every L2 value carries a badge: Verified, Pending or Inconsistent.

### zeno-devnet

The whole system on one machine, with one command. `scripts/devnet.sh up` starts go-zenon’s devnet nodes and explorer, the executor and its gateway, and the console. It then registers the executor, configures domain 1 and fuses plasma for the test accounts, so the devnet is ready to use when the command returns.

- **Pinned or local.** By default it runs the commits pinned in `sources.txt`, so a fresh clone works on its own. Developers working on Zeno itself point it at their own checkouts instead.
- **End-to-end flows.** Ten scripted flows exercise the system against the running devnet: chunked deploys and storage quota, deposits, payable calls with refunds, withdrawals, force inclusion while the executor is stopped, a crashed worker, a crashed executor, handing a domain to a second executor and back, pauses, and fee settlement.
- **Checked at every step.** Each flow verifies every receipt against the batch Settlement accepted, and re-checks after every step that Settlement has never released more than was deposited.

It is the quickest way to try Zeno before testnet opens, and the place to start stress testing.

### Supporting work

- **nom-ui** gained the components the console needed: a stepper, hex view, file dropzone, empty state and description item.
- **nom-webwallet** gained an injected dapp provider and WalletConnect with an approval flow, so the console signs through the user’s wallet and never touches keys.

## What’s next: Phase 2, validity proofs on mainnet

Phase 2 takes Zeno to mainnet by proving every batch correct before Settlement accepts it. No executor, committee or watcher is trusted for correctness; the proof is.

| | Phase 1 | Phase 2 |
| --- | --- | --- |
| Network | Testnet only | Mainnet |
| Correctness rests on | The registered executor | A zero-knowledge validity proof per batch |
| Finality | After a withdrawal delay | When Settlement verifies the proof |
| Executors | One administrator-registered pillar | A set of pillars, round-robin per epoch |

There is no optimistic, fraud-proof phase in between. That removes the dispute game, the replay referee, watchers, challenger payouts and slashing from the plan entirely.

**What Phase 2 brings:**

- **Trustless execution.** Settlement verifies one SNARK per batch against the domain’s verifying key. An invalid state transition cannot be accepted.
- **Still no VM on L1.** Settlement verifies proofs and never runs WASM, EVM or any other runtime. Adding a runtime means adding a proving program and registering its key, with no Settlement code change.
- **Faster, simpler withdrawals.** Accepting a batch makes it final, so the withdrawal delay is no longer a safety mechanism and the relay-then-release two-step goes away.
- **Liveness without trust.** A round-robin primary executor per epoch, a fallback that lets any registered executor submit if the primary stalls, and then anyone with a valid proof. This replaces the escape hatch.
- **A path to new runtimes and bridges.** The same proving stack opens the way for an EVM runtime and a ZK-verified Ethereum bridge.

**How it will be built.** The executor shell stays in Go. The state transition moves into one Rust crate (codec, Merkle tree, WASM interpreter) that runs natively in the executor and inside a zkVM guest, so what runs and what is proven are the same code.

**Research comes first.** Before the build starts, we need measured answers to:

1. Which zkVM to use (SP1, RISC Zero or others).
2. What proving WASM execution costs, per gas unit and per worst-case batch.
3. Whether an embedded contract can verify a SNARK within Zenon’s 16 KiB block limit and at a sane plasma price.
4. Who pays for proving, and at what fee level it breaks even.
5. Whether SHA3-256 stays as the tree hash or migrates to a ZK-friendly hash before mainnet.

If proving every batch turns out too expensive, the fallback is _prove on challenge_: batches are accepted optimistically and a validity proof is demanded only when someone challenges. It reuses the same crate, zkVM and verifier, with no bisection game.

Mainnet starts from a fresh genesis; no Phase 1 testnet state carries over.

## How to get involved

Testnet is where Phase 1 meets the community. Anyone can help, in whatever way suits them:

- **Run the devnet.** Bring up a local devnet with [zeno-devnet](https://github.com/Zeno-L2/zeno-devnet), run an executor against it, and tell us where setup is unclear or breaks.
- **Stress test the system.** Push batches, deposits, withdrawals and upgrades hard, and look for the edge cases we missed.
- **Experiment with Rust contracts.** Scaffold a contract with `cargo zeno`, starting from the counter and reference vault examples, and build something of your own.
- **Review the Phase 1 code and specification.** Every consensus encoding has conformance vectors, so you can run independent checks against them.
- **Give feedback on the Phase 2 plan.** Tell us what is missing, what is wrong, and what you would change.
- **Research the open questions.** Phase 2 brings ZK validity proofs and mainnet, and several design questions are still open. Researchers who want to take one on are especially welcome.

The specification, architecture notes and bridge guide live in the [zeno-docs](https://github.com/Zeno-L2/zeno-docs) repo. Questions and feedback are welcome in this thread.

---

<div class="post-metadata">

**Author:** ![sultanofstaking](http://forum.zenon.org/user_avatar/forum.zenon.org/sultanofstaking/32/245_2.png) [@sultanofstaking](http://forum.zenon.org/u/sultanofstaking)\
**Post date:** [November 3, 2026, 1:19am UTC](http://forum.zenon.org/t/project-zeno/2384/2 "2026-11-03T01:19:41Z")

</div>

Thanks for putting this out, digitalSloth. We ran the Phase 1 devnet and the deploy-quota flow passed cleanly. It’s light too, about 480 MB RAM and under 5% CPU, so it sits fine next to a node.

Two notes from a pillar operator’s view:

1. The devnet’s default rpc ports (35997/35998) are the same ones znnd uses, so on a box already running a node it won’t start until you move them. A config option or a line in the README would save people some head-scratching.
2. The executor container runs privileged. We ran Docker rootless to contain it, but will the testnet or mainnet executor need privileged mode? Pillars will be careful about that.

Looking forward to the testnet and happy to help test executors when it opens. -SoS
