ZYCORD docs
English
ZycordDocsPublic testnet

Public testnet

The public testnet carries mainnet's consensus rules under its own chain id, so what it measures is mainnet's behaviour and not its own. Its coins are worth nothing and are meant to be.

What it is#

zcd genesis --testnet
network        zycord-testnet
chain id       2
params hash    0xc4a670f04575ac3aa6e670888e1a42ec877779fda8e5519e2637f4df93815b57
launch commit  0x83aeb709b14b43a0296666f006d99378049064f3e30d8191e074e09d485e2ff7
genesis id     0x81094507a4a083d01e24af21bddbf4d7eb496472a69c4b5dfb0d7a27c6b03b55
state root     0x4f45e604e1fd7ccf066e20e5fd41105373a0ba0d28aea8fc825b8795e880384f
genesis time   1791158400
cells written  6
allocations    0

Run that command before you trust this page. A build that prints a different genesis id is a build on a different chain, and it will not connect to this one — the handshake refuses before a block is evaluated. allocations 0 is the premine claim, checkable rather than promised.

Genesis was 2026-10-05T00:00:00Z (unix 1791158400), two days before mainnet's: the testnet rehearsed the launch with the same binary and the same procedure. It is now where Era 1 runs first — the cEVM, sequencers, intents and fills, the directory and the forced path have been active here since height 2,880, its first day, while mainnet reaches the same gate at height 80,640. You can watch the chain at testnet.zycord.com.

It differs from mainnet in ten values and nowhere else#

name, chain_id, genesis_target, max_target, genesis_time, randomx_key_interval, h1_bond, h1_vm, coinbase_maturity and launch_commit. The activation heights are lower here on purpose: the testnet reached them on its first day, so the machine is exercised for weeks before mainnet arrives at the same gate. h1_bond moves with h1_vm and opens nothing on either network: bonding is not part of Era 1. The launch commitment is the testnet's own, so its block 1 rehearses mainnet's launch without revealing mainnet's. Everything else — undo_depth, target_block_seconds, the subsidy split, and the whole gas schedule — is mainnet's on purpose. The gas schedule especially, because it is what makes the base-fee behaviour measured here mainnet's rather than this network's own. A testnet on its own gas schedule measures a different chain.

ParameterPublic testnetMainnet
namezycord-testnetzycord
chain_id21
genesis_time1791158400 — 2026-10-05T00:00:00Z1791331200 — 2026-10-07T00:00:00Z
randomx_key_interval512 blocks2048 blocks
h1_bond, h1_vm2,880 — about day 180,640 — about day 28
coinbase_maturity100 blocks240 blocks
target_block_seconds30 — identical
epoch_length2880 blocks, about a day — identical
ttl_max240 blocks, about two hours — identical
emission_ramp_blocks86,400, the 30-day reward ramp — identical
founder_share, treasury_share_bps94% miner, 3% founder until 3,153,600, 3% treasury — identical
Delete your data directory before joining a reset network

A testnet may be reset from genesis. When it is, its coins, its history and its peer lists are gone, the network takes a fresh chain id, and a data directory holding the old chain is refused at startup rather than silently mixed. The two networks also disconnect at the handshake, so nothing carries over quietly.

Joining#

make build-randomx        # the testnet is randomx-v2; see below
                          #   -> bin/zcd-randomx, bin/zycordd-randomx

./bin/zycordd-randomx --testnet --dir ./testnet

make build-randomx, not make build. The testnet's pow_engine is randomx-v2, the same work function as mainnet. A binary built without the tag refuses to start against it rather than falling back to the development engine, which would accept a single BLAKE3 pass as proof of work for every header it ever saw.

The tagged binaries carry the tag in their names, so that building both leaves both on disk and the file name says which engine is inside it. Elsewhere on these pages the commands are written zcd and zycordd for brevity; on this network those are the -randomx pair.

Bootstrap#

The binary carries the testnet's seeds: seed1.zycord.com to seed4.zycord.com on port 19421. Mainnet's seeds are the same hosts on 9421, and the two networks refuse each other at the handshake, so nothing mixes. An older binary that names testnet.zycord.com as its seed should be replaced rather than worked around. To supply other peers instead, or as well:

zycordd --testnet --dir ./testnet --peers-file peers.txt
zycordd --testnet --dir ./testnet --peers host:19421,otherhost:19421
zycordd --testnet --dir ./testnet --no-seeds --peers-file peers.txt

Be dialable if you can#

Zycord does not do NAT traversal. A node with --listen on a reachable port is somewhere others can bootstrap from, and the share of such nodes is the falsifiable condition the whole no-traversal decision rests on — it is measured, not assumed.

zycordd --testnet --dir ./testnet \
  --listen 0.0.0.0:9421 --advertise <public-address>:9421

If you cannot forward a port, leave --listen off and be periphery. That is a perfectly good way to participate. Check which you are with curl -s localhost:9420/network — listening: true with inbound: 0 after a few minutes means the port is not actually reachable.

Getting coins#

Two routes, and the second is the one this network was designed around.

The faucet#

The testnet explorer runs one. It pays a small amount to any address you give it, so that a send, a refund and a sweep can be rehearsed without allocating two gibibytes to RandomX first. What it is and why it is built that way is a page of its own.

It exists on this network and on no other. The faucet is a feature of the explorer that is off by default, and enabling it requires naming a network — a name checked against the chain that explorer is actually indexing, with mainnet refused outright. Mainnet has no faucet and no premine, and that is a check in the binary rather than a policy somebody has to remember.

Nothing is minted for it. The faucet holds an ordinary key, signs an ordinary transfer through the same wallet/session the command line uses, and pays one claim per block because a certificate carries the state it read and two built against one reading of its cell would race. Its balance comes from mining, so an empty faucet stays empty until somebody refills it.

Self-mining#

The route with no queue and no operator, and the same distribution mainnet gets:

zcd wallet new --out miner.json
zycordd --testnet --dir ./testnet \
  --mine --payout $(zcd wallet address --key miner.json | awk '/^persistent/ {print $3}')

The payout must be a persistent (0x02) address — the persistent line of zcd wallet address, which prints the next one-shot address too — and zycordd refuses anything else rather than warning. Why.

coinbase_maturity is 100, so for roughly the first hundred blocks after your first reward only miners can transact. That ramp is mainnet's and is part of what this network is rehearsing — and it is the reason the faucet exists here and cannot exist there: the faucet shortens the ramp for someone who wants to exercise a wallet, on the one network where shortening it costs nothing.

Mining allocates the RandomX dataset — about 2 GiB, plus ~256 MiB per key epoch held. A machine that can verify comfortably cannot necessarily mine; the budgets are under Mining.

The testnet coins are worth nothing#

By design, and permanently. The network can be reset from genesis, which is what a testnet is for. Anyone offering to buy or sell them is running a scam that does not even need a story.

What this network is measuring#

It is not a demo. Four things it exists to produce numbers for:

  • The key-change pause. At 512 blocks the RandomX re-key lands roughly every four hours instead of mainnet's seventeen, so the dataset rebuild is rehearsed often enough to measure rather than theorise about.
  • Base-fee behaviour under the mainnet gas schedule, which is why the schedule is not adjusted here.
  • The share of dialable nodes, which is the first reopen condition on the no-NAT-traversal decision.
  • Era 1 under real load: sequencers, fills and the forced path on a live network, weeks before mainnet reaches its gate.

When something looks wrong#

Running a node has the diagnosis path for a node that will not sync, and the repair command for a data directory it refuses to start against. Findings and reproductions belong in the issue tracker; the project would rather have the report than the benefit of the doubt.