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 0x0b732489dee8fd2bcb5fa37b513b2ea10edc616bd664ba5b55c69952f63e2c1b
genesis id 0xc1b21b079b3dfe781c40a187326bb8dbbcf0fb97164d6fdf7a7d6a536c74705b
state root 0x6974f84b8088039ab721fd6be6ac72b73845e5dc93f0b5625b4e9c564ccf73e3
genesis time 1789430400
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-09-15T00:00:00Z (unix 1789430400). You can watch
the chain at testnet.zycord.com.
It differs from mainnet in eight values and nowhere else#
name, chain_id, genesis_target, max_target,
genesis_time, randomx_key_interval, h1_bond and
h1_vm. The last two are the activation heights, and they are lower here on purpose:
the testnet reaches them on its first and third day, so the machine is exercised for weeks before
mainnet arrives at the same gates. Everything else —
undo_depth, target_block_seconds, coinbase_maturity, 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.
| Parameter | Public testnet | Mainnet |
|---|---|---|
name | zycord-testnet | zycord |
chain_id | 2 | 1 |
genesis_time | 1789430400 — 2026-09-15T00:00:00Z | 1790812800 — 2026-10-01T00:00:00Z |
randomx_key_interval | 512 blocks | 2048 blocks |
h1_bond | 2,880 — about day 1 | 40,320 — about day 14 |
h1_vm | 8,640 — about day 3 | 80,640 — about day 28 |
target_block_seconds | 30 — identical | |
coinbase_maturity | 100 — identical | |
epoch_length | 2880 blocks, about a day — identical | |
ttl_max | 240 blocks, about two hours — identical | |
treasury_share_bps | 300, i.e. 3% — identical | |
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-v1; 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-v1, 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 ships one seed address for this network, and nothing for any other. You do not have to find a peer before you can start — the command above joins from the built-in seed. To supply your own instead, or as well:
zycordd --testnet --dir ./testnet --peers-file peers.txt
zycordd --testnet --dir ./testnet --peers host:9421,host2:9421
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)
Start it before the network opens if you like — that is the intended way to use it. A node whose clock has not reached the earliest timestamp the next block may carry refuses to build one, says how long the wait is, and starts mining by itself when the time comes. There is nothing to schedule and nothing to restart, and it peers and syncs the whole time it waits.
The payout must be a persistent (0x02) address —
zcd wallet address prints one by default, 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.
- The pre-genesis wait, and whether an honest early start really does become an on-time start with nothing to restart.
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.